Pre-ansification changes for lib/pcc
authorNick Downing <downing.nick@gmail.com>
Fri, 3 Feb 2017 11:02:49 +0000 (22:02 +1100)
committerNick Downing <downing.nick@gmail.com>
Fri, 3 Feb 2017 12:56:30 +0000 (23:56 +1100)
265 files changed:
doc/7thEdMan/Rv7man [new file with mode: 0644]
doc/7thEdMan/bswv7.html [new file with mode: 0644]
doc/7thEdMan/index.html [new file with mode: 0644]
doc/7thEdMan/tmac.an [new file with mode: 0644]
doc/7thEdMan/tmac.s [new file with mode: 0644]
doc/7thEdMan/tmac.scover [new file with mode: 0644]
doc/7thEdMan/tmac.sdisp [new file with mode: 0644]
doc/7thEdMan/tmac.skeep [new file with mode: 0644]
doc/7thEdMan/tmac.srefs [new file with mode: 0644]
doc/7thEdMan/v7vol1.pdf [new file with mode: 0644]
doc/7thEdMan/v7vol2a.pdf [new file with mode: 0644]
doc/7thEdMan/v7vol2b.pdf [new file with mode: 0644]
doc/7thEdMan/vol1/man0.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man1.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man2.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man3.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man4.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man5.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man6.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man7.bun [new file with mode: 0644]
doc/7thEdMan/vol1/man8.bun [new file with mode: 0644]
doc/7thEdMan/vol2/README [new file with mode: 0644]
doc/7thEdMan/vol2/adb.bun [new file with mode: 0644]
doc/7thEdMan/vol2/adv.ed.bun [new file with mode: 0644]
doc/7thEdMan/vol2/assembler [new file with mode: 0644]
doc/7thEdMan/vol2/awk [new file with mode: 0644]
doc/7thEdMan/vol2/bc [new file with mode: 0644]
doc/7thEdMan/vol2/beginners.bun [new file with mode: 0644]
doc/7thEdMan/vol2/cacm.bun [new file with mode: 0644]
doc/7thEdMan/vol2/cman [new file with mode: 0644]
doc/7thEdMan/vol2/ctour.bun [new file with mode: 0644]
doc/7thEdMan/vol2/dc [new file with mode: 0644]
doc/7thEdMan/vol2/edtut.bun [new file with mode: 0644]
doc/7thEdMan/vol2/eqn.bun [new file with mode: 0644]
doc/7thEdMan/vol2/f77 [new file with mode: 0644]
doc/7thEdMan/vol2/implement [new file with mode: 0644]
doc/7thEdMan/vol2/index [new file with mode: 0644]
doc/7thEdMan/vol2/iosys [new file with mode: 0644]
doc/7thEdMan/vol2/learn.bun [new file with mode: 0644]
doc/7thEdMan/vol2/lex [new file with mode: 0644]
doc/7thEdMan/vol2/lint [new file with mode: 0644]
doc/7thEdMan/vol2/m4 [new file with mode: 0644]
doc/7thEdMan/vol2/make [new file with mode: 0644]
doc/7thEdMan/vol2/msmacros.bun [new file with mode: 0644]
doc/7thEdMan/vol2/password [new file with mode: 0644]
doc/7thEdMan/vol2/porttour.bun [new file with mode: 0644]
doc/7thEdMan/vol2/ratfor.bun [new file with mode: 0644]
doc/7thEdMan/vol2/refer.bun [new file with mode: 0644]
doc/7thEdMan/vol2/regen [new file with mode: 0644]
doc/7thEdMan/vol2/run [new file with mode: 0644]
doc/7thEdMan/vol2/security [new file with mode: 0644]
doc/7thEdMan/vol2/sed [new file with mode: 0644]
doc/7thEdMan/vol2/setup [new file with mode: 0644]
doc/7thEdMan/vol2/shell.bun [new file with mode: 0644]
doc/7thEdMan/vol2/summary.bun [new file with mode: 0644]
doc/7thEdMan/vol2/tbl [new file with mode: 0644]
doc/7thEdMan/vol2/troff.bun [new file with mode: 0644]
doc/7thEdMan/vol2/trofftut.bun [new file with mode: 0644]
doc/7thEdMan/vol2/uprog.bun [new file with mode: 0644]
doc/7thEdMan/vol2/uucp.bun [new file with mode: 0644]
doc/7thEdMan/vol2/yacc.bun [new file with mode: 0644]
doc/tack/6500.html [new file with mode: 0644]
doc/tack/6500.pdf [new file with mode: 0644]
doc/tack/LLgen.html [new file with mode: 0644]
doc/tack/LLgen.pdf [new file with mode: 0644]
doc/tack/The Amsterdam Compiler Kit.pdf [new file with mode: 0644]
doc/tack/ack.html [new file with mode: 0644]
doc/tack/ack.pdf [new file with mode: 0644]
doc/tack/ansi_C.html [new file with mode: 0644]
doc/tack/ansi_C.pdf [new file with mode: 0644]
doc/tack/basic.html [new file with mode: 0644]
doc/tack/basic.pdf [new file with mode: 0644]
doc/tack/ceg.html [new file with mode: 0644]
doc/tack/ceg.pdf [new file with mode: 0644]
doc/tack/cg.html [new file with mode: 0644]
doc/tack/cg.pdf [new file with mode: 0644]
doc/tack/crefman.html [new file with mode: 0644]
doc/tack/crefman.pdf [new file with mode: 0644]
doc/tack/ego.html [new file with mode: 0644]
doc/tack/ego.pdf [new file with mode: 0644]
doc/tack/em.html [new file with mode: 0644]
doc/tack/em.pdf [new file with mode: 0644]
doc/tack/grohtml-100191.png [new file with mode: 0644]
doc/tack/grohtml-100601.png [new file with mode: 0644]
doc/tack/grohtml-100602.png [new file with mode: 0644]
doc/tack/grohtml-101091.png [new file with mode: 0644]
doc/tack/grohtml-101092.png [new file with mode: 0644]
doc/tack/grohtml-101093.png [new file with mode: 0644]
doc/tack/grohtml-101094.png [new file with mode: 0644]
doc/tack/grohtml-101481.png [new file with mode: 0644]
doc/tack/grohtml-101482.png [new file with mode: 0644]
doc/tack/grohtml-101483.png [new file with mode: 0644]
doc/tack/grohtml-101484.png [new file with mode: 0644]
doc/tack/grohtml-101485.png [new file with mode: 0644]
doc/tack/grohtml-101486.png [new file with mode: 0644]
doc/tack/grohtml-101487.png [new file with mode: 0644]
doc/tack/grohtml-101488.png [new file with mode: 0644]
doc/tack/grohtml-101489.png [new file with mode: 0644]
doc/tack/grohtml-102111.png [new file with mode: 0644]
doc/tack/grohtml-102411.png [new file with mode: 0644]
doc/tack/grohtml-102412.png [new file with mode: 0644]
doc/tack/grohtml-102413.png [new file with mode: 0644]
doc/tack/grohtml-102721.png [new file with mode: 0644]
doc/tack/grohtml-1027210.png [new file with mode: 0644]
doc/tack/grohtml-1027211.png [new file with mode: 0644]
doc/tack/grohtml-1027212.png [new file with mode: 0644]
doc/tack/grohtml-1027213.png [new file with mode: 0644]
doc/tack/grohtml-1027214.png [new file with mode: 0644]
doc/tack/grohtml-1027215.png [new file with mode: 0644]
doc/tack/grohtml-1027216.png [new file with mode: 0644]
doc/tack/grohtml-1027217.png [new file with mode: 0644]
doc/tack/grohtml-1027218.png [new file with mode: 0644]
doc/tack/grohtml-1027219.png [new file with mode: 0644]
doc/tack/grohtml-102722.png [new file with mode: 0644]
doc/tack/grohtml-1027220.png [new file with mode: 0644]
doc/tack/grohtml-1027221.png [new file with mode: 0644]
doc/tack/grohtml-1027222.png [new file with mode: 0644]
doc/tack/grohtml-1027223.png [new file with mode: 0644]
doc/tack/grohtml-1027224.png [new file with mode: 0644]
doc/tack/grohtml-1027225.png [new file with mode: 0644]
doc/tack/grohtml-1027226.png [new file with mode: 0644]
doc/tack/grohtml-1027227.png [new file with mode: 0644]
doc/tack/grohtml-1027228.png [new file with mode: 0644]
doc/tack/grohtml-1027229.png [new file with mode: 0644]
doc/tack/grohtml-102723.png [new file with mode: 0644]
doc/tack/grohtml-1027230.png [new file with mode: 0644]
doc/tack/grohtml-1027231.png [new file with mode: 0644]
doc/tack/grohtml-1027232.png [new file with mode: 0644]
doc/tack/grohtml-1027233.png [new file with mode: 0644]
doc/tack/grohtml-1027234.png [new file with mode: 0644]
doc/tack/grohtml-1027235.png [new file with mode: 0644]
doc/tack/grohtml-1027236.png [new file with mode: 0644]
doc/tack/grohtml-1027237.png [new file with mode: 0644]
doc/tack/grohtml-1027238.png [new file with mode: 0644]
doc/tack/grohtml-1027239.png [new file with mode: 0644]
doc/tack/grohtml-102724.png [new file with mode: 0644]
doc/tack/grohtml-102725.png [new file with mode: 0644]
doc/tack/grohtml-102726.png [new file with mode: 0644]
doc/tack/grohtml-102727.png [new file with mode: 0644]
doc/tack/grohtml-102728.png [new file with mode: 0644]
doc/tack/grohtml-102729.png [new file with mode: 0644]
doc/tack/grohtml-105631.png [new file with mode: 0644]
doc/tack/grohtml-105632.png [new file with mode: 0644]
doc/tack/grohtml-105633.png [new file with mode: 0644]
doc/tack/grohtml-105634.png [new file with mode: 0644]
doc/tack/grohtml-106061.png [new file with mode: 0644]
doc/tack/grohtml-106062.png [new file with mode: 0644]
doc/tack/grohtml-106561.png [new file with mode: 0644]
doc/tack/grohtml-1065610.png [new file with mode: 0644]
doc/tack/grohtml-1065611.png [new file with mode: 0644]
doc/tack/grohtml-1065612.png [new file with mode: 0644]
doc/tack/grohtml-1065613.png [new file with mode: 0644]
doc/tack/grohtml-1065614.png [new file with mode: 0644]
doc/tack/grohtml-106562.png [new file with mode: 0644]
doc/tack/grohtml-106563.png [new file with mode: 0644]
doc/tack/grohtml-106565.png [new file with mode: 0644]
doc/tack/grohtml-106566.png [new file with mode: 0644]
doc/tack/grohtml-106567.png [new file with mode: 0644]
doc/tack/grohtml-106568.png [new file with mode: 0644]
doc/tack/grohtml-106569.png [new file with mode: 0644]
doc/tack/grohtml-107771.png [new file with mode: 0644]
doc/tack/grohtml-107772.png [new file with mode: 0644]
doc/tack/grohtml-107773.png [new file with mode: 0644]
doc/tack/grohtml-96851.png [new file with mode: 0644]
doc/tack/grohtml-96852.png [new file with mode: 0644]
doc/tack/grohtml-96853.png [new file with mode: 0644]
doc/tack/grohtml-96854.png [new file with mode: 0644]
doc/tack/grohtml-96855.png [new file with mode: 0644]
doc/tack/grohtml-96856.png [new file with mode: 0644]
doc/tack/grohtml-96857.png [new file with mode: 0644]
doc/tack/grohtml-97441.png [new file with mode: 0644]
doc/tack/grohtml-974410.png [new file with mode: 0644]
doc/tack/grohtml-974411.png [new file with mode: 0644]
doc/tack/grohtml-974412.png [new file with mode: 0644]
doc/tack/grohtml-974413.png [new file with mode: 0644]
doc/tack/grohtml-974414.png [new file with mode: 0644]
doc/tack/grohtml-974415.png [new file with mode: 0644]
doc/tack/grohtml-974416.png [new file with mode: 0644]
doc/tack/grohtml-974418.png [new file with mode: 0644]
doc/tack/grohtml-974419.png [new file with mode: 0644]
doc/tack/grohtml-97442.png [new file with mode: 0644]
doc/tack/grohtml-974420.png [new file with mode: 0644]
doc/tack/grohtml-97443.png [new file with mode: 0644]
doc/tack/grohtml-97444.png [new file with mode: 0644]
doc/tack/grohtml-97445.png [new file with mode: 0644]
doc/tack/grohtml-97446.png [new file with mode: 0644]
doc/tack/grohtml-97447.png [new file with mode: 0644]
doc/tack/grohtml-97448.png [new file with mode: 0644]
doc/tack/grohtml-97449.png [new file with mode: 0644]
doc/tack/grohtml-99071.png [new file with mode: 0644]
doc/tack/grohtml-99261.png [new file with mode: 0644]
doc/tack/grohtml-99451.png [new file with mode: 0644]
doc/tack/grohtml-99452.png [new file with mode: 0644]
doc/tack/grohtml-99453.png [new file with mode: 0644]
doc/tack/grohtml-99454.png [new file with mode: 0644]
doc/tack/grohtml-99455.png [new file with mode: 0644]
doc/tack/grohtml-99456.png [new file with mode: 0644]
doc/tack/grohtml-99457.png [new file with mode: 0644]
doc/tack/i80.html [new file with mode: 0644]
doc/tack/i80.pdf [new file with mode: 0644]
doc/tack/install.html [new file with mode: 0644]
doc/tack/install.pdf [new file with mode: 0644]
doc/tack/int.html [new file with mode: 0644]
doc/tack/int.pdf [new file with mode: 0644]
doc/tack/lint.html [new file with mode: 0644]
doc/tack/lint.pdf [new file with mode: 0644]
doc/tack/m2ref.html [new file with mode: 0644]
doc/tack/m2ref.pdf [new file with mode: 0644]
doc/tack/m68020.html [new file with mode: 0644]
doc/tack/m68020.pdf [new file with mode: 0644]
doc/tack/ncg.html [new file with mode: 0644]
doc/tack/ncg.pdf [new file with mode: 0644]
doc/tack/nopt.html [new file with mode: 0644]
doc/tack/nopt.pdf [new file with mode: 0644]
doc/tack/occam.html [new file with mode: 0644]
doc/tack/occam.pdf [new file with mode: 0644]
doc/tack/pascal.html [new file with mode: 0644]
doc/tack/pascal.pdf [new file with mode: 0644]
doc/tack/pcref.html [new file with mode: 0644]
doc/tack/pcref.pdf [new file with mode: 0644]
doc/tack/peep.html [new file with mode: 0644]
doc/tack/peep.pdf [new file with mode: 0644]
doc/tack/regadd.html [new file with mode: 0644]
doc/tack/regadd.pdf [new file with mode: 0644]
doc/tack/toolkit.html [new file with mode: 0644]
doc/tack/toolkit.pdf [new file with mode: 0644]
doc/tack/top.html [new file with mode: 0644]
doc/tack/top.pdf [new file with mode: 0644]
doc/tack/v7bugs.html [new file with mode: 0644]
doc/tack/v7bugs.pdf [new file with mode: 0644]
doc/tack/val.html [new file with mode: 0644]
doc/tack/val.pdf [new file with mode: 0644]
doc/tack/z80.html [new file with mode: 0644]
doc/tack/z80.pdf [new file with mode: 0644]
lib/pcc/Makefile
lib/pcc/allo.c [new file with mode: 0644]
lib/pcc/cgram.c [new file with mode: 0644]
lib/pcc/cgram.y [new file with mode: 0644]
lib/pcc/comm1.c [new file with mode: 0644]
lib/pcc/config.h [new file with mode: 0644]
lib/pcc/conflicts.txt [new file with mode: 0644]
lib/pcc/fort.c [new file with mode: 0644]
lib/pcc/groups.txt [new file with mode: 0644]
lib/pcc/local2.c
lib/pcc/localdefs.h [deleted file]
lib/pcc/mac2defs.h
lib/pcc/macdefs.h
lib/pcc/manifest.h [new file with mode: 0644]
lib/pcc/match.c [new file with mode: 0644]
lib/pcc/ndu.h [new file with mode: 0644]
lib/pcc/optim.c [new file with mode: 0644]
lib/pcc/order.c
lib/pcc/pass1.h [new file with mode: 0644]
lib/pcc/pass1.txt [new file with mode: 0644]
lib/pcc/pass2.h [new file with mode: 0644]
lib/pcc/pass2.txt [new file with mode: 0644]
lib/pcc/pcclocal.h [new file with mode: 0644]
lib/pcc/pftn.c [new file with mode: 0644]
lib/pcc/reader.c [new file with mode: 0644]
lib/pcc/scan.c [new file with mode: 0644]
lib/pcc/stab.c
lib/pcc/trees.c [new file with mode: 0644]
lib/pcc/uniqifystab.sed [new file with mode: 0644]
lib/pcc/xdefs.c [new file with mode: 0644]
scripts/ansify.sh

diff --git a/doc/7thEdMan/Rv7man b/doc/7thEdMan/Rv7man
new file mode 100644 (file)
index 0000000..e5da452
--- /dev/null
@@ -0,0 +1,405 @@
+%A L. P. Deutsch
+%A B. W. Lampson
+%T An online editor
+%J Comm. Assoc. Comp. Mach.
+%V 10
+%N 12
+%D December 1967
+%P 793-799, 803
+%K qed
+
+.[
+%r 17
+%K cstr
+%R Comp. Sci. Tech. Rep. No. 17
+%I Bell Laboratories
+%C Murray Hill, New Jersey
+%A B. W. Kernighan
+%A L. L. Cherry
+%T A System for Typesetting Mathematics
+%d May 1974, revised April 1977
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 18
+%P 151-157
+%D March 1975
+.]
+
+%T U\s-2NIX\s0 Time-Sharing System: Document Preparation
+%K unix bstj
+%A B. W. Kernighan
+%A M. E. Lesk
+%A J. F. Ossanna
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 2115-2135
+%D 1978
+
+%A T. A. Dolotta
+%A J. R. Mashey
+%T An Introduction to the Programmer's Workbench
+%J Proc. 2nd Int. Conf. on Software Engineering
+%D October 13-15, 1976
+%P 164-168
+
+%T U\s-2NIX\s0 Time-Sharing System: The Programmer's Workbench
+%A T. A. Dolotta
+%A R. C. Haight
+%A J. R. Mashey
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 2177-2200
+%D 1978
+%K unix bstj
+
+%T U\s-2NIX\s0 Time-Sharing System: U\s-2NIX\s0 on a Microprocessor
+%K unix bstj
+%A H. Lycklama
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 2087-2101
+%D 1978
+
+%T The C Programming Language
+%A B. W. Kernighan
+%A D. M. Ritchie
+%I Prentice-Hall
+%C Englewood Cliffs, New Jersey
+%D 1978
+
+%T Computer Recreations
+%A Aleph-null
+%J Software Practice and Experience
+%V 1
+%N 2
+%D April-June 1971
+%P 201-204
+
+%T U\s-2NIX\s0 Time-Sharing System: The U\s-2NIX\s0 Shell
+%A S. R. Bourne
+%K unix bstj
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 1971-1990
+%D 1978
+
+%A L. P. Deutsch
+%A B. W. Lampson
+%T \*sSDS\*n 930 time-sharing system preliminary reference manual
+%R Doc. 30.10.10, Project \*sGENIE\*n
+%C Univ. Cal. at Berkeley
+%D April 1965
+
+%A R. J. Feiertag
+%A E. I. Organick
+%T The Multics input-output system
+%J Proc. Third Symposium on Operating Systems Principles
+%D October 18-20, 1971
+%P 35-41
+
+%A D. G. Bobrow
+%A J. D. Burchfiel
+%A D. L. Murphy
+%A R. S. Tomlinson
+%T \*sTENEX\*n, a Paged Time Sharing System for the \*sPDP\*n-10
+%J Comm. Assoc. Comp. Mach.
+%V 15
+%N 3
+%D March 1972
+%K tenex
+%P 135-143
+
+%A R. E. Griswold
+%A D. R. Hanson
+%T An Overview of SL5
+%J SIGPLAN Notices
+%V 12
+%N 4
+%D April 1977
+%P 40-50
+
+%A E. W. Dijkstra
+%T Cooperating Sequential Processes
+%B Programming Languages
+%E F. Genuys
+%I Academic Press
+%C New York
+%D 1968
+%P 43-112
+
+%A J. A. Hawley
+%A W. B. Meyer
+%T M\s-2UNIX\s0, A Multiprocessing Version of U\s-2NIX\s0
+%K munix unix
+%R M.S. Thesis
+%I Naval Postgraduate School
+%C Monterey, Cal.
+%D 1975
+
+%T The U\s-2NIX\s0 Time-Sharing System
+%K unix bstj
+%A D. M. Ritchie
+%A K. Thompson
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 1905-1929
+%D 1978
+
+%A E. I. Organick
+%T The M\s-2ULTICS\s0 System
+%K multics
+%I M.I.T. Press
+%C Cambridge, Mass.
+%D 1972
+
+%T UNIX for Beginners
+%A B. W. Kernighan
+%D 1978
+
+%T U\s-2NIX\s0 Programmer's Man\&ual
+%A K. Thompson
+%A D. M. Ritchie
+%K unix
+%I Bell Laboratories
+%O Seventh Edition.
+%D 1978
+
+%A K. Thompson
+%T The U\s-2NIX\s0 Command Language
+%B Structured Programming\(emInfotech State of the Art Report
+%I Infotech International Ltd.
+%C Nicholson House, Maidenhead, Berkshire, England
+%D March 1975
+%P 375-384
+%K unix
+%X pwb
+Brief description of shell syntax and semantics, without much
+detail on implementation.
+Much on pipes and convenience of hooking programs together.
+Includes SERMONETTE:
+"Many familiar computing `concepts' are missing from UNIX.
+Files have no records. There are no access methods.
+There are no file types.  These concepts fill a much-needed gap.
+I sincerely hope that when future systems are designed by
+manufacturers the value of some of these ingrained notions is re-examined.
+Like the politician and his `common man', manufacturers have
+their `average user'.
+
+%A J. R. Mashey
+%T PWB/UNIX Shell Tutorial
+%D September 30, 1977
+
+%A D. F. Hartley (Ed.)
+%T The Cambridge Multiple Access System \- Users Reference Manual
+%I University Mathematical Laboratory
+%C Cambridge, England
+%D 1968
+
+%A P. A. Crisman (Ed.)
+%T The Compatible Time-Sharing System
+%I M.I.T. Press
+%K whole ctss book
+%C Cambridge, Mass.
+%D 1965
+
+%T LR Parsing
+%A A. V. Aho
+%A S. C. Johnson
+%J Comp. Surveys
+%V 6
+%N 2
+%P 99-124
+%D June 1974
+
+%T Deterministic Parsing of Ambiguous Grammars
+%A A. V. Aho
+%A S. C. Johnson
+%A J. D. Ullman
+%J Comm. Assoc. Comp. Mach.
+%K acm cacm
+%V 18
+%N 8
+%P 441-452
+%D August 1975
+
+%A A. V. Aho
+%A J. D. Ullman
+%T Principles of Compiler Design
+%I Addison-Wesley
+%C Reading, Mass.
+%D 1977
+
+.[
+%r 65
+%R Comp. Sci. Tech. Rep. No. 65
+%K CSTR
+%A S. C. Johnson
+%T Lint, a C Program Checker
+%D December 1977
+%O updated version TM 78-1273-3
+%D 1978
+.]
+
+%T A Portable Compiler: Theory and Practice
+%A S. C. Johnson
+%J Proc. 5th ACM Symp. on Principles of Programming Languages
+%P 97-104
+%D January 1978
+
+.[
+%r 39
+%K CSTR
+%R Comp. Sci. Tech. Rep. No. 39
+%I Bell Laboratories
+%C Murray Hill, New Jersey
+%A M. E. Lesk
+%T Lex \(em A Lexical Analyzer Generator
+%D October 1975
+.]
+
+.[
+%r 32
+%K CSTR
+%R Comp. Sci. Tech. Rep. No. 32
+%I Bell Laboratories
+%C Murray Hill, New Jersey
+%A S. C. Johnson
+%T Yacc \(em  Yet Another Compiler-Compiler
+%D July 1975
+.]
+
+%T U\s-2NIX\s0 Time-Sharing System: Portability of C Programs and the U\s-2NIX\s0 System
+%K unix bstj
+%A S. C. Johnson
+%A D. M. Ritchie
+%J Bell Sys. Tech. J.
+%V 57
+%N 6
+%P 2021-2048
+%D 1978
+
+%T Typing Documents on UNIX and GCOS:  The -ms Macros for Troff
+%A M. E. Lesk
+%D 1977
+
+%A K. Thompson
+%A D. M. Ritchie
+%T U\s-2NIX\s0 Programmer's Manual
+%K unix
+%I Bell Laboratories
+%O Sixth Edition
+%D May 1975
+
+%T The Network U\s-2NIX\s0 System
+%K unix
+%A G. L. Chesson
+%J Operating Systems Review
+%V 9
+%N 5
+%P 60-66
+%D 1975
+%O Also in \f2Proc. 5th Symp. on Operating Systems Principles.\f1
+
+%T Spider \(em An Experimental Data Communications System
+%Z ctr127
+%A A. G. Fraser
+%J Proc. IEEE Conf. on Communications
+%P 21F
+%O IEEE Cat. No. 74CH0859-9-CSCB.
+%D June 1974
+
+%T A Virtual Channel Network
+%A A. G. Fraser
+%J Datamation
+%P 51-56
+%D February 1975
+
+.[
+%r 41
+%K CSTR
+%R Comp. Sci. Tech. Rep. No. 41
+%I Bell Laboratories
+%C Murray Hill, New Jersey
+%A J. W. Hunt
+%A M. D. McIlroy
+%T An Algorithm for Differential File Comparison
+%D June 1976
+.]
+
+%A F. P. Brooks, Jr.
+%T The Mythical Man-Month
+%I Addison-Wesley
+%C Reading, Mass.
+%D 1975
+%X pwb
+Readable, classic reference on software engineering and
+problems of large projects, from someone with experience in them.
+Required reading for any software engineer, even if conclusions may not
+always be agreed with.
+%br
+"The second is the most dangerous system a man every designs." p.55.
+%br
+"Hence plan to throw one away; you will, anyhow." p.116.
+%br
+"Cosgrove has perceptively pointed out that the programmer delivers
+satisfaction of a user need rather than any tangible product.
+And both the actual need and the user's perception of that need
+will change as programs are built, tested, and used." p.117.
+%br
+"The total cost of maintaining a widely used program is typically 40 percent
+or more of the cost of developing it." p.121.
+%br
+"As shown above, amalgamating prose and program reduces the total
+number of characters to be stored." p.175.
+
+%T A Portable Compiler for the Language C
+%A A. Snyder
+%I Master's Thesis, M.I.T.
+%C Cambridge, Mass.
+%D 1974
+
+%T The C Language Calling Sequence
+%A M. E. Lesk
+%A S. C. Johnson
+%A D. M. Ritchie
+%D 1977
+
+%T Optimal Code Generation for Expression Trees
+%A A. V. Aho
+%A S. C. Johnson
+%D 1975
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 23
+%N 3
+%P 488-501
+%O Also in \f2Proc. ACM Symp. on Theory of Computing,\f1 pp. 207-217, 1975.
+
+%A R. Sethi
+%A J. D. Ullman
+%T The Generation of Optimal Code for Arithmetic Expressions
+%J J. Assoc. Comp. Mach.
+%K acm jacm
+%V 17
+%N 4
+%D October 1970
+%P 715-728
+%O Reprinted as pp. 229-247 in \fICompiler Techniques\fR, ed. B. W. Pollack, Auerbach, Princeton NJ (1972).
+%X pwb
+Optimal approach for straight-line, fixed
+number of regs.
+
+%T Code Generation for Machines with Multiregister
+Operations
+%A A. V. Aho
+%A S. C. Johnson
+%A J. D. Ullman
+%J Proc. 4th ACM Symp. on Principles of Programming Languages
+%P 21-28
+%D January 1977
+
diff --git a/doc/7thEdMan/bswv7.html b/doc/7thEdMan/bswv7.html
new file mode 100644 (file)
index 0000000..3c5a0b1
--- /dev/null
@@ -0,0 +1,145 @@
+<HTML>
+<HEAD>
+<TITLE>
+7th Edition Manual PDF
+</TITLE>
+</HEAD>
+<BODY BGCOLOR="#FFFFFF" LINK="#0000FF" VLINK="#800080">
+<BR>
+<BR>
+<center>
+<H3>
+PDF and PostScript Renditions of Seventh Edition Manual
+</H3>
+</center>
+<p>
+
+Brian S. Walden has kindly done the work to render the manual
+in PDF, by processes he describes below.  The files
+<p>
+<ul>
+<li><A HREF="v7vol1.pdf">v7vol1.pdf</A> (960KB)</li>
+
+<li><A HREF="v7vol2a.pdf">v7vol2a.pdf</A> (1267KB)</li>
+
+<li><A HREF="v7vol2b.pdf">v7vol2b.pdf</A> (819KB)</li>
+</ul>
+<p>
+are copies of the PDF produced by him from our troff source
+at <A HREF="http://plan9.bell-labs.com/7thEdMan/">http://plan9.bell-labs.com/7thEdMan/</A>
+and are reproduced here with his kind permission.
+<p>
+In turn, Aharon (Arnold) Robbins transliterated the PDF into
+PostScript, here compressed with gzip:
+<p>
+<ul>
+<li><A HREF="v7vol1.ps.gz">v7vol1.ps.gz</A> (534KB)</li>
+
+<li><A HREF="v7vol2a.ps.gz">v7vol2a.ps.gz</A> (913KB)</li>
+
+<li><A HREF="v7vol2b.ps.gz">v7vol2b.ps.gz</A> (571KB)</li>
+</ul>
+
+<p>
+Walden's own rendition and his production notes remain available at
+<A HREF="http://www.panix.com/~bsw/v7">http://www.panix.com/~bsw/v7</A>.
+<p>
+Walden's description of his work follows.
+<p>
+&nbsp;Dennis
+</i>
+<hr>
+<PRE>
+
+<BR>
+I thought it would be fairly simple and straight forward, but it took
+more effort than initially expected.  Because of this extra effort I
+am offering them back in this PDF format to place them along side the
+source.  Today, they are much more usable in this form, especially
+since these things are not going to be updated.  It can be read,
+browsed and searched on many platforms as well as printed to many
+different printers (not just PostScript ones)
+<BR>
+These are most of the the changes I made to get them produced --
+<BR>
+For volume 1:
+ remove the page break ticks from tmac.an
+<BR>
+ header files needed for .so's in various man pages:
+       /usr/include/sys/acct.h
+       /usr/include/sys/var.h
+       /usr/include/sys/dir.h
+       /usr/include/sys/fblk.h
+       /usr/include/sys/filsys.h
+       /usr/include/sys/ino.h
+       /usr/include/sys/stat.h
+       /usr/include/sys/types.h
+       /usr/include/sys/timeb.h
+       /usr/include/a.out.h
+       /usr/include/ar.h
+       /usr/include/dumprestor.h
+       /usr/include/grp.h
+       /usr/include/pwd.h
+       /usr/include/ustat.h
+       /usr/include/time.h
+       /usr/include/utmp.h
+<BR>
+  Place a \& in front of lines beginning with . so it would be literal:
+       man1/roff.1
+       man1/tbl.1
+       man7/man.7
+       man7/ms.7
+<BR>
+For both volumes 1 and 2:
+ added an old bell system logo into PostScript for \(bs in the sources
+<BR>
+For volume 2:
+ modify the tmac.s macros to remove the page break ticks.
+<BR>
+ uucp/network needs to be run through refer as well (fix in "run" script).
+<BR>
+ needed to make 4 figures (with pic, at the time of these docs, Kernighan
+ hadn't written it yet) --
+       msmacros/ms: last page, Figure 1, arrangement of commands at the
+               beginning of a document
+       make: transformation paths diagram
+       implement: Fig 1 & Fig 2 (got what they looked like from
+               the bstj of '78)
+<BR>
+ the missing learn references were taken from the learn.ms file found in:
+       <A HREF="http://cm.bell-labs.com/cm/cs/who/bwk/learn.tar.gz">http://cm.bell-labs.com/cm/cs/who/bwk/learn.tar.gz</A>
+<BR>
+ replace .ND dates for some files so they didn't get printed with the
+ date it was troff'd.
+<BR>
+ the missing C reference manual was replaced with the PostScript one
+ for the 6th edition available at <A HREF="http://cm.bell-labs.com/cm/cs/who/dmr/cman.ps">http://cm.bell-labs.com/cm/cs/who/dmr/cman.ps</A>
+<BR>
+ fixed the typo in ratfor/m0 of the word "oe" to "one" (I really don't
+ want to be an editor but this has bothered me since the first time I
+ saw it long ago)
+<BR>
+ fix the uprog/cwscript sed script because the old symbols in constant-width
+ are no longer the correct mapping.
+<BR>
+Production procedure:
+ (refer,pic,eqn,tbl,troff)'d, PostScript'd and distill'd them into PDF
+ I ran into a distiller bug so I needed to slightly modify many
+ of the PostScript files just before distilling (this did not change
+ the contents of the documents)
+<BR>
+ added blank pages as needed so that sections and papers started on 
+ an odd page number so that they can be printed double-sided
+<BR>
+ after they were in PDF I added the bookmarks:
+    Volume 1 being man pages, the bookmarks are at each section. The
+    best way to find something here is to just use the acrobat reader's
+    search (binoculars icon) function.
+    Volume 2 bookmarks are on each individual paper.
+<BR>
+The PDF doesn't look exactly like the original because troff now produces
+slightly different output for PostScript devices.
+</PRE>
+</BODY>
+</HTML>
+
diff --git a/doc/7thEdMan/index.html b/doc/7thEdMan/index.html
new file mode 100644 (file)
index 0000000..e77243d
--- /dev/null
@@ -0,0 +1,122 @@
+<html>
+<head>
+<title>
+Unix Seventh Edition Manual
+</title>
+</head><body>
+<H1>Unix Seventh Edition Manual</H1>
+<hr>
+<P>
+This page points to the source for the documents
+that came with the Seventh Edition release of the Unix
+operating system from (then) Bell Telephone Laboratories,
+Incorporated.  The files are those that were shipped
+on the distribution tapes.
+<P>
+The printed version came in three volumes: 1, 2A, 2B.
+Volume one has the traditional "man pages" describing
+commands, system calls, etc.  Volumes 2 contained
+papers describing various parts of the system in more
+detail.  Besides the version shipped with the distribution,
+the manuals were later reprinted by Saunders College
+Publishing; doubtless this edition is out of print.
+<P>
+Thanks to the efforts of Brian S. Walden and then Aharon Robbins,
+<A HREF=bswv7.html>PDF and PostScript renditions</A> are available.
+The PDF is readily searchable and printable if you
+have an Adobe Acrobat reader.
+<P>
+For those who prefer the original bits,
+the manual sections referenced below need to be formatted with troff, using
+the -man macros (a copy of which is here, as tmac.an).
+The papers are generally formatted with the
+-ms macros (tmac.s).  The other tmac files are included
+by tmac.s.
+<P>
+References are included by using the refer program,
+which almost no one has any more.  However, the database
+of references is included (Rv7man) in case someone wants
+to look up a reference by hand.
+<P>
+CAUTION: The source material here is not formatted for HTML and is not
+readily viewed over the web unless you like to read troff.
+The files that end with
+".bun" are shell bundles of documents that were in
+several separate files.
+<P>
+All of this material was copyrighted in 1979 by Bell
+Telephone Laboratories, Incorporated.  Currently
+the copyright is held jointly by Lucent Technologies Inc.
+and AT&T Corporation.  All rights reserved.
+<p>
+<hr>
+<P>
+<H2> Volume 1</H2>
+<P>
+<br>
+<br><A HREF="/7thEdMan/vol1/man0.bun">vol1/man0.bun </a>       - introduction
+<br><A HREF="/7thEdMan/vol1/man1.bun">vol1/man1.bun </a>       - commands
+<br><A HREF="/7thEdMan/vol1/man2.bun">vol1/man2.bun </a>       - system calls
+<br><A HREF="/7thEdMan/vol1/man3.bun">vol1/man3.bun </a>       - libraries
+<br><A HREF="/7thEdMan/vol1/man4.bun">vol1/man4.bun </a>       - devices
+<br><A HREF="/7thEdMan/vol1/man5.bun">vol1/man5.bun </a>       - file formats
+<br><A HREF="/7thEdMan/vol1/man6.bun">vol1/man6.bun </a>       - games
+<br><A HREF="/7thEdMan/vol1/man7.bun">vol1/man7.bun </a>       - macros and language conventions
+<br><A HREF="/7thEdMan/vol1/man8.bun">vol1/man8.bun </a>       - administration
+<P>
+<H2> Volumes 2A and 2B</H2>
+<P>
+<br>
+<br><A HREF="/7thEdMan/vol2/README">vol2/README </a>
+<br><A HREF="/7thEdMan/vol2/assembler">vol2/assembler </a>     - assembler syntax (PDP-11)
+<br><A HREF="/7thEdMan/vol2/awk">vol2/awk </a> - awk language
+<br><A HREF="/7thEdMan/vol2/bc">vol2/bc </a>   - desk calculator (infix)
+<br><A HREF="/7thEdMan/vol2/cman">vol2/cman </a>       - explains why C manual is missing
+<br><A HREF="/7thEdMan/vol2/dc">vol2/dc </a>   - desk calculator (postfix)
+<br><A HREF="/7thEdMan/vol2/f77">vol2/f77 </a> - Fortran 77
+<br><A HREF="/7thEdMan/vol2/implement">vol2/implement </a>     - implementation of system
+<br><A HREF="/7thEdMan/vol2/index">vol2/index </a>     - the index
+<br><A HREF="/7thEdMan/vol2/iosys">vol2/iosys </a>     - workings of IO system
+<br><A HREF="/7thEdMan/vol2/lex">vol2/lex </a> - lexical analyzer generator
+<br><A HREF="/7thEdMan/vol2/lint">vol2/lint </a>       - program checker
+<br><A HREF="/7thEdMan/vol2/m4">vol2/m4 </a>   - macro processor
+<br><A HREF="/7thEdMan/vol2/make">vol2/make </a>       - directing program compilation
+<br><A HREF="/7thEdMan/vol2/password">vol2/password </a>       - the password scheme
+<br><A HREF="/7thEdMan/vol2/regen">vol2/regen </a>     - regenerating system software
+<br><A HREF="/7thEdMan/vol2/run">vol2/run </a> - commands for formatting the manual
+<br><A HREF="/7thEdMan/vol2/security">vol2/security </a>       - general security discussion
+<br><A HREF="/7thEdMan/vol2/sed">vol2/sed </a> - stream editor
+<br><A HREF="/7thEdMan/vol2/setup">vol2/setup </a>     - directions for installing the system
+<br><A HREF="/7thEdMan/vol2/tbl">vol2/tbl </a> - table formatter
+<br><A HREF="/7thEdMan/vol2/adb.bun">vol2/adb.bun </a> - debugger
+<br><A HREF="/7thEdMan/vol2/adv.ed.bun">vol2/adv.ed.bun </a>   - advanced editing with ed
+<br><A HREF="/7thEdMan/vol2/beginners.bun">vol2/beginners.bun </a>     - tutorial
+<br><A HREF="/7thEdMan/vol2/cacm.bun">vol2/cacm.bun </a>       - Original CACM paper on Unix
+<br><A HREF="/7thEdMan/vol2/ctour.bun">vol2/ctour.bun </a>     - Tour of the PDP-11 C compiler
+<br><A HREF="/7thEdMan/vol2/edtut.bun">vol2/edtut.bun </a>     - ed tutorial
+<br><A HREF="/7thEdMan/vol2/eqn.bun">vol2/eqn.bun </a> - mathematical typesetting
+<br><A HREF="/7thEdMan/vol2/learn.bun">vol2/learn.bun </a>     - interpreter for generating teaching scripts
+<br><A HREF="/7thEdMan/vol2/msmacros.bun">vol2/msmacros.bun </a>       - the troff
+-ms macros
+<br><A HREF="/7thEdMan/vol2/porttour.bun">vol2/porttour.bun </a>       - tour of Johnson's portable C compiler
+<br><A HREF="/7thEdMan/vol2/ratfor.bun">vol2/ratfor.bun </a>   - ratfor language
+<br><A HREF="/7thEdMan/vol2/refer.bun">vol2/refer.bun </a>     - reference generator for papers
+<br><A HREF="/7thEdMan/vol2/shell.bun">vol2/shell.bun </a>     - the command interpreter
+<br><A HREF="/7thEdMan/vol2/summary.bun">vol2/summary.bun </a> - what's new in the seventh edition
+<br><A HREF="/7thEdMan/vol2/troff.bun">vol2/troff.bun </a>     - text formatter
+<br><A HREF="/7thEdMan/vol2/trofftut.bun">vol2/trofftut.bun </a>       - tutorial for troff
+<br><A HREF="/7thEdMan/vol2/uprog.bun">vol2/uprog.bun </a>     - technique for unix programming
+<br><A HREF="/7thEdMan/vol2/uucp.bun">vol2/uucp.bun </a>       - sending files and mail
+between machines
+<br><A HREF="/7thEdMan/vol2/yacc.bun">vol2/yacc.bun </a>       - parser generator
+<H2> Macros and References</H2>
+<P>
+<br><A HREF="/7thEdMan/tmac.s">tmac.s </a>
+<br><A HREF="/7thEdMan/tmac.scover">tmac.scover </a>
+<br><A HREF="/7thEdMan/tmac.sdisp">tmac.sdisp </a>
+<br><A HREF="/7thEdMan/tmac.skeep">tmac.skeep </a>
+<br><A HREF="/7thEdMan/tmac.an">tmac.an </a>
+<br><A HREF="/7thEdMan/tmac.srefs">tmac.srefs </a>
+<br><A HREF="/7thEdMan/Rv7man">Rv7man </a>
+</body>
+</html>
diff --git a/doc/7thEdMan/tmac.an b/doc/7thEdMan/tmac.an
new file mode 100644 (file)
index 0000000..cbe2af2
--- /dev/null
@@ -0,0 +1,267 @@
+'      # month name
+.if "\nd"0" .nr m \n(mo-1
+.if "\nm"0" .ds ]m January
+.if "\nm"1" .ds ]m February
+.if "\nm"2" .ds ]m March
+.if "\nm"3" .ds ]m April
+.if "\nm"4" .ds ]m May
+.if "\nm"5" .ds ]m June
+.if "\nm"6" .ds ]m July
+.if "\nm"7" .ds ]m August
+.if "\nm"8" .ds ]m September
+.if "\nm"9" .ds ]m October
+.if "\nm"10" .ds ]m November
+.if "\nm"11" .ds ]m December
+'      # set the date
+.if n \{.nr m \nm+1
+.       ie \nd .ds ]W Modified \nm/\nd/\ny
+.       el .ds ]W Printed \n(mo/\n(dy/\n(yr\}
+.if t \{.ie \nd .ds ]W \*(]m \nd, 19\ny
+.       el .ds ]W \*(]m \n(dy, 19\n(yr\}
+.if t .ds ]W 7th Edition
+'      # reset the basic page layout
+.de }E
+.}f
+.in \\n()Ru+\\n(INu
+.ll \\n(LLu
+..
+'      # default tabs
+.de DT
+'ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i 5.5i 6i 6.5i
+..
+'      # set type font and size
+.de }f
+.ps 10
+.ft 1
+..
+'      # handle the head of the page
+.de }H
+.ev 1
+.}C
+'sp .5i
+.ft 1
+.ps 10
+.tl @\\*(]H@\\*(]D@\\*(]H@
+'sp .5i
+.ev
+.ns
+..
+'      # handle the foot of the page
+.de }F
+.ev 1
+.ft 1
+.ps 10
+'sp .5i
+.tl @\\*(]W@\\*(]L@%@
+'bp
+.ev
+..
+'      # the cut mark
+.if n .ig
+.de }C
+.po .1i
+.tl '-'
+.po
+..
+'      # the final cut mark
+.de }M
+.}N
+.wh -1p }C
+.ll \\n(LLu
+..
+'      # no runout unless there was a .TH
+.de }K
+.}N
+.pl 1
+.ll \\n(LLu
+..
+.em }K
+'      # set title and heading
+.de TH
+.PD
+.if n .nr IN .5i
+.if t .nr IN .5i
+.nr LL \\n(.l
+.ds ]H \\$1\|(\|\\$2\|)
+.ds ]D UNIX Programmer's Manual
+.ds ]L \\$3
+.wh 0 }H
+.if t .wh -1i }F
+.if n .wh -1.167i }F
+.em }M
+.if \\n(nl .bp 1
+.}E
+.DT
+.nr )I .5i
+.nr )R 0
+.if n .na
+..
+'      # section heading
+.de SH
+.}X 0
+.nr )E 2
+\&\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6
+..
+'      # sub section heading
+.de SS
+.}X \\n()Ru+\\n(INu
+\&\\$1 \|\\$2 \|\\$3 \|\\$4 \|\\$5 \|\\$6
+.br
+..
+'      # subroutine for section heading
+.de }X
+.}E
+.ti \\$1
+.sp \\n()Pu
+.ne 2
+.nr )R 0
+.fi
+.it 1 }N
+.SM
+.B
+..
+'      # end of SH (cf }X above and }N below)
+.de }2
+.nr )E 0
+.}E
+.nr )I .5i
+.ns
+..
+'      # italic
+.de I
+.ft 2
+.it 1 }N
+.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6
+..
+'      # bold
+.de B
+.ft 3
+.it 1 }N
+.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6
+..
+'      # small
+.de SM
+.ps 9
+.it 1 }N
+.if !"\\$1"" \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6
+..
+'      # combinations of Roman, italic, bold
+.de RI
+.}S 1 2 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de RB
+.}S 1 3 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de IR
+.}S 2 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de IB
+.}S 2 3 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de BR
+.}S 3 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de BI
+.}S 3 2 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+'      # make special case of shift out of italic
+.de }S
+.ds ]F
+.if "\\$1"2" .if !"\\$5"" .ds ]F\^
+.ie !"\\$4"" .}S \\$2 \\$1 "\\$3\f\\$1\\$4\\*(]F" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9"
+.el \\$3
+.}f
+..
+'      # paragraph
+.de LP
+.PP
+..
+.de PP
+.sp \\n()Pu
+.ne 2
+.}E
+.nr )I .5i
+.ns
+..
+'      # paragraph distance
+.de PD
+.if t .nr )P .4v
+.if n .nr )P 1v
+.if !"\\$1"" .nr )P \\$1v
+..
+'      # hanging indent
+.de HP
+.sp \\n()Pu
+.ne 2
+.if !"\\$1"" .nr )I \\$1n
+.ll \\n(LLu
+.in \\n()Ru+\\n(INu+\\n()Iu
+.ti \\n()Ru+\\n(INu
+.}f
+..
+'      # indented paragraph
+.de IP
+.TP \\$2
+\&\\$1
+..
+'      # hanging label
+.de TP
+.if !"\\$1"" .nr )I \\$1n
+.sp \\n()Pu
+.in \\n()Ru
+.nr )E 1
+.ns
+.it 1 }N
+.di ]B
+..
+'      # end of TP (cf }N below)
+.de }1
+.ds ]X \&\\*(]B\\
+.nr )E 0
+.if !"\\$1"" .nr )I \\$1n
+.}f
+.ll \\n(LLu
+.in \\n()Ru+\\n(INu+\\n()Iu
+.ti \\n(INu
+.ie !\\n()Iu+\\n()Ru-\w@\\*(]X@u-3p \{\\*(]X
+.br\}
+.el \\*(]X\h@|\\n()Iu+\\n()Ru@\c
+.}f
+..
+'      # handle end of 1-line features
+.de }N
+.if \\n()E .br
+.di
+.if "\\n()E"0" .}f
+.if "\\n()E"1" .}1
+.if "\\n()E"2" .}2
+.nr )E 0
+..
+'      # increase relative indent
+.de RS
+.nr ]\\n+()p \\n()I
+.nr )\\n()p \\n()R
+.ie !"\\$1"" .nr )R +\\$1n
+.el .nr )R +\\n()I
+.nr )I .5i
+.}E
+..
+'      # decrease relative indent
+.de RE
+.if !"\\$1"" \{.ie "\\$1"0" .nr )p 1 1
+.              el .nr )p \\$1 1\}
+.ds ]i \\*(]I\\n()p
+.ds ]r \\*(]R\\n()p
+.nr )I \\*(]i
+.nr )R \\*(]r
+.if \\n()p .nr )p -1
+.}E
+..
+.nr )p 0 1
+.ds ]I \\\\n(]
+.ds ]R \\\\n()
+.bd S 3 3
+.if t .ds R \(rg
+.if n .ds R (Reg.)
+.ds S \s10
+.hy 14
diff --git a/doc/7thEdMan/tmac.s b/doc/7thEdMan/tmac.s
new file mode 100644 (file)
index 0000000..3b5d0e2
--- /dev/null
@@ -0,0 +1,1360 @@
+.nr TN 0
+.\"    RT -  reset everything to normal state
+.de RT
+.if !\\n(1T .BG
+.if !\\n(IK .if !\\n(IF .if !\\n(IX .if !\\n(BE .di
+.ce 0
+.ul 0
+.if \\n(QP \{\
+.      ll +\\n(QIu
+.      in -\\n(QIu
+.      nr QP -1\}
+.if \\n(NX<=1 .if \\n(AJ=0 .ll \\n(LLu
+.if \\n(IF=0 \{\
+.      ps \\n(PS
+.      if \\n(VS>=40 .vs \\n(VSu
+.      if \\n(VS<=39 .vs \\n(VSp\}
+.if \\n(IP .in -\\n(I\\n(IRu
+.if \\n(IP=0 .nr I0 \\n(PIu
+.if \\n(IP .nr IP -1
+.ft 1
+.bd 1
+.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n
+.fi
+..
+.      \"IZ - initialization
+.de IZ
+.if \\n(FM=0 .nr FM 1i
+.nr YY -\\n(FMu
+.nr XX 0 1
+.nr IP 0
+.nr PI 5n
+.nr QI 5n
+.nr I0 \\n(PIu
+.nr PS 10
+.nr VS 12
+.if !\\n(PD .if n .nr PD 1v
+.if !\\n(PD .if t .nr PD 0.3v
+.nr ML 3v
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.nr IR 0
+.nr TB 0
+.nr SJ \\n(.j
+.nr LL 6i
+.ll \\n(LLu
+.nr LT \\n(.l
+.lt \\n(LTu
+.ev 1
+.nr FL \\n(LLu*11u/12u
+.ll \\n(FLu
+.ps 8
+.vs 10p
+.ev
+.if \a\\*(CH\a\a .ds CH "\(hy \\\\n(PN \(hy
+.if n .ds CF "\\*(DY
+.wh 0 NP
+.wh -\\n(FMu FO
+.ch FO 16i
+.wh -\\n(FMu FX
+.ch FO -\\n(FMu
+.wh -\\n(FMu/2u BT
+..
+.de TM
+.if \\n(IM=0 .if \\n(MN=0 .pn 0
+.so /usr/lib/tmac/tmac.scover
+.if \\n(IM=0 .if \\n(MN=0 .rm IM
+.if \\n(IM=0 .if \\n(MN=0 .rm MF
+.if \\n(IM=0 .if \\n(MN=0 .rm MR
+.if \\n(.T=0 .pi /usr/bin/col
+.nr ST 1
+.ds QF MEMORANDUM FOR FILE
+.br
+.ds MN \\$1
+.if !"\\$1"" .nr MM 1
+.if !"\\$2"" .nr MC 1
+.if !"\\$3"" .nr MG 1
+.nr TN 1
+.if \\n(.$-1 .ds CA \\$2
+.if \\n(.$-2 .ds CC \\$3
+.rm RP
+.rm S0
+.rm S2
+.rm AX
+..
+.              \" IM - internal memorandum
+.de IM
+.nr IM 1
+.TM "\\$1" "\\$2" "\\$3"
+.rm QF
+.RA
+.rm RA
+.rm RP
+.rm MF
+.rm MR
+..
+.              \" MF - memorandum for file.
+.de MF
+.nr MN 1
+.TM "\\$1" "\\$2" "\\$3"
+.rm MR
+.rm IM
+.RA
+.rm RA
+.rm RP
+.rm TM
+..
+.              \" MR - memo for record
+.de MR
+.nr MN 2
+.TM "\\$1" "\\$2" "\\$3"
+.ds QF MEMORANDUM FOR RECORD
+.rm MF
+.RA
+.rm RA
+.rm RP
+.rm IM
+.rm TM
+..
+.de EG
+.nr MN 3
+.TM "\\$1" "\\$2" "\\$3"
+.ds QF ENGINEER'S NOTES
+.rm MF
+.rm RP
+.rm IM
+.RA
+.rm RA
+.rm TM
+..
+.      \" LT - letter
+.de LT
+.LP
+.rs
+.sp 6
+.ll 80n
+.ti 48
+\\*(DY
+.ll
+.br
+.sp 3
+..
+.de OK
+.br
+.di
+.di OD
+..
+.de RP
+.nr ST 2
+.pn 0
+.rm SG
+.rm CS
+.rm TM
+.rm QF
+.rm IM
+.rm MR
+.rm MF
+.rm EG
+.br
+..
+.de TR \" Comp. Sci. Tech Rept series.
+.nr ST 3
+.pn 0
+.ds MN \\$1
+.rm SG
+.rm CS
+.rm TM
+.rm QF
+.rm IM
+.rm MR
+.rm MF
+.rm EG
+.br
+..
+.      \"TL - title and initialization
+.de TL
+.br
+.nr TV 1
+.if \\n(IM>0 .rm CS
+.if \\n(MN>0 .rm CS
+.ME
+.rm ME
+.di WT
+.nr SJ \\n(.j
+.na
+.fi
+.ll 5.0i
+.if n .if \\n(TN .ll 30
+.if t .if \\n(TN .ll 3.5i
+.ft 3
+.ps 10
+.if !\\n(TN .ps 12
+.if !\\n(TN .rm CS
+.hy 0
+..
+.de TX
+.rs
+.sp .5i
+.ce 1000
+.if n .ul 1000
+.ps 12
+.ft 3
+.vs 15p
+.ne 4
+.hy 0
+.WT
+.hy 14
+.ce 0
+.ul 0
+..
+.      \"      AU - author(s)
+.de AU
+.nr AV 1
+.ad \\n(SJ
+.br
+.di
+.br
+.nf
+.nr NA +1
+.ds R\\n(NA \\$1
+.ds E\\n(NA \\$2
+.di A\\n(NA
+.ll \\n(LLu
+.if \\n(TN=0 .if t .ft 2
+.if \\n(TN=0 .if n .ft 1
+.if \\n(TN>0 .ft 3
+.if \\n(TN .if n .ll 16
+.if \\n(TN .if t .ll 1.4i
+.ps 10
+..
+.de AX
+.ft 1
+.rs
+.ce 1000
+.if n .ul 0
+.ps 10
+.vs 12p
+.if n .sp 2
+.if t .sp
+.A1
+.if n .sp 
+.if t .sp 0.5
+.ns
+.I1
+.if \\n(NA-1 .if n .sp 2
+.if \\n(NA-1 .if t .sp
+.A2
+.if \\n(NA-1 .if n .sp
+.if \\n(NA-1 .if t .sp 0.5
+.ns
+.I2
+.if \\n(NA-2 .if t .sp
+.if \\n(NA-2 .if n .sp 2
+.A3
+.if \\n(NA-2 .if t .sp 0.5
+.if \\n(NA-2 .if n .sp
+.ns
+.I3
+.if \\n(NA-3 .if t .sp
+.if \\n(NA-3 .if n .sp 2
+.A4
+.if \\n(NA-3 .if t .sp 0.5
+.if \\n(NA-3 .if n .sp
+.ns
+.I4
+.if \\n(NA-4 .if t .sp
+.if \\n(NA-4 .if n .sp 2
+.A5
+.if \\n(NA-4 .if n .sp
+.if \\n(NA-4 .if t .sp 0.5
+.ns
+.I5
+.if \\n(NA-5 .if t .sp
+.if \\n(NA-5 .if n .sp 2
+.A6
+.if \\n(NA-5 .if n .sp
+.if \\n(NA-5 .if t .sp 0.5
+.ns
+.I6
+.if \\n(NA-6 .if t .sp
+.if \\n(NA-6 .if n .sp 2
+.A7
+.if \\n(NA-6 .if n .sp
+.if \\n(NA-6 .if t .sp 0.5
+.ns
+.I7
+.if \\n(NA-7 .if t .sp
+.if \\n(NA-7 .if n .sp 2
+.A8
+.if \\n(NA-7 .if n .sp
+.if \\n(NA-7 .if t .sp 0.5
+.ns
+.I8
+.if \\n(NA-8 .if t .sp
+.if \\n(NA-8 .if n .sp 2
+.A9
+.if \\n(NA-8 .if n .sp
+.if \\n(NA-8 .if t .sp 0.5
+.ns
+.I9
+..
+.      \"AI - authors institution
+.de AI
+.br
+.ft 1
+.di
+.di I\\n(NA
+.nf
+..
+.      \"AB - begin an abstract
+.de AB
+.br
+.di
+.ul 0
+.ce 0
+.nr 1T 1
+.nr IK 1
+.nr KI 1
+.di WB
+.rs
+.nr AJ 1
+.ce 1
+.ft 2
+.if n .ul
+.ll \\n(LLu
+.if \\n(.$=0 ABSTRACT
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no"  \\$1
+.if \\n(.$=0 .sp
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no" .sp
+.hy 14
+.ul 0
+.ce 0
+.fi
+.ft 1
+.nr OJ \\n(.i
+.in +\\n(.lu/12u
+.ll -\\n(.lu/12u
+.br
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ti +\\n(PIu
+..
+.      \"AE - end of an abstract
+.de AE
+.br
+.di
+.ll \\n(LLu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.nr 1T 0
+.nr IK 0
+.in \\n(OJu
+.nr AJ 0
+.di
+.ce 0
+.if \\n(ST=2 .SY
+.if \\n(ST<3 .rm SY
+..
+.      \"S2 - release paper style
+.      \"SY - cover sheet of released paper
+.de SY
+.ll \\n(LLu
+.ns
+.if \\n(TV .TX
+.if \\n(AV .AX
+.rs
+.ce 0
+.nf
+.sp 3
+.ls 1
+.pn 2
+.WB
+.ls 
+.sp 3v
+\\*(DY
+.sp |9i
+.if \\n(FP>0 .FA
+.FG
+.if \\n(GA=1 .nr GA 2
+.fi
+..
+.      \"S2 - first text page, released paper format
+.de S2
+.ce 0
+.br
+.SY
+.rm SY
+.bp 1
+.if \\n(TV .TX
+.if \\n(AV .AX
+.rs
+.ce 0
+.ft 1
+.ad \\n(SJ
+..
+.      \"S0- mike lesk conserve paper style
+.de S0
+.ce 0
+.br
+.ll \\n(LLu
+.if \\n(TV+\\n(AV>0 .ns
+.if \\n(TV .TX
+.if \\n(AV .AX
+.if \\n(TV+\\n(AV>0 .rs
+.ce 0
+.if \\n(TV>0 .sp 2
+.ls 1
+.if \\n(FP>0 \{\
+.      FJ
+.      nf
+.      FG
+.      fi
+.      FK
+.      nr FP 0\}
+.nf
+.WB
+.ls
+.fi
+.ad \\n(SJ
+..
+.      \"S3 - CSTR style
+.de S3
+.rs
+.sp |2.25i
+.ce 1000
+.I1
+.if \\n(NA>1 .sp .5
+.if \\n(NA>1 .I2
+.if \\n(NA>2 .sp .5
+.if \\n(NA>2 .I3
+.if \\n(NA>3 .sp .5
+.if \\n(NA>3 .I4
+.if \\n(NA>4 .sp .5
+.if \\n(NA>4 .I5
+.if \\n(NA>5 .sp .5
+.if \\n(NA>5 .I6
+.if \\n(NA>6 .sp .5
+.if \\n(NA>6 .I7
+.if \\n(NA>7 .sp .5
+.if \\n(NA>7 .I8
+.if \\n(NA>8 .sp .5
+.if \\n(NA>8 .I9
+.sp |4i
+.      \"check how long title is: can space extra .25 inch if short
+.di EZ
+.WT
+.di
+.if \\n(dn<1.5v .if \\n(NA=1 .sp .25i
+.ft 1
+Computing Science Technical Report No. \\*(MN
+.sp
+.if t .ft 3
+.if n .ul 100
+.ps 12
+.vs 15p
+.hy 0
+.WT
+.hy 14
+.ft 1
+.if n .ul 0
+.ps 10
+.vs 12p
+.sp
+.ft 1
+.A1
+.A2
+.A3
+.A4
+.A5
+.A6
+.A7
+.A8
+.A9
+.ce 0
+.sp |8.5i
+.ce 0
+\\*(DY
+.bp 0
+.ft 1
+.S2
+..
+.      \"SG - signature
+.de SG
+.br
+.KS
+.in +2u*\\n(.lu/3u
+.sp 2
+.A1
+.if \\n(NA-1 .sp 2
+.A2
+.if \\n(NA-2 .sp 2
+.A3
+.if \\n(NA-3 .sp 2
+.A4
+.if \\n(NA-4 .sp 2
+.A5
+.if \\n(NA>5 .sp 2
+.A6
+.if \\n(NA>6 .sp 2
+.A7
+.if \\n(NA>7 .sp 2
+.A8
+.if \\n(NA>8 .sp 2
+.A9
+.in
+.nf
+.sp -1
+.if \\n(.$>=1 \\$1
+.if \\n(.$>=2 \\$2
+.if \\n(.$>=3 \\$3
+.if \\n(.$>=4 \\$4
+.if \\n(.$>=5 \\$5
+.if \\n(.$>=6 \\$6
+.if \\n(.$>=7 \\$7
+.if \\n(.$>=8 \\$8
+.if \\n(.$>=9 \\$9
+.fi
+.br
+.KE
+..
+.      \"Tables.  TS - table start, TE - table end
+.de TS
+.br
+.if !\\n(1T .RT
+.ul 0
+.ti \\n(.iu
+.if t .sp 0.5
+.if n .sp
+.if \a\\$1\aH\a .TQ
+.nr IX 1
+..
+.de TQ
+.di TT
+.nr IT 1
+..
+.de TH
+.if \\n(.d>0.5v .nr T. 0
+.if \\n(.d>0.5v .T# 0
+.di
+.nr TQ \\n(.i
+.nr HT 1
+.in 0
+.mk #a
+.mk #b
+.mk #c
+.mk #d
+.mk #e
+.mk #f
+.TT
+.in \\n(TQu
+.mk #T
+..
+.de TE
+.nr IX 0
+.if \\n(IT>0 .if \\n(HT=0 .di
+.if \\n(IT>0 .if \\n(HT=0 .nr EF \\n(.u
+.if \\n(IT>0 .if \\n(HT=0 .nf
+.if \\n(IT>0 .if \\n(HT=0 .TT
+.if \\n(IT>0 .if \\n(HT=0 .if \\n(EF>0 .fi
+.nr IT 0
+.nr HT 0
+.if n .sp 1
+.if t .sp 0.5
+.rm a+ b+ c+ d+ e+ f+ g+ h+ i+ j+ k+ l+ n+ m+
+.rr 32 33 34 35 36 37 38 40 79 80 81 82
+.rr a| b| c| d| e| f| g| h| i| j| k| l| m|
+.rr a- b- c- d- e- f- g- h- i- j- k- l- m-
+..
+.so /usr/lib/tmac/tmac.sdisp
+.de KS
+.so /usr/lib/tmac/tmac.skeep
+.]K
+.rn ]J KF
+.rn ]K KS
+..
+.de KF
+.so /usr/lib/tmac/tmac.skeep
+.]J
+.rn ]K KS
+.rn ]J KF
+..
+.de EQ  \"equation, breakout and display
+.nr EF \\n(.u
+.rm EE
+.nr LE 1       \" 1 is center
+.ds EL \\$1
+.if "\\$1"L" .ds EL \\$2
+.if "\\$1"L" .nr LE 0
+.if "\\$1"C" .ds EL \\$2
+.if "\\$1"I" .nr LE 0
+.if "\\$1"I" .ds EE \\h'|10n'
+.if "\\$1"I" .if !"\\$3"" .ds EE \\h'\\$3'
+.if "\\$1"I" .ds EL \\$2
+.if \\n(YE>0 .nf
+.di EZ
+..
+.de EN  \" end of a displayed equation
+.br
+.di
+.rm EZ
+.nr ZN \\n(dn
+.if \\n(ZN>0 .if \\n(YE=0 .LP
+.if \\n(ZN=0 .if !"\\*(EL"" .nr ZN 1
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if t .sp .5
+.if "\\n(.z"" .if \\n(ZN>0 .if !\\n(nl=\\n(PE .if n .sp 1
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if t .sp .5
+.if !"\\n(.z"" .if \\n(ZN>0 .if !\\n(.d=\\n(PE .if n .sp 1
+'pc
+.if \\n(BD>0 .nr LE 0 \" can't mean centering in this case.
+.if \\n(MK>0 .if \\n(LE=1 .ds EE \\h'|10n'
+.if \\n(MK>0 .nr LE 0 \" don't center if mark/lineup
+'lt \\n(.lu
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\(ts\\*(10\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EE\\*(10\(ts\(ts\\*(EL\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP=0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\*(10\\t\\*(EL
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE>0 .tl \(ts\\*(EL\(ts\\*(10\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD=0 .tl \(ts\\*(EL\\*(EE\\*(10\(ts\(ts\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 .if \\n(BD<\\w\(ts\\*(10\(ts .nr BD \\w\(ts\\*(10\(ts
+.if \\n(EP>0 .if \\n(ZN>0 .if \\n(LE=0 .if \\n(BD>0 \!\\h'-\\\\n(.iu'\\*(EL\\h'|0'\\*(10
+.\".di EZ \" GCOS patch
+.\"\\*(10 \" GCOS patch
+.\".br \" GCOS patch
+.\".di \" GCOS patch
+.\".rm EZ \" GCOS patch
+'lt \\n(LLu
+'pc %
+.if \\n(YE>0 .if \\n(EF>0 .fi
+.rm EL 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.rr 10 11 12 13 14 15 16 17 18 19 20 21 22 23
+.if \\n(ZN>0 .if t .sp .5
+.if \\n(ZN>0 .if n .sp
+.if "\\n(.z"" .nr PE \\n(nl
+.if !"\\n(.z"" .nr PE \\n(.d
+..
+.de ME
+.nr SJ \\n(.j
+.if \\n(LL>0 .nr LT \\n(LL
+.nr YE 1
+.if \\n(PO=0 .nr PO \\n(.o
+..
+.      \"EM end up macro - process left over keep-release
+.de EM
+.br
+.if \\n(TB=0 .if t .wh -1p CM
+.if \\n(TB \&\c
+.if \\n(TB 'bp
+.if \\n(TB .NP
+.if \\n(TB .ch CM 160
+..
+.      \"NP new page
+.de NP
+.if \\n(FM+\\n(HM>=\\n(.p .tm Margins bigger than page length.
+.if \\n(FM+\\n(HM>=\\n(.p .ab
+.if \\n(FM+\\n(HM>=\\n(.p .ex
+.nr PX \\n(.s
+.nr PF \\n(.f
+.if t .CM
+.if \\n(HM=0 .nr HM 1i
+'sp \\n(HMu/2u
+.lt \\n(LTu
+.ps \\n(PS
+.ft 1
+.if \\n(PO>0 .po \\n(POu
+.PT
+.ps \\n(PX
+.ft \\n(PF
+'sp |\\n(HMu
+.nr XX 0 1
+.nr YY 0-\\n(FMu
+.ch FO 16i
+.ch FX 17i
+.ch FO -\\n(FMu
+.ch FX \\n(.pu-\\n(FMu
+.if \\n(MF .FV
+.nr MF 0
+.mk
+.os
+.ev 1
+.if \\n(TD=0 .if \\n(TC<5  .XK
+.nr TC 0
+.ns
+.ev
+.nr TQ \\n(.i
+.nr TK \\n(.u
+.if \\n(IT>0 \{\
+.      in 0
+.      nf
+.      TT
+.      in \\n(TQu
+.      if \\n(TK .fi\
+\}
+.mk #T
+.if t .if \\n(.o+\\n(LL>7.75i .tm Offset + line length exceeds 7.75 inches, too wide
+..
+.de XK
+.nr TD 1
+.nf
+.ls 1
+.in 0
+.rn KJ KL
+.KL
+.rm KL
+.if "\\n(.z"KJ" .di
+.nr TB 0
+.if "\\n(.z"KJ" .nr TB 1
+.br
+.in
+.ls
+.fi
+.nr TD 0
+..
+.de KD
+.nr KM 0
+.if "\\n(.z"KJ" .nr KM 1 \" KM is 1 if in a rediversion of keeps
+.if \\n(KM>0 \!.KD \\$1
+.if \\n(KM=0 .if \\n(.t<\\$1 .di KJ
+..
+.de PT
+.lt \\n(LLu
+.pc %
+.nr PN \\n%
+.if \\n%-1 .tl '\\*(LH'\\*(CH'\\*(RH'
+.lt \\n(.lu
+..
+.      \"FO - footer of page
+.de FO
+.rn FO FZ
+.if \\n(K1>0 .tm This memo has a multi-page cover sheet.  You are
+.if \\n(K1>0 .tm rebuked in the name of the Committee on Technical Memoranda.
+.if \\n(IT>0 .nr T. 1
+.if \\n(IT>0 .if \\n(FC=0  .T# 1
+.if \\n(IT>0 .br
+.nr FC +1
+.if \\n(NX<2 .nr WF 0
+.nr dn 0
+.if \\n(FC<=1 .if \\n(XX .XF
+.rn FZ FO
+.nr MF 0
+.if \\n(dn  .nr MF 1
+.if !\\n(WF .nr YY 0-\\n(FMu
+.if !\\n(WF .ch FO \\n(YYu
+.if !\\n(dn .nr WF 0
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX>1 .RC
+.if \\n(FC<=1 .if \\n(XX=0  .if \\n(NX<1 'bp
+.nr FC -1
+.if \\n(ML>0 .ne \\n(MLu
+..
+.      \"2C - begin double column
+.de 2C
+.MC \" default MC is double column
+..
+.de MC \" multiple columns- arg is line length
+.nr L1 \\n(LL*7/15
+.if \\n(.$>0 .nr L1 \\$1n
+.nr GW 0-1
+.if \\n(.$>1 .nr GW \\$1n
+.nr NQ \\n(LL/\\n(L1
+.if \\n(NQ<1 .nr NQ 1
+.if \\n(NQ>2 .if (\\n(LL%\\n(L1)=0 .nr NQ -1
+.if \\n(1T=0 \{\
+.      BG
+.      if n .sp 4
+.      if t .sp 2\}
+.if \\n(NX=0 .nr NX 1
+.if !\\n(NX=\\n(NQ \{\
+.      RT
+.      if \\n(NX>1 .bp
+.      mk
+.      nr NC 1
+.      po \\n(POu\}
+.if \\n(NQ>1 .hy 12
+.nr NX \\n(NQ
+.nr CW \\n(L1
+.ll \\n(CWu
+.nr FL \\n(CWu*11u/12u
+.if \\n(NX>1 .nr GW (\\n(LL-(\\n(NX*\\n(CW))/(\\n(NX-1)
+.nr RO \\n(CW+\\n(GW
+.ns
+..
+.de RC
+.if \\n(NC>=\\n(NX .C2
+.if \\n(NC<\\n(NX .C1
+.nr NC \\n(ND
+..
+.de C1
+.rt
+.po +\\n(ROu
+.nr ND \\n(NC+1
+.nr XX 0 1
+.if \\n(MF .FV
+.ch FX \\n(.pu-\\n(FMu
+.ev 1
+.if \\n(TB .XK
+.nr TC 0
+.ev
+.nr TQ \\n(.i
+.if \\n(IT>0 .in 0
+.if \\n(IT>0 .TT
+.if \\n(IT>0 .in \\n(TQu
+.mk #T
+.ns
+..
+.ch FO \\n(YYu
+.de C2
+.po \\n(POu
+'bp
+.nr ND 1
+..
+.      \"1C - return to single column format
+.de 1C
+.MC \\n(LLu
+.hy 14
+..
+.      \".de R3
+.      \".pl 102
+.      \".nr LT \\n(.l
+.      \"..
+.de MH
+Bell Laboratories
+Murray Hill, New Jersey 07974
+..
+.de PY
+Bell Laboratories
+Piscataway, New Jersey 08854
+..
+.de BT
+.nr PX \\n(.s
+.nr PF \\n(.f
+.ft 1
+.ps \\n(PS
+'lt \\n(LTu
+.po \\n(POu
+.if \\n%>0 .tl '\\*(LF'\\*(CF'\\*(RF'
+.ft \\n(PF
+.ps \\n(PX
+..
+.      \"PP - paragraph
+.de PP
+.RT
+.ne 1.1
+.if \\n(1T .sp \\n(PDu
+.ti +\\n(PIu
+..
+.      \"SH - (unnumbered) section heading
+.de SH
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+.if n .ul 1000
+..
+.      \"NH - numbered heading
+.de NH
+.RT
+.if \\n(1T .sp 1
+.if !\\n(1T .BG
+.RT
+.ne 4
+.ft 3
+.if n .ul 1000
+.nr NS \\$1
+.if !\\n(.$ .nr NS 1
+.if !\\n(NS .nr NS 1
+.nr H\\n(NS +1
+.if !\\n(NS-4 .nr H5 0
+.if !\\n(NS-3 .nr H4 0
+.if !\\n(NS-2 .nr H3 0
+.if !\\n(NS-1 .nr H2 0
+.if !\\$1 .if \\n(.$ .nr H1 1
+.ds SN \\n(H1.
+.ti \\n(.iu
+.if \\n(NS-1 .as SN \\n(H2.
+.if \\n(NS-2 .as SN \\n(H3.
+.if \\n(NS-3 .as SN \\n(H4.
+.if \\n(NS-4 .as SN \\n(H5.
+\\*(SN
+..
+.      \"BG - begin, execute at first PP
+.de BG
+.br
+.ME
+.rm ME
+.di
+.ce 0
+.nr KI 0
+.hy 14
+.nr 1T 1
+.S\\n(ST
+.rm S0
+.rm S1
+.rm S2
+.rm S3
+.rm OD
+.rm OK
+.rm TX
+.rm AX
+.rm WT
+.rm CS
+.rm TM
+.rm IM
+.rm MF
+.rm MR
+.rm RP
+.rm I1
+.rm I2
+.rm I3
+.rm I4
+.rm I5
+.rm CB
+.rm E1
+.rm E2
+.de TL
+.ft 3
+.sp
+.if n .ul 100
+.ce 100
+.LG
+\\..
+.de AU
+.ft 2
+.if n .ul 0
+.ce 100
+.sp
+.NL
+\\..
+.de AI
+.ft 1
+.ce 100
+.if n .ul 0
+.if n .sp
+.if t .sp .5
+.NL
+\\..
+.RA
+.rm RA
+.rn FJ FS
+.rn FK FE
+.nf
+.ev 1
+.ps \\n(PS-2
+.vs \\n(.s+2p
+.ev
+.if \\n(KG=0 .nr FP 0 
+.if \\n(GA>1 .if \\n(KG=0 .nr GA 0 \" next UNIX must be flagged.
+.nr KG 0 
+.if \\n(FP>0 .FS
+.if \\n(FP>0 .FG
+.if \\n(FP>0 .FE
+.br
+.if \\n(TV>0 .if n .sp 2
+.if \\n(TV>0 .if t .sp 1
+.fi
+.ll \\n(LLu
+..
+.de RA \"redefine abstract macros
+.de AB
+.br
+.if !\\n(1T .BG
+.ce 1
+.sp 1
+.if \\n(.$=0 ABSTRACT
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no"  \\$1
+.if \\n(.$=0 .sp
+.if \\n(.$>0 .if !"\\$1"-" .if !"\\$1"no" .sp
+.sp 1
+.nr AJ 1
+.in +\\n(.lu/12u
+.ll -\\n(.lu/12u
+.RT
+\\..
+.de AE
+.nr AJ 0
+.br
+.in 0
+.ll \\n(LLu
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+\\..
+..
+.      \"IP - indented paragraph
+.de IP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.ne 3v
+.if \\n(.$-1 .nr I\\n(IR \\$2n
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(I\\n(IRu \\n(TYuR
+.if \\n(.$>0 \{\
+.ti -\\n(I\\n(IRu
+\&\\$1\t\c\}
+..
+.      \"LP - left aligned (block) paragraph
+.de LP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+.ne 1.1
+..
+.de QP
+.ti \\n(.iu
+.RT
+.if \\n(1T .sp \\n(PDu
+.ne 1.1
+.nr QP 1
+.in +\\n(QIu
+.ll -\\n(QIu
+.ti \\n(.iu
+..
+.      \"IE - synonym for .LP
+.de IE
+.LP
+..
+.      \"LB - label paragraph
+.de LB
+.in +\\n(I\\n(IRu
+.ta \\n(I\\n(IRu
+.if \\n(.$ .ti -\\n(I\\n(IRu
+.if \\n(.$ \&\\$1\t\c
+..
+.de XP
+.RT
+.if !\\n(IP .nr IP +1
+.sp \\n(PDu
+.ne 3
+.if \\n(.$=3 .nr I\\n(IR \\$3n
+.if \\n(.$=4 .nr I\\n(IR \\$4n
+.nr J\\n(IR \\n(IRu/2u
+.if \\n(.$=4 .nr J\\n(IR \\$3n
+.in +\\n(I\\n(IRu
+.ta \\n(J\\n(IRu \\n(I\\n(IRu
+.ti -\\n(I\\n(IRu
+\0\\$1\t\\$2\t\c
+..
+.      \"RS - prepare for double indenting
+.de RS
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IP>0 .in +\\n(I\\n(IRu
+.nr IR +1
+.nr I\\n(IR \\n(PIu
+.in +\\n(I\\n(IRu
+.nr TY \\n(TZ-\\n(.i
+.ta \\n(TYuR
+..
+.      \"RE - retreat to the left
+.de RE
+.nr IS \\n(IP
+.RT
+.nr IP \\n(IS
+.if \\n(IR>0 .nr IR -1
+.if \\n(IP<=0 .in -\\n(I\\n(IRu
+..
+.de TC
+.nr TZ \\n(.lu
+.if \\n(.$ .nr TZ \\$1n
+.ta \\n(TZuR
+..
+.de TD
+.LP
+.nr TZ 0
+..
+.      \"CM - cut mark
+.de CM
+.po 0
+.lt 7.6i
+.ft 1
+.ps 10
+.vs 4p
+.tl '--''--'
+.po
+.vs
+.lt
+.ps
+.ft
+..
+.      \"B - bold font
+.de B
+.nr PQ \\n(.f
+.if t .ft 3
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.      \"R - Roman font
+.de R
+.if n .ul 0
+.ft 1
+..
+.      \"I - italic font
+.de I
+.nr PQ \\n(.f
+.if t .ft 2
+.if "\\$1"" .if n .ul 1000
+.if !"\\$1"" .if n .ul 1
+.if t .if !"\\$1"" \&\\$1\|\\f\\n(PQ\\$2
+.if n .if \\n(.$=1 \&\\$1
+.if n .if \\n(.$>1 \&\\$1\\c
+.if n .if \\n(.$>1 \\&\\$2
+..
+.      \"TA - tabs set in ens or chars
+.de TA
+.ta \\$1n \\$2n \\$3n \\$4n \\$5n \\$6n \\$7n \\$8n \\$9n
+..
+.      \"SM - make smaller size
+.de SM
+.if \\n(.$>0 \&\\$3\s-2\\$1\s0\\$2
+.if \\n(.$=0 .ps -2
+..
+.      \"LG - make larger size
+.de LG
+.ps +2
+..
+.      \"NL - return to normal size
+.de NL
+.ps \\n(PS
+..
+.      \"DA - force date; ND - no date or new date.
+.de DA
+.if \\n(.$ .ds DY \\$1 \\$2 \\$3 \\$4
+.ds CF \\*(DY
+..
+.de ND
+.ds DY \\$1 \\$2 \\$3 \\$4
+.rm CF
+..
+.if \n(mo-0 .ds MO January
+.if \n(mo-1 .ds MO February
+.if \n(mo-2 .ds MO March
+.if \n(mo-3 .ds MO April
+.if \n(mo-4 .ds MO May
+.if \n(mo-5 .ds MO June
+.if \n(mo-6 .ds MO July
+.if \n(mo-7 .ds MO August
+.if \n(mo-8 .ds MO September
+.if \n(mo-9 .ds MO October
+.if \n(mo-10 .ds MO November
+.if \n(mo-11 .ds MO December
+.if \n(dw-0 .ds DW Sunday
+.if \n(dw-1 .ds DW Monday
+.if \n(dw-2 .ds DW Tuesday
+.if \n(dw-3 .ds DW Wednesday
+.if \n(dw-4 .ds DW Thursday
+.if \n(dw-5 .ds DW Friday
+.if \n(dw-6 .ds DW Saturday
+.ds DY \*(MO \n(dy, 19\n(yr
+.IZ
+.rm IZ
+.rm MO
+.de FN
+.FS
+..
+.      \"FS - begin footnote
+.de FJ
+'ce 0
+.di
+.ev1
+.ll \\n(FLu
+.da FF
+.br
+.if \\n(IF>0 .tm Footnote within footnote-illegal.
+.nr IF 1
+.if !\\n+(XX-1 .FA
+..
+.      \"FE - footnote end
+.de FK
+.br
+.in 0
+.nr IF 0
+.di
+.ev
+.if !\\n(XX-1 .nr dn +\\n(.v
+.nr YY -\\n(dn
+.if \\n(NX=0 .nr WF 1
+.if \\n(dl>\\n(CW .nr WF 1
+.if (\\n(nl+\\n(.v)<=(\\n(.p+\\n(YY) .ch FO \\n(YYu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl>(\\n(HM+1.5v) .ch FO \\n(nlu+\\n(.vu
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl+\\n(FM+1v>\\n(.p .ch FX \\n(.pu-\\n(FMu+2v
+.if (\\n(nl+\\n(.v)>(\\n(.p+\\n(YY) .if \\n(nl<=(\\n(HM+1.5v) .ch FO \\n(HMu+(4u*\\n(.vu)
+..
+.\"    First page footer.
+.de FS
+.ev1
+.br
+.ll \\n(FLu
+.da FG
+..
+.de FE
+.br
+.di
+.nr FP \\n(dn
+.if \\n(1T=0 .nr KG 1 \"not in abstract repeat next page.
+.if "\\n(.z"OD" .nr KG 0 \" if in OK, don't repeat.
+.ev
+..
+.de FA
+.if n __________________________
+.if t \l'1i'
+.br
+..
+.de FV
+.FS
+.nf
+.ls 1
+.FY
+.ls
+.fi
+.FE
+..
+.de FX
+.if \\n(XX>0 .di FY
+.if \\n(XX>0 .ns
+..
+.de XF
+.if \\n(nlu+1v>(\\n(.pu-\\n(FMu) .ch FX \\n(nlu+1.9v
+.ev1
+.nf
+.ls 1
+.FF
+.rm FF
+.nr XX 0 1
+.br
+.ls
+.di
+.fi
+.ev
+..
+.de FL
+.ev1
+.nr FL \\$1n
+.ll \\$1
+.ev
+..
+.de HO
+Bell Laboratories
+Holmdel, New Jersey 07733
+..
+.de WH
+Bell Laboratories
+Whippany, New Jersey 07981
+..
+.de IH
+Bell Laboratories
+Naperville, Illinois 60540
+..
+.de UL \" underline argument, don't italicize
+.if t \\$1\l'|0\(ul'\\$2
+.if n .I \\$1 \\$2
+..
+.em EM
+. \"  ACCENTS  say \*'e or \*`e to get e acute or e grave
+.ds ' \h'\w'e'u*4/10'\z\(aa\h'-\w'e'u*4/10'
+.ds ` \h'\w'e'u*4/10'\z\(ga\h'-\w'e'u*4/10'
+. \"  UMLAUT  \*:u, etc.
+.ds : \v'-0.6m'\h'(1u-(\\n(.fu%2u))*0.13m+0.06m'\z.\h'0.2m'\z.\h'-((1u-(\\n(.fu%2u))*0.13m+0.26m)'\v'0.6m'
+. \" TILDE and CIRCUMFLEX
+.ds ^ \\k:\h'-\\n(.fu+1u/2u*2u+\\n(.fu-1u*0.13m+0.06m'\z^\h'|\\n:u'
+.ds ~ \\k:\h'-\\n(.fu+1u/2u*2u+\\n(.fu-1u*0.13m+0.06m'\z~\h'|\\n:u'
+.      \" czech v symbol
+.ds C \\k:\\h'+\\w'e'u/4u'\\v'-0.6m'\\s6v\\s0\\v'0.6m'\\h'|\\n:u'
+.ds v \\k:\\h'+\\w'e'u/4u'\\v'-0.6m'\\s6v\\s0\\v'0.6m'\\h'|\\n:u'
+.              \" cedilla
+.ds , \\k:\\h'\\w'c'u*0.4u'\\z,\\h'|\\n:u'
+.so /usr/lib/tmac/tmac.srefs
+.if n .ds [. [
+.if t .ds [. \s-2\v'-.4m'\f1
+.if n .ds .] ]
+.if t .ds .] \v'.4m'\s+2\fP
+.if n .ds [o ""
+.if n .ds [c ""
+.if t .ds [o ``
+.if t .ds [c ''
+.de UX
+.ie \\n(GA>0 \\$2\s-2UNIX\s0\\$1
+.el \{\
+.if n \\$2UNIX\\$1*
+.if t \\$2\s-2UNIX\\s0\\$1\\f1\(dg\\fP
+.FS
+.if n *UNIX
+.if t \(dgUNIX
+.ie \\$3=1 is a Footnote of Bell Laboratories.
+.el is a Trademark of Bell Laboratories.
+.FE
+.nr GA 1\}
+..
+.de US
+the
+.UX
+operating system
+..
+.de QS
+.br
+.LP
+.in +\\n(QIu
+.ll -\\n(QIu
+..
+.de QE
+.br
+.ll +\\n(QIu
+.in -\\n(QIu
+.LP
+..
+.de B1 \" begin boxed stuff
+.br
+.di BB
+.nr BC 0
+.if "\\$1"C" .nr BC 1
+.nr BE 1
+..
+.de B2 \" end boxed stuff
+.br
+.nr BI 1n
+.if \\n(.$>0 .nr BI \\$1n
+.di
+.nr BE 0
+.nr BW \\n(dl
+.nr BH \\n(dn
+.ne \\n(BHu+\\n(.Vu
+.nr BQ \\n(.j
+.nf
+.ti 0
+.if \\n(BC>0 .in +(\\n(.lu-\\n(BWu)/2u
+.in +\\n(BIu
+.BB
+.in -\\n(BIu
+.nr BW +2*\\n(BI
+.sp -1
+\l'\\n(BWu\(ul'\L'-\\n(BHu'\l'|0\(ul'\h'|0'\L'\\n(BHu'
+.if \\n(BC>0 .in -(\\n(.lu-\\n(BWu)/2u
+.if \\n(BQ .fi
+.br
+..
+.de AT
+.nf
+.sp
+.ne 2
+Attached:
+..
+.de CT
+.nf
+.sp
+.ne 2
+.ie \\n(.$ Copy to \\$1:
+.el Copy to:
+..
+.de BX
+.if t \(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul'
+.if n \(br\\kA\|\\$1\|\\kB\(br\v'-1v'\h'|\\nBu'\l'|\\nAu'\v'1v'\l'|\\nAu'
+..
diff --git a/doc/7thEdMan/tmac.scover b/doc/7thEdMan/tmac.scover
new file mode 100644 (file)
index 0000000..bc15e02
--- /dev/null
@@ -0,0 +1,323 @@
+.      \"OK - "other keywords" for cover sheet.
+.de OK
+.br
+.di
+.di OD
+.nf
+.ft 3
+..
+.      \"CS - spew out cover sheet
+.de CS
+.br
+.if \\n(AJ>0 .tm Abstract not finished, AE assumed.
+.if \\n(AJ>0 .AE
+.di
+.if t .po 0.5i
+.ft 2
+.nr IB \\n(.b
+.ft P
+.nr K1 1
+.if t .sp |.4i
+.if t .lg
+.ll 7.0i
+.vs 12p
+.nf
+.if t \h'7n'\s24\(bs\s12\f3  Bell Laboratories        \s16\f1Cover Sheet for Technical Memorandum
+.if n Bell Laboratories        Cover Sheet for Technical Memorandum
+.if t .sp .5v
+.if n .sp
+.if t \s6\l'7i'
+.fi
+.ps 9
+.ft 2
+.if t .sp 2p
+.if \\n(.$<=6 The information contained herein is for the use of employees of Bell Laboratories and is not for publication.  (See GEI 13.9-3)\p
+.if \\n(.$>6 Warning: studying this document may cause drowsiness.  Do not read before driving or operating machinery.  (See GEI 13.9-3)\p
+.ft 1
+.nf
+.if \\n(IB>0 .bd 2 \\n(IB
+.if t \s6\l'7i'
+.if t .sp .5v
+.if n .sp
+.if t .ll 4.0i
+.if n .ll 30
+.if t .po 1.0i
+.ps 9
+.if t .ta 0.5i 4.5i 4.9i
+.if n .ta 9 39 46
+.mk
+Title- \f3\s10
+.rt
+.if t .in 0.5i
+.if n .in 10
+.hy 0
+.WT
+.hy 14
+.br
+.rt
+.ll \\n(LLu
+.if t .in 4.5i
+.if n .in 40
+.nf
+\s9\f1Date- \s10\f3
+.rt
+.if t .in 4.9i
+.if n .in 47
+\\*(DY
+.sp
+.if t .ti 4.5i
+.if n .ti 40
+.mk
+\s9\f1TM- \f3\s10
+.br
+.rt
+.CZ \\*(MN
+.in 0
+.sp |\\n(.hu+1v
+.mk
+\s9\f1Other Keywords- \f3
+.rt
+.if t .in 1.1i
+.if n .in 20
+.OD
+.in 0
+.if t .sp .7i
+.if n .sp 3
+.ps 9
+.if t .ta 1.8i 3.3i 4.3i
+.if n .ta 19 34 44
+.ft 1
+.mk
+.fi
+.ll 6.7i
+.in 4.6i
+.ti 0
+.nr SJ \\n(.j
+.na
+Author Location        Extension       Charging Case- \s10\f3\\*(CA
+.ps 10
+.ti 4.3i
+\f1\s9Filing Case- \s10\f3\\*(CC
+.nf
+.in 0
+.ad \\n(SJ
+.rt
+.sp 1
+.CB 1
+.if \\n(NA-1 .CB 2
+.if \\n(NA-2 .CB 3
+.if \\n(NA-3 .CB 4
+.if \\n(NA-4 .CB 5
+.if \\n(NA-5 .CB 6
+.if \\n(NA-6 .CB 7
+.if \\n(NA-7 .CB 8
+.if \\n(NA-8 .CB 9
+.ft 1
+.rm OK OD R1 E1 R2 E2 R3 E3 R4 E4 AB AE
+.ds K1 \\$1
+.ds K2 \\$2
+.ds K3 \\$3
+.ds K4 \\$4
+.ds K5 \\$5
+.ds K6 \\$6
+.wh 9.8i CG
+.ch FO 16i
+.if t .sp .4i
+.if n .sp 2
+.ls 1
+.pn 2
+.WB
+.rm WB
+.ls
+.br
+.if 9.7i-\\n(nlu-\\n(FPu-1v>0 .sp 9.7i-\\n(nlu-\\n(FPu-1v
+.if \\n(FP>0 .FA
+.FG
+.nr K1 0
+.if \\n(GA=1 .nr GA 2
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.bp 1
+.rm CG
+.if t .po \\n(POu
+..
+.      \" CG - write bottom box on cover sheet
+.de CG
+.if t .po 0.5i
+.vs 12p
+.ch FO 12i
+.ch FX 12i
+.if t .ll 7i
+.br
+.if t \l'7i'
+.if t .ta 1.4i 2.8i 4.2i
+.if n .ta 14 29 44
+.if t .sp 8p
+.if n .sp
+Pages Text   \\*(K1    Other   \\*(K2  Total   \\*(K3
+.if t .sp 8p
+.if n .sp 
+.if t .po .5i
+.if t No. Figures   \\*(K4     No. Tables   \\*(K5     No. Refs.   \\*(K6      \b'|||||\ \ '
+.if n No. Figures   \\*(K4     No. Tables   \\*(K5     No. Refs.   \\*(K6
+.br
+.if t .po .5i
+.if t \l'7i'
+.ps 7
+.br
+.if n .sp
+.rm K1
+.rm K2
+.rm K3
+.rm K4
+.rm K5
+.rm K6
+.if t .po .5i
+.if t .tl 'E-1932-U (6-73)'SEE REVERSE SIDE FOR DISTRIBUTION LIST''
+.if n .tl 'E-1932-U (6-73)  SEE REVERSE SIDE FOR DISTRIBUTION LIST'''
+.if t .po 0.5i
+.ll \\n(LLu
+.ps 10
+.ch CG 12i
+.if \\n(K1>0 .bp
+..
+.      \"CB - help with cover sheet
+.de CB
+.br
+.mk
+.A\\$1
+.rt
+\&     \\*(R\\$1       \\*(E\\$1
+.br
+..
+.de CZ
+.br
+.if !"\\$1"" \\$1
+.br
+.if !"\\$2"" \\$2
+.br
+.if !"\\$3"" \\$3
+.br
+.if !"\\$4"" \\$4
+.br
+.if !"\\$5"" \\$5
+.br
+.if !"\\$6"" \\$6
+.br
+.if !"\\$7"" \\$7
+.br
+.if !"\\$8"" \\$8
+.br
+.if !"\\$9"" \\$9
+..
+.      \"S1 - tm style 
+.de S1
+.br
+.if t .ta 4.75i
+.if n .ta 46
+.ll 80
+.ps 36
+.br
+.if t .vs .35i
+.if t \t\(bs
+.br
+.if n .sp 24p
+.ps 12
+.br
+.ft 3
+\tBell Laboratories
+.ft 1
+.nr SJ \\n(.j
+.na
+.br
+.ps 8
+.vs 12p
+.sp 2v
+.mk
+.ll
+.ll 4.0i
+Subject:
+.ft 3
+.br
+.rt
+.if n .in +9
+.if t .in +\w'Subject: 'u
+.ps
+.nf
+.hy 0
+.WT
+.hy 14
+.ft 1
+.fi
+.in 0
+.if \\n(MC>0 \\s8Case- \\*(CA\\s10
+.if \\n(MG>0 --\s8 File- \\*(CC\\s10
+.br
+.rt
+.if n .ll 70
+.if t .ll 6.5i
+.if t .in 5.10i
+.if n .in 52
+.ps 8
+.ti -6n
+.ta 6n
+date:\t\\s\\n(PS\\f3\\*(DY
+.sp
+.ft 1
+.ps 8
+.mk
+.ti -6n
+from:
+.ps
+.br
+.rt
+.nf
+.ft 3
+.A1
+.if \\n(NA>1 .A2
+.if \\n(NA>2 .A3
+.if \\n(NA>3 .A4
+.if \\n(NA>4 .A5
+.if \\n(NA>5 .A6
+.if \\n(NA>6 .A7
+.if \\n(NA>7 .A8
+.if \\n(NA>8 .A9
+.ft 1
+.sp
+.mk
+.ps 8
+.ti -6n
+.ft 1
+.if \\n(IM=0 .if \\n(MM .if "\\*(MQ"" \{\
+.if \\n(MN=0 .ds MQ TM:
+.if \\n(MN=1 .ds MQ MF:
+.if \\n(MN=2 .ds MQ MR:
+.if \\n(MN=3 .ds MQ EN:\}
+\\*(MQ
+.br
+.ti \\n(.iu
+.rt
+.ps
+.ft 3
+.hy 0
+.ll 20i
+.if t .ll 7.75i-\\n(.ou
+.fi
+.na
+.if \\n(MM .CZ \\*(MN
+.hy 14
+.nf
+.ft 1
+.ll \\n(LLu
+.in
+.sp |\\n(.hu
+.if \\n(IM=0 .sp
+.ad \\n(SJ
+.ce
+.ft 2
+.if \\n(IM=0 \\*(QF
+.ft 1
+.ce 0
+.if \\n(IM=0 .sp
+.fi
+..
diff --git a/doc/7thEdMan/tmac.sdisp b/doc/7thEdMan/tmac.sdisp
new file mode 100644 (file)
index 0000000..644f872
--- /dev/null
@@ -0,0 +1,60 @@
+.      \"DS - display.  If .DS C, center; L, left-adjust; I, indent.
+.de DS
+.KS
+.nf
+.\\$1D \\$2 \\$1
+.ft 1
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+..
+.de D
+.ID \\$1
+..
+.de CD
+.XD
+.ce 1000
+..
+.de ID
+.XD
+.if t .in +0.5i
+.if n .in +8
+.if \\n(.$ .if !"\\$1"I" .if !"\\$1"" .in \\n(OIu
+.if \\n(.$ .if !"\\$1"I" .if !"\\$1"" .in +\\$1n
+..
+.de LD
+.XD
+..
+.de XD
+.nf
+.nr OI \\n(.i
+.if t .sp 0.5
+.if n .sp 1
+..
+.de BD \" block display: save everything, then center it.
+.XD
+.nr BD 1
+.nf
+.in \\n(OIu
+.di DD
+..
+.      \"DE - display end
+.de DE
+.ce 0
+.if \\n(BD>0 .DF
+.nr BD 0
+.in \\n(OIu
+.KE
+.if t .sp 0.5
+.if n .sp 1
+.fi
+..
+.de DF \" finish a block display to be recentered.
+.di
+.if \\n(dl>\\n(BD .nr BD \\n(dl
+.if \\n(BD<\\n(.l .in (\\n(.lu-\\n(BDu)/2u
+.nr EI \\n(.l-\\n(.i
+.ta \\n(EIuR
+.DD
+.in \\n(OIu
+..
diff --git a/doc/7thEdMan/tmac.skeep b/doc/7thEdMan/tmac.skeep
new file mode 100644 (file)
index 0000000..9e7a373
--- /dev/null
@@ -0,0 +1,80 @@
+.      \"KS keep - for keep release features. As in IFM
+.de ]K
+.nr KN \\n(.u
+.if \\n(IK=0 .if \\n(IF=0 .KQ
+.nr IK +1
+..
+.      \"KQ - real keep processor
+.de KQ
+.br
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 0
+..
+.      \"KF - floating keep
+.de ]J
+.nr KN \\n(.u
+.if !\\n(IK .FQ
+.nr IK +1
+..
+.      \"FQ real floating keep processor
+.de FQ
+.nr KI \\n(.i
+.ev 2
+.br
+.in \\n(KIu
+.ps \\n(PS
+.if \\n(VS>40 .vs \\n(VSu
+.if \\n(VS<=39 .vs \\n(VSp
+.ll \\n(LLu
+.lt \\n(LTu
+.if \\n(NX>1 .ll \\n(CWu
+.if \\n(NX>1 .lt \\n(CWu
+.di KK
+.nr TB 1
+..
+.      \"KE release - everything between keep and release is together
+.de KE
+.if \\n(IK .if !\\n(IK-1 .if \\n(IF=0 .RQ
+.if \\n(IK .nr IK -1
+..
+.      \"RQ real release
+.de RQ
+.br
+.di
+.nr NF 0
+.if \\n(dn-\\n(.t .nr NF 1
+.if \\n(TC .nr NF 1
+.if \\n(NF .if !\\n(TB .sp 200
+.if !\\n(NF .if \\n(TB .nr TB 0
+.nf
+.rs
+.nr TC 5
+.in 0
+.ls 1
+.if \\n(TB=0 .ev
+.if \\n(TB=0 .br
+.if \\n(TB=0 .ev 2
+.if \\n(TB=0 .KK
+.ls
+.ce 0
+.if \\n(TB=0 .rm KK
+.if \\n(TB .da KJ
+.if \\n(TB \!.KD \\n(dn
+.if \\n(TB .KK
+.if \\n(TB .di
+.nr TC \\n(TB
+.if \\n(KN .fi
+.in
+.ev
+..
diff --git a/doc/7thEdMan/tmac.srefs b/doc/7thEdMan/tmac.srefs
new file mode 100644 (file)
index 0000000..2357590
--- /dev/null
@@ -0,0 +1,149 @@
+.\" REFER macros .... citations
+.de []
+.][ \\$1
+..
+.de ][
+.if \\$1>5 .tm Bad arg to []
+.[\\$1
+..
+.if n .ds [. [
+.if t .ds [. \s-2\v'-.4m'\f1
+.if n .ds .] ]
+.if t .ds .] \v'.4m'\s+2\fP
+.if n .ds [o ""
+.if n .ds [c ""
+.if t .ds [o ``
+.if t .ds [c ''
+.\" the next lines deal with the problem of .[1] or [1].
+.\" refer will write "linexxx\*(<.[1]\*(>.
+.\" and either "<." or ">." should produce the .;
+.\" similarly for ,
+.if n .ds >. .
+.if t .ds <. .
+.if n .ds >, ,
+.if t .ds <, ,
+.de [5 \" tm style
+.FS
+.IP "\\*([F.\0"
+\\*([A, \\f2\\*([T\\f1,
+.ie \\n(TN \\*([M.
+.el Bell Laboratories internal memorandum (\\*([D).
+.RT
+.FE
+..
+.de [0 \" other
+.FS
+.nr [: 0
+.if !"\\*([F"" .IP "\\*([F.\0"
+.if !"\\*([A"" \{.nr [: 1
+\\*([A\c\}
+.if !"\\*([T"" \{.if \\n([:>0 ,
+.nr [: 1
+\\f2\\*([T\\f1\c\}
+.if !"\\*([O""\{.if \\n([:>0 ,
+.nr [: 1
+.if \\n([O>0 .nr [: 0
+\\*([O\c
+.if \\n([O>0 \& \c\}
+.ie !"\\*([D"" \{.if \\n([:>0 ,
+.nr [: 1
+\\*([D\c\}
+.if \\n([:>0 \&.
+.RT
+.FE
+..
+.de [1 \" journal article
+.FS
+.if !"\\*([F"" .IP "\\*([F.\0"
+.if !"\\*([A"" \\*([A,
+.if !"\\*([T"" \\*([o\\*([T,\\*([c
+\\f2\\*([J\\f1\c
+.if !"\\*([V"" .if n \& Vol.\&\c
+.if !"\\*([V"" \& \\f3\\*([V\\f1\c
+.if !"\\*([N"" (\\*([N)\c
+.if !"\\*([P"" \{\
+.ie \\n([P>0 , pp.\c
+.el , p.\c
+\\*([P\c\}
+.if !"\\*([I"" .if "\\*([R"" , \\*([I\c
+.if !"\\*([O"" .if \\n([O=0 , \\*([O\c
+.if !"\\*([D"" \& (\\*([D)\c
+\&.
+.if !"\\*([O"" .if \\n([O>0  \\*([O
+.RT
+.FE
+..
+.de [2 \" book
+.FS
+.if !"\\*([F"" .IP "\\*([F.\0"
+.if !"\\*([A"" \\*([A,
+.if !"\\*([T"" \\f2\\*([T,\\f1
+\\*([I\c
+.if !"\\*([C"" , \\*([C\c
+.if !"\\*([D"" \& (\\*([D)\c
+\&.
+.if !"\\*([G"" Gov't. ordering no. \\*([G.
+.if !"\\*([O"" \\*([O
+.RT
+.FE
+..
+.de [4 \" report
+.FS
+.if !"\\*([F"" .IP "\\*([F.\0"
+\\*([A, \\*([o\\*([T,\\*([c
+\\*([R\c
+.if !"\\*([G"" \& (\\*([G)\c
+.if !"\\*([I"" ,  \\*([I\c
+.if !"\\*([C"" ,  \\*([C\c
+.if !"\\*[D"" \& (\\*[D)\c
+\&.
+.if !"\\*([O"" \\*([O
+.RT
+.FE
+..
+.de [3 \" article in book
+.FS
+.if !"\\*([F"" .IP "\\*([F.\0"
+.if !"\\*([A"" \\*([A,
+.if !"\\*([T"" \\*([o\\*([T,\\*([c
+.if !"\\*([P"" pp. \\*([P
+in \\f2\\*([B\\f1\c
+.if !"\\*([E"" , ed. \\*([E\c
+.if !"\\*([I"" , \\*([I\c
+.if !"\\*([C"" , \\*([C\c
+.if !"\\*([D"" \& (\\*([D)\c
+\&.
+.if !"\\*([O"" \\*([O
+.RT
+.FE
+..
+.de ]<
+.[<
+..
+.de [<
+.SH
+References
+.LP
+.rm FS FE
+..
+.de [>
+.]>
+..
+.de ]>
+.sp
+..
+.de ]-
+.[-
+..
+.de [-
+.rm [V [P [A [T
+.rm [N [C [B [O
+.rm [R [I [E [D
+..
+.de ]]
+this is never
+executed
+and just
+uses up an end-of-file
+bug.
+..
diff --git a/doc/7thEdMan/v7vol1.pdf b/doc/7thEdMan/v7vol1.pdf
new file mode 100644 (file)
index 0000000..e9fa75f
Binary files /dev/null and b/doc/7thEdMan/v7vol1.pdf differ
diff --git a/doc/7thEdMan/v7vol2a.pdf b/doc/7thEdMan/v7vol2a.pdf
new file mode 100644 (file)
index 0000000..fa293b6
Binary files /dev/null and b/doc/7thEdMan/v7vol2a.pdf differ
diff --git a/doc/7thEdMan/v7vol2b.pdf b/doc/7thEdMan/v7vol2b.pdf
new file mode 100644 (file)
index 0000000..1136c4f
Binary files /dev/null and b/doc/7thEdMan/v7vol2b.pdf differ
diff --git a/doc/7thEdMan/vol1/man0.bun b/doc/7thEdMan/vol1/man0.bun
new file mode 100644 (file)
index 0000000..6d1a2de
--- /dev/null
@@ -0,0 +1,2167 @@
+# To unbundle, run this file
+echo intro
+sed 's/.//' >intro <<'//GO.SYSIN DD intro'
+-.de IR
+-\fI\\$1\^\fR\\$2
+-..
+-.de RI
+-\fR\\$1\fI\\$2\^\fR\\$3
+-..
+-.TL
+-INTRODUCTION TO VOLUME 1
+-.af PN i
+-.pn 3
+-.LP
+-This volume gives descriptions of the publicly available
+-features of the
+-.UX
+-system.
+-It does not attempt to provide perspective or tutorial
+-information upon the
+-.UX
+-operating system,
+-its facilities, or its implementation.
+-Various documents on those topics are contained in
+-Volume 2.
+-In particular,
+-for an overview see `The
+-.UX
+-Time-Sharing System'
+-by Ritchie and Thompson; for a tutorial see
+-`\s8UNIX\s10 for Beginners' by Kernighan.
+-.LP
+-Within the area it surveys, this volume attempts
+-to be timely, complete and concise.
+-Where the latter two objectives conflict,
+-the obvious is often left unsaid in favor of brevity.
+-It is intended that each program be described
+-as it is, not as it should be.
+-Inevitably, this means that
+-various sections will soon be out of date.
+-.LP
+-The volume is divided into
+-eight sections:
+-.DS
+-1.    Commands
+-2.    System calls
+-3.    Subroutines
+-4.    Special files
+-5.    File formats and conventions
+-6.    Games
+-7.    Macro packages and language conventions
+-8.    Maintenance
+-.DE
+-Commands are programs intended to be invoked directly by
+-the user, in contradistinction to subroutines, which are
+-intended to be called by the user's programs.
+-Commands generally reside in directory
+-.I /bin
+-(for
+-.IR bin \|ary
+-programs).
+-Some programs also reside in
+-.I
+-/\|usr/\|bin,
+-.R
+-to save space in
+-.I  /bin.
+-These directories are searched automatically by the command interpreter.
+-.LP
+-System calls are entries into the
+-.UX
+-supervisor.
+-Every system call has one or more C language interfaces
+-described in section 2.
+-The underlying assembly language interface, coded with opcode
+-.I sys,
+-a synonym for
+-.I trap,
+-is given as well.
+-.LP
+-An assortment
+-of subroutines is available;
+-they are described in section 3.
+-The primary libraries in which they are kept are described in
+-.IR intro (3).
+-The functions are described in terms of C, but most will
+-work with Fortran as well.
+-.LP
+-The special files section 4 discusses the characteristics of
+-each system `file' that actually refers to an I/O device.
+-The names in this
+-section refer to the DEC device names for the
+-hardware,
+-instead of the names of
+-the special files themselves.
+-.LP
+-The file formats and conventions section 5 documents the structure of particular
+-kinds of files; for example, the form of the output of the loader and
+-assembler is given.  Excluded are files used by only one command,
+-for example the assembler's intermediate files.
+-.LP
+-Games have been relegated to section 6 to keep them from contaminating
+-the more staid information of section 1.
+-.LP
+-Section 7 is a miscellaneous collection of information necessary to
+-writing in various specialized languages:
+-character codes, 
+-macro packages for typesetting,
+-etc.
+-.LP
+-The maintenance 
+-section 8 discusses procedures not intended
+-for use by the ordinary user.
+-These procedures often involve use of commands
+-of section 1, where an attempt has been made to
+-single out peculiarly maintenance-flavored commands
+-by marking them 1M.
+-.LP
+-Each section consists of a number of independent
+-entries of a page or so each.
+-The name of the entry is in the upper corners of its pages,
+-together with the section number, and sometimes a
+-letter characteristic of a subcategory, e.g. graphics is 1G,
+-and the math library is 3M.
+-Entries within each section are
+-alphabetized.
+-The page numbers of each entry start at 1;
+-it is infeasible to number consecutively the pages of 
+-a document like this that is republished in many variant forms.
+-.LP
+-All entries are based on a common format,
+-not all of whose subsections will always appear.
+-.RS
+-.LP
+-The
+-.I name
+-subsection lists the exact names of the commands and subroutines
+-covered under the entry and gives
+-a very short description of their purpose.
+-.LP
+-The
+-.IR synopsis ""
+-summarizes the use of the
+-program being described.
+-A few conventions are used, particularly in the
+-Commands subsection:
+-.LP
+-.RS
+-.B Boldface
+-words are considered literals, and
+-are typed just as they appear.
+-.LP
+-Square brackets [ ] around an argument
+-indicate that the argument is optional.
+-When an argument is given as `name', it always
+-refers to a file name.
+-.LP
+-Ellipses `.\|.\|.' are used to show that the previous argument-prototype
+-may be repeated.
+-.LP
+-A final convention is used by the commands themselves.
+-An argument beginning with a minus sign `\-'
+-is often taken to mean some sort of option-specifying argument
+-even if it appears in a position where a file name
+-could appear.  Therefore, it is unwise to have files
+-whose names begin with `\-'.
+-.LP
+-.RE
+-The
+-.IR description ""
+-subsection discusses in detail the subject at hand.
+-.LP
+-The
+-.IR files ""
+-subsection gives the names of files which are
+-built into the program.
+-.LP
+-A
+-.I
+-see also
+-.R
+-subsection gives pointers to related information.
+-.LP
+-A
+-.I  diagnostics
+-subsection discusses
+-the diagnostic indications which may be produced.
+-Messages which are intended to be self-explanatory
+-are not listed.
+-.LP
+-The
+-.IR bugs ""
+-subsection gives
+-known bugs and sometimes deficiencies.
+-Occasionally also the suggested fix is
+-described.
+-.LP
+-In section 2 an
+-.I assembler
+-subsection carries the assembly language system interface.
+-.LP
+-.RE
+-At the beginning of the volume is a table of contents,
+-organized by section and alphabetically within each section.
+-There is also a permuted index derived from the table of contents.
+-Within each index entry, the title
+-of the writeup to which
+-it refers is followed by the appropriate section number in parentheses.
+-This fact is important because there is considerable
+-name duplication among the sections,
+-arising principally from commands which
+-exist only to exercise a particular system call.
+-.SH
+-HOW TO GET STARTED
+-.LP
+-This section sketches the basic information
+-you need to get started on \*(UX:
+-how to log in and log out,
+-how to communicate through your terminal,
+-and how to run a program.
+-See `\c
+-.UX
+-for Beginners'
+-in Volume 2 for a more complete introduction
+-to the system.
+-.LP
+-.I
+-Logging in.\ \ 
+-.R
+-You must call
+-.UX
+-from an appropriate terminal.
+-.UX
+-terminals are typified by the TTY 43,
+-the GE Terminet 300, the DASI 300S and 450, and most
+-video terminals such as
+-the Datamedia 5120 or HP 2640.
+-You must also have a valid user name,
+-which may be obtained, together with the telephone number, from the system administrators.
+-The same telephone number
+-serves terminals operating at all the standard speeds.
+-After a data connection is established,
+-the login procedure depends on what kind of terminal
+-you are using.
+-.I
+-.I
+-.R
+-.R
+-.LP
+-.I
+-300-baud terminals:\ \ 
+-.R
+-Such terminals include the GE Terminet 300 and most display terminals
+-run with popular modems.
+-These terminals generally have a speed
+-switch which should be set at `300' (or `30' for
+-30 characters per second)
+-and a half/full duplex switch which should be set at
+-full-duplex.
+-(This switch will often have to be changed
+-since many other systems require half-duplex).
+-When a connection is established, the system
+-types `login:'; you type your
+-user name, followed by the `return' key.
+-If you have a password, the system asks for it
+-and turns off the printer on the terminal
+-so the password will not appear.
+-After you have logged in,
+-the `return', `new line', or `linefeed' keys
+-will give exactly the same results.
+-.LP
+-.I
+-1200- and 150-baud terminals:\ \ 
+-.R
+-If there is a half/full duplex switch, set it at full-duplex.
+-When you have established a data connection,
+-the system types out a few garbage characters
+-(the `login:' message at the wrong speed).
+-Depress the `break' (or `interrupt')
+-key; this is a speed-independent signal
+-to
+-.UX
+-that a different speed terminal
+-is in use.
+-The system then will type `login:,' this time at another
+-speed.
+-Continue depressing the break key
+-until `login:' appears in clear, then
+-respond with your user name.
+-From the TTY 37 terminal, and any other which has the `newline'
+-function (combined carriage return and linefeed), terminate each line you type with the
+-`new line' key,
+-otherwise use the `return' key.
+-.LP
+-.I
+-Hard-wired terminals.\ \ 
+-.R
+-Hard-wired terminals usually begin at the right
+-speed, up to 9600 baud; otherwise the preceding instructions
+-apply.
+-.LP
+-For all these terminals, it is important
+-that you type your name in lower-case if possible; if you type
+-upper-case letters,
+-.UX
+-will assume that your terminal cannot generate lower-case
+-letters and will translate all subsequent upper-case
+-letters to lower case.
+-.LP
+-The evidence that you have successfully
+-logged in is that the Shell program
+-will type a `$' to you.
+-(The Shell is described below under
+-`How to run a program.')
+-.LP
+-For more information, consult
+-.IR stty (1),
+-which tells how to adjust terminal behavior,
+-.IR getty (8),
+-which discusses the login sequence in more
+-detail, and
+-.IR tty(4),
+-which discusses terminal I/O.
+-.LP
+-.I
+-Logging out.\ \ 
+-.R
+-There are three ways to log out:
+-.IP
+-You can simply hang up the phone.
+-.IP
+-You can log out by typing an end-of-file indication
+-(EOT character, control-d) to the Shell.
+-The Shell will terminate and the `login: ' message
+-will appear again.
+-.IP
+-You can also log in directly as another user
+-by giving a
+-.IR login (1)
+-command.
+-.LP
+-.I
+-How to communicate through your terminal.\ \ 
+-.R
+-When you type characters, a gnome deep in the system
+-gathers your characters and saves them in a secret
+-place.
+-The
+-characters will not be given to a program
+-until you type a return (or newline), as described above
+-in
+-.I
+-Logging in.
+-.R
+-.LP
+-.UX
+-terminal I/O is full-duplex.
+-It has full read-ahead, which means that you can
+-type at any time,
+-even while a program is
+-typing at you.
+-Of course, if you type during output, the printed output will
+-have the input characters interspersed.
+-However, whatever you type will be saved
+-up and interpreted in correct sequence.
+-There is a limit to the amount of read-ahead,
+-but it is generous and not likely to be exceeded unless
+-the system is in trouble.
+-When the read-ahead limit is exceeded, the system
+-throws away all the saved characters.
+-.LP
+-The character `@' in typed input
+-kills all the preceding characters in the line, so
+-typing mistakes
+-can be repaired on a single line.
+-Also, the character `#' erases the last character typed.
+-Successive uses of `#' erase characters back to, but
+-not beyond, the beginning of the line.
+-`@' and `#' can be transmitted to a program
+-by preceding them with `\\'.
+-(So, to erase `\\', you need two `#'s).
+-These conventions can be changed by the
+-.IR stty (1)
+-command.
+-.LP
+-The `break' or `interrupt' key causes an
+-.I
+-interrupt signal,
+-.R
+-as does the
+-The \s8ASCII\s10 `delete' (or `rubout') character,
+-which is not passed to programs.
+-This signal
+-generally causes whatever program
+-you are running to terminate.
+-It is typically used to stop a long printout that
+-you don't want.
+-However, programs can arrange either to ignore
+-this signal altogether,
+-or to be notified when it happens (instead
+-of being terminated).
+-The editor, for example, catches interrupts and
+-stops what it is doing,
+-instead of terminating, so that an interrupt can
+-be used to halt an editor printout without
+-losing the file being edited.
+-.LP
+-The
+-.IR quit ""
+-signal is generated
+-by typing the \s8ASCII\s10 FS character.
+-(FS appears many places on different terminals, most commonly
+-as control-\e or control-\^|\^.)
+-It not only causes a running program to terminate
+-but also generates a file with the core image
+-of the terminated process.
+-Quit is useful
+-for debugging.
+-.LP
+-Besides adapting to the speed of the terminal,
+-.UX
+-tries to be intelligent about whether
+-you have a terminal with the newline function
+-or whether it must be simulated with carriage-return
+-and line-feed.
+-In the latter case, all input carriage returns
+-are turned to newline characters (the standard
+-line delimiter)
+-and both a carriage return and a line feed
+-are echoed to the terminal.
+-If you get into the wrong mode, the
+-.IR stty (1)
+-command will rescue you.
+-.LP
+-Tab characters are used freely in
+-.UX
+-source programs.
+-If your terminal does not have the tab function,
+-you can arrange to have them turned into spaces
+-during output, and echoed as spaces
+-during input.
+-The system assumes
+-that tabs are set every eight columns.
+-Again, the
+-.IR stty (1)
+-command will set or reset this mode.
+-Also, the command
+-.IR tabs (1)
+-will set the tab stops automatically on many terminals.
+-.LP
+-.I
+-How to run a program; the Shell.\ \ 
+-.R
+-When you have successfully logged in, a program
+-called the Shell is listening to your terminal.
+-The Shell reads typed-in lines, splits them up
+-into a command name and arguments, and executes the command.
+-A command is simply an executable program.
+-The Shell looks first in your current directory
+-(see below)
+-for a program with the given name,
+-and if none is there, then in a system directory.
+-There is nothing special about system-provided
+-commands except that they are kept in a directory
+-where the Shell can find them.
+-.LP
+-The command name is always the first word on an input line;
+-it and its arguments are separated from one another by
+-spaces.
+-.LP
+-When a program terminates, the Shell will ordinarily regain control and type 
+-a `$' at you to indicate that it is ready for another command.
+-.LP
+-The Shell has many other capabilities, which are described in detail in section
+-.IR sh (1).
+-.LP
+-.I
+-The current directory.\ \ 
+-.R
+-.UX
+-has a file system arranged in a hierarchy of directories.
+-When the system administrator gave you a user name,
+-he also created a directory for you (ordinarily
+-with the same name as your user name).
+-When you log in, any file
+-name you type is by default
+-in this directory.
+-Since you are the owner of this directory, you have
+-full permission to read, write, alter, or destroy
+-its contents.
+-Permissions to have your will with other directories
+-and files will have been granted or denied to you
+-by their owners.
+-As a matter of observed fact, few
+-.UX
+-users
+-protect their files from destruction,
+-let alone perusal, by other users.
+-.LP
+-To change the
+-current directory (but not the set of permissions you
+-were endowed with at login) use
+-.IR cd (1).
+-.LP
+-.I
+-Path names.\ \ 
+-.R
+-To refer to files not in the current directory, you must
+-use a path name.
+-Full path names begin with `/', the name of the root directory of the
+-whole file system.
+-After the slash comes the name of each directory containing the next
+-sub-directory (followed by a `/') until finally the
+-file name is reached.
+-For example,
+-.I
+-/\^usr/\^lem/\^filex
+-.R
+-refers to the file
+-.I
+-filex
+-.R
+-in the directory
+-.I
+-lem; lem
+-.R
+-is itself a subdirectory of
+-.I
+-usr; usr
+-.R
+-springs directly from the root directory.
+-.LP
+-If your current directory has subdirectories,
+-the path names of files therein begin with
+-the name of the subdirectory with no prefixed `/'.
+-.LP
+-A path name may be used anywhere a file name is
+-required.
+-.LP
+-Important commands which modify the contents of files
+-are
+-.IR cp (1),
+-.IR mv (1),
+-and
+-.IR rm (1),
+-which respectively copy, move (i.e. rename) and remove files.
+-To find out the status of files or directories, use 
+-.IR ls (1).
+-See
+-.IR mkdir (1)
+-for making directories and
+-.I
+-rmdir
+-.R
+-(in
+-.IR rm (1))
+-for destroying them.
+-.LP
+-For a fuller discussion of the file system, see
+-`The
+-.UX
+-Time-Sharing System,'
+-by Ken Thompson and Dennis Ritchie.
+-It may also be useful to glance through
+-section 2 of this manual, which discusses
+-system calls, even if you don't intend
+-to deal with the system at that level.
+-.LP
+-.I
+-Writing a program.\ \ 
+-.R
+-To enter the text of a source program into a
+-.UX
+-file, use
+-the editor
+-.IR ed (1).
+-The three principal languages in
+-.UX
+-are
+-provided by the C compiler
+-.IR cc (1),
+-the Fortran compiler
+-.IR f77 (1),
+-and the assembler
+-.IR as (1).
+-After the program text has been entered through 
+-the editor
+-and written on a file, you can give the file
+-to the appropriate language processor as an argument.
+-The output of the language processor
+-will be left on a file in the current directory named `a.out'.
+-(If the output is precious, use
+-.I mv
+-to move it to a less
+-exposed name soon.)\ 
+-If you wrote in assembly language, you will probably
+-need to load the program with library subroutines; see
+-.IR ld (1).
+-The other two language processors call
+-the loader automatically.
+-.LP
+-When you have finally gone through this entire process
+-without provoking any diagnostics, the resulting program
+-can be run by giving its name to the Shell
+-in response to the `$' prompt.
+-.LP
+-Your programs can receive arguments from the command line
+-just as system programs do,
+-see
+-.IR exec (2).
+-.LP
+-.I
+-Text processing.\ \ 
+-.R
+-Almost all text is entered through the editor
+-.IR ed (1).
+-The commands most often used to write text on a terminal are:
+-.I
+-cat, pr, roff
+-.R
+-and
+-.I nroff,
+-all in section 1.
+-.LP
+-The
+-.I cat
+-command simply dumps \s8ASCII\s10 text
+-on the terminal, with no processing at all.
+-The
+-.IR pr ""
+-command paginates the text, supplies headings,
+-and has a facility for multi-column output.
+-.I
+-Nroff
+-.R
+-is an elaborate text formatting program.
+-Used naked, it requires careful forethought, but for
+-ordinary documents it has been tamed;
+-see
+-.IR ms (7).
+-.I Roff
+-is a simpler text formatting
+-program, and requires somewhat less forethought.
+-.I
+-.LP
+-.I Troff
+-prepares documents for a
+-Graphics Systems phototypesetter;
+-it is very similar to 
+-.I nroff,
+-and often works from exactly the same
+-source text.
+-It was used to produce this manual.
+-.LP
+-.I
+-Status inquiries.\ \ 
+-.R
+-Various commands exist to provide you with useful
+-information.
+-.IR Who (1)
+-prints a list of users presently logged in.
+-.IR Date (1)
+-prints the current time and date.
+-.IR Ls (1)
+-will list the files in your directory or give
+-summary information about particular files.
+-.LP
+-.I
+-Surprises.\ \ 
+-.R
+-Certain commands provide inter-user communication.
+-Even if you do not plan to use them, it would be
+-well to learn something about them, because someone else may
+-aim them at you.
+-.LP
+-To communicate with another user currently logged in,
+-.IR write (1)
+-is used;
+-.IR mail (1)
+-will leave a message whose presence will be announced
+-to another user when he next logs in.
+-The write-ups in the manual also suggest how to respond to
+-the two commands if you are a target.
+-.LP
+-When you log in, a message-of-the-day may greet you
+-before the first `$'.
+-.SH
+-CONVERTING FROM THE 6TH EDITION
+-.LP
+-There follows a catalogue of significant, mostly incompatible,
+-changes that will affect old users converting to the 7th edition.
+-No attempt is made to list all new facilities, or even all
+-minor, but easily spotted changes,
+-just the bare essentials without which it will be
+-almost impossible to do anything.
+-.LP
+-.I
+-Addressing files.\ \ 
+-.R
+-Byte addresses in files are now long (32-bit) integers.
+-Accordingly
+-.I seek
+-has been replaced by
+-.IR lseek (2).
+-Every program that contains a 
+-.I seek
+-must be modified.
+-.I Stat
+-and
+-.IR fstat (2)
+-have been affected similarly, since file lengths are now
+-32- rather than 24-bit quantities.
+-.LP
+-.I
+-Assembly language.\ \ 
+-.R
+-System entry points are no longer built in symbols.
+-Their values must be obtained from
+-.I /usr/include/sys.s,
+-see
+-.IR intro (2).
+-All system calls modify r0.
+-This means that sequences like
+-.DS
+-mov   file,r0
+-sys   lseek,0,0,2
+-sys   write,buf,n
+-.DE
+-will no longer work.
+-(In fact, 
+-.I lseek
+-now modifies r1 as well, so be doubly cautious.)
+-.LP
+-The
+-.IR sleep (2)
+-entry point is gone; see the more general facility,
+-.IR alarm,
+-plus
+-.I pause.
+-.LP
+-Few library functions have assembly language entry points any more.
+-You will have to simulate the C calling sequence.
+-.LP
+-.I
+-Stty and gtty.\ \ 
+-.R
+-These system calls have been extensively altered,
+-see
+-.IR ioctl (2)
+-and
+-.IR tty (4).
+-.LP
+-.I
+-Archive files.\ \ 
+-.R
+-The format of files produced by
+-.IR ar (1)
+-has been altered.
+-To convert to the new style, use
+-.IR arcv (1).
+-.LP
+-.I 
+-C language, lint.\ \ 
+-.R
+-The official syntax for initialization
+-requires an equal sign = before an initializer,
+-and brackets { } around compound initial values;
+-arrays and structures are now initialized honestly.
+-Two-address operators, such as =+ and =-, are now written
+-+= and -= to avoid ambiguities, although the old
+-style is still accepted.
+-You will also certainly want to learn about
+-.DS
+-long integers
+-type definitions
+-casts (for type conversion)
+-unions (for more honest storage sharing)
+-#include <filename> (which searches in standard places)
+-.DE
+-.LP
+-The program
+-.IR lint (1)
+-checks for obsolete syntax and
+-does strong type checking of C programs, singly
+-or in groups that are expected to be loaded together.
+-It is indispensable for conversion work.
+-.LP
+-.I Fortran.\ \ 
+-The old 
+-.I fc
+-is replaced by
+-.I f77,
+-a true compiler for Fortran 77,
+-compatible with C.
+-There are substantial changes in the language;
+-see `A Portable Fortran 77 Compiler' in Volume 2.
+-.LP
+-.I
+-Stream editor.\ \ 
+-.R
+-The program
+-.IR sed (1)
+-is adapted to massive, repetitive
+-editing jobs of the sort encountered in converting to
+-the new system.
+-It is well worth learning.
+-.LP
+-.I
+-Standard I/O.\ \ 
+-.R
+-The old 
+-.I
+-fopen, getc, putc
+-.R
+-complex and the old
+-.I \-lp
+-package are both dead,
+-and even
+-.I getchar
+-has changed.
+-All have been replaced by the clean, highly efficient,
+-.IR stdio (3)
+-package.
+-The first things to know are that
+-.IR getchar (3)
+-returns the integer EOF (\-1), which is not a possible byte value,
+-on end of file, that 518-byte buffers are out, and that there
+-is a defined FILE data type.
+-.LP
+-.I Make.\ \ 
+-The program
+-.IR make (1)
+-handles the recompilation and loading of
+-software in an orderly way from
+-a `makefile' recipe given for each piece of software.
+-It remakes only as much as the modification dates of the input files
+-show is necessary.
+-The makefiles will guide you in building your new system.
+-.LP
+-.I
+-Shell, chdir.\ \ 
+-.R
+-F. L. Bauer once said Algol 68 is the Everest that
+-must be climbed by every computer scientist because
+-it is there.
+-So it is with the shell for
+-.UX
+-users.
+-Everything beyond simple command invocation from a terminal is
+-different.
+-Even
+-.I chdir
+-is now spelled
+-.I cd.
+-You will want to study
+-.IR sh (1)
+-long and hard.
+-.LP
+-.I Debugging.\ \ 
+-.IR Adb (1)
+-is a far more capable replacement for the debugger
+-.I db.
+-The first-time user should be especially careful about
+-distinguishing / and ? in
+-.I adb
+-commands, and watching to make sure that the
+-.I x
+-whose value he asked for is the real
+-.I x,
+-and not just some absolute location equal to the stack offset
+-of some automatic
+-.I x.
+-You can always use the `true' name,
+-.I _x,
+-to pin down a C external variable.
+-.LP
+-.I Dsw.
+-This little-known, but indispensable facility has been
+-taken over by
+-.I
+-rm \-ri.
+-.LP
+-.I
+-Boot procedures.\ \ 
+-.R
+-Needless to say, these are all different.
+-See section 8 of this volume, and
+-`Setting up \s8UNIX\s10' in Volume 2.
+//GO.SYSIN DD intro
+echo permindex
+sed 's/.//' >permindex <<'//GO.SYSIN DD permindex'
+-.xx "" "" "abort \- generate IOT fault" "" abort(3)
+-.xx "" "" "abs \- integer absolute value" "" abs(3)
+-.xx "" "fabs, floor, ceil \-" "absolute value, floor, ceiling functions" "" floor(3)
+-.xx "" "" "ac \- login accounting" "" ac(1)
+-.xx "" "" "access \- determine accessibility of file" "" access(2)
+-.xx "" "phys \- allow a process to" "access physical addresses" "" phys(2)
+-.xx "" "access \- determine" "accessibility of file" "" access(2)
+-.xx "" "ac \- login" "accounting" "" ac(1)
+-.xx "" "sa, accton \- system" "accounting" "" sa(1)
+-.xx "" "acct \- execution" "accounting file" "" acct(5)
+-.xx "" "acct \- turn" "accounting on or off" "" acct(2)
+-.xx "" "sa," "accton \- system accounting" "" sa(1)
+-.xx "" "sin, cos, tan, asin," "acos, atan, atan2 \- trigonometric functions" "" sin(3)
+-.xx "" "dn \- DN-11" "ACU interface" "" dn(4)
+-.xx "" "" "adb \- debugger" "" adb(1)
+-.xx "" "phys \- allow a process to access physical" "addresses" "" phys(2)
+-.xx "" "basename \- strip filename" "affixes" "" basename(1)
+-.xx "" "plot: openpl et" "al. \- graphics interface" "" plot(3)
+-.xx "" "" "alarm \- schedule signal after specified time" "" alarm(2)
+-.xx "" "brk, sbrk, break \- change core" "allocation" "" brk(2)
+-.xx "" "malloc, free, realloc, calloc \- main memory" "allocator" "" malloc(3)
+-.xx "" "lex \- generator of lexical" "analysis programs" "" lex(1)
+-.xx "" "bcd, ppt \- convert to" "antique media" "" bcd(6)
+-.xx "" "" "a.out \- assembler and link editor output" "" a.out(5)
+-.xx "" "" "ar \- archive and library maintainer" "" ar(1)
+-.xx "" "" "ar \- archive (library) file format" "" ar(5)
+-.xx "" "bc \-" "arbitrary-precision arithmetic language" "" bc(1)
+-.xx "" "tp \- manipulate tape" "archive" "" tp(1)
+-.xx "" "ar \-" "archive and library maintainer" "" ar(1)
+-.xx "" "ar \-" "archive (library) file format" "" ar(5)
+-.xx "" "tar \- tape" "archiver" "" tar(1)
+-.xx "" "arcv \- convert" "archives to new format" "" arcv(1)
+-.xx "" "echo \- echo" "arguments" "" echo(1)
+-.xx "" "expr \- evaluate" "arguments as an expression" "" expr(1)
+-.xx "" "pow, gcd, rpow \- multiple precision integer" "arithmetic" "/msub, mult, mdiv, min, mout," mp(3)
+-.xx "" "" "arithmetic \- provide drill in number facts" "" arithmetic(6)
+-.xx "" "bc \- arbitrary-precision" "arithmetic language" "" bc(1)
+-.xx "" "" "as \- assembler" "" as(1)
+-.xx "" "asctime, timezone \- convert date and time to" "ASCII" "ctime, localtime, gmtime," ctime(3)
+-.xx "" "" "ascii \- map of ASCII character set" "" ascii(7)
+-.xx "" "atof, atoi, atol \- convert" "ASCII to numbers" "" atof(3)
+-.xx "ASCII" "ctime, localtime, gmtime," "asctime, timezone \- convert date and time to" "" ctime(3)
+-.xx "functions" "sin, cos, tan," "asin, acos, atan, atan2 \- trigonometric" "" sin(3)
+-.xx "" "as \-" "assembler" "" as(1)
+-.xx "" "a.out \-" "assembler and link editor output" "" a.out(5)
+-.xx "" "" "assert \- program verification" "" assert(3)
+-.xx "" "setbuf \-" "assign buffering to a stream" "" setbuf(3)
+-.xx "" "" "at \- execute commands at a later time" "" at(1)
+-.xx "" "sin, cos, tan, asin, acos," "atan, atan2 \- trigonometric functions" "" sin(3)
+-.xx "" "" "atof, atoi, atol \- convert ASCII to numbers" "" atof(3)
+-.xx "" "wait \-" "await completion of process" "" wait(1)
+-.xx "language" "" "awk \- pattern scanning and processing" "" awk(1)
+-.xx "" "" "backgammon \- the game" "" backgammon(6)
+-.xx "" "" "banner \- make long posters" "" banner(6)
+-.xx "" "" "bas \- basic" "" bas(1)
+-.xx "" "store, delete, firstkey, nextkey \- data" "base subroutines" "dbminit, fetch," dbm(3)
+-.xx "" "" "basename \- strip filename affixes" "" basename(1)
+-.xx "" "bas \-" "basic" "" bas(1)
+-.xx "" "" "bc \- arbitrary-precision arithmetic language" "" bc(1)
+-.xx "" "" "bcd, ppt \- convert to antique media" "" bcd(6)
+-.xx "" "cb \- C program" "beautifier" "" cb(1)
+-.xx "" "j0, j1, jn, y0, y1, yn \-" "bessel functions" "" j0(3)
+-.xx "" "fread, fwrite \- buffered" "binary input/output" "" fread(3)
+-.xx "" "" "bj \- the game of black jack" "" bj(6)
+-.xx "" "sync \- update the super" "block" "" sync(1)
+-.xx "" "sync \- update super-" "block" "" sync(2)
+-.xx "" "update \- periodically update the super" "block" "" update(8)
+-.xx "" "sum \- sum and count" "blocks in a file" "" sum(1)
+-.xx "" "ching, fortune \- the" "book of changes and other cookies" "" ching(6)
+-.xx "" "" "boot \- startup procedures" "" boot(8)
+-.xx "" "brk, sbrk," "break \- change core allocation" "" brk(2)
+-.xx "export, login,/" "sh, for, case, if, while," "break, continue, cd, eval, exec, exit," "" sh(1)
+-.xx "" "" "brk, sbrk, break \- change core allocation" "" brk(2)
+-.xx "" "fread, fwrite \-" "buffered binary input/output" "" fread(3)
+-.xx "" "stdio \- standard" "buffered input/output package" "" stdio(3)
+-.xx "" "setbuf \- assign" "buffering to a stream" "" setbuf(3)
+-.xx "" "mknod \-" "build special file" "" mknod(1)
+-.xx "" "l3tol, ltol3 \- convert between 3-" "byte integers and long integers" "" l3tol(3)
+-.xx "" "swab \- swap" "bytes" "" swab(3)
+-.xx "" "cc, pcc \-" "C compiler" "" cc(1)
+-.xx "" "cb \-" "C program beautifier" "" cb(1)
+-.xx "" "lint \- a" "C program verifier" "" lint(1)
+-.xx "" "hypot," "cabs \- euclidean distance" "" hypot(3)
+-.xx "" "" "cal \- print calendar" "" cal(1)
+-.xx "" "dc \- desk" "calculator" "" dc(1)
+-.xx "" "cal \- print" "calendar" "" cal(1)
+-.xx "" "" "calendar \- reminder service" "" calendar(1)
+-.xx "" "indir \- indirect system" "call" "" indir(2)
+-.xx "" "cu \-" "call UNIX" "" cu(1)
+-.xx "" "malloc, free, realloc," "calloc \- main memory allocator" "" malloc(3)
+-.xx "" "intro, errno \- introduction to system" "calls and error numbers" "" intro(2)
+-.xx "exec, exit, export, login, newgrp,/" "sh, for," "case, if, while, break, continue, cd, eval," "" sh(1)
+-.xx "" "" "cat \- catenate and print" "" cat(1)
+-.xx "" "" "cat \- phototypesetter interface" "" cat(4)
+-.xx "" "signal \-" "catch or ignore signals" "" signal(2)
+-.xx "" "cat \-" "catenate and print" "" cat(1)
+-.xx "" "" "cb \- C program beautifier" "" cb(1)
+-.xx "" "" "cc, pcc \- C compiler" "" cc(1)
+-.xx "" "" "cd \- change working directory" "" cd(1)
+-.xx "" "sh, for, case, if, while, break, continue," "cd, eval, exec, exit, export, login, newgrp,/" "" sh(1)
+-.xx "functions" "fabs, floor," "ceil \- absolute value, floor, ceiling" "" floor(3)
+-.xx "" "brk, sbrk, break \-" "change core allocation" "" brk(2)
+-.xx "" "chdir \-" "change default directory" "" chdir(2)
+-.xx "" "passwd \-" "change login password" "" passwd(1)
+-.xx "" "chmod \-" "change mode" "" chmod(1)
+-.xx "" "chmod \-" "change mode of file" "" chmod(2)
+-.xx "" "chown \-" "change owner and group of a file" "" chown(2)
+-.xx "" "chown, chgrp \-" "change owner or group" "" chown(1)
+-.xx "" "cd \-" "change working directory" "" cd(1)
+-.xx "" "ching, fortune \- the book of" "changes and other cookies" "" ching(6)
+-.xx "" "pipe \- create an interprocess" "channel" "" pipe(2)
+-.xx "" "ungetc \- push" "character back into input stream" "" ungetc(3)
+-.xx "" "ispunct, isprint, iscntrl, isascii \-" "character classification" "/isalnum, isspace," ctype(3)
+-.xx "" "eqnchar \- special" "character definitions for eqn" "" eqnchar(7)
+-.xx "" "getc, getchar, fgetc, getw \- get" "character or word from stream" "" getc(3)
+-.xx "" "putc, putchar, fputc, putw \- put" "character or word on a stream" "" putc(3)
+-.xx "" "ascii \- map of ASCII" "character set" "" ascii(7)
+-.xx "" "tr \- translate" "characters" "" tr(1)
+-.xx "" "" "chdir \- change default directory" "" chdir(2)
+-.xx "" "dcheck \- file system directory consistency" "check" "" dcheck(1)
+-.xx "" "icheck \- file system storage consistency" "check" "" icheck(1)
+-.xx "" "eqn, neqn," "checkeq \- typeset mathematics" "" eqn(1)
+-.xx "" "" "checkers \- game" "" checkers(6)
+-.xx "" "chess \- the game of" "chess" "" chess(6)
+-.xx "" "chown," "chgrp \- change owner or group" "" chown(1)
+-.xx "other cookies" "" "ching, fortune \- the book of changes and" "" ching(6)
+-.xx "" "" "chmod \- change mode" "" chmod(1)
+-.xx "" "" "chmod \- change mode of file" "" chmod(2)
+-.xx "" "" "chown \- change owner and group of a file" "" chown(2)
+-.xx "" "" "chown, chgrp \- change owner or group" "" chown(1)
+-.xx "" "isprint, iscntrl, isascii \- character" "classification" "/isalnum, isspace, ispunct," ctype(3)
+-.xx "" "clri \-" "clear i-node" "" clri(1)
+-.xx "" "feof, ferror," "clearerr, fileno \- stream status inquiries" "" ferror(3)
+-.xx "" "cron \-" "clock daemon" "" cron(8)
+-.xx "" "" "close \- close a file" "" close(2)
+-.xx "" "fclose, fflush \-" "close or flush a stream" "" fclose(3)
+-.xx "" "" "clri \- clear i-node" "" clri(1)
+-.xx "" "" "cmp \- compare two files" "" cmp(1)
+-.xx "" "" "col \- filter reverse line feeds" "" col(1)
+-.xx "sorted files" "" "comm \- select or reject lines common to two" "" comm(1)
+-.xx "" "system \- issue a shell" "command" "" system(3)
+-.xx "" "test \- condition" "command" "" test(1)
+-.xx "" "time \- time a" "command" "" time(1)
+-.xx "" "nice, nohup \- run a" "command at low priority" "" nice(1)
+-.xx "" "uux \- unix to unix" "command execution" "" uux(1)
+-.xx "" "set, shift, times, trap, umask, wait \-" "command language" "/newgrp, read, readonly," sh(1)
+-.xx "" "intro \- introduction to" "commands" "" intro(1)
+-.xx "" "at \- execute" "commands at a later time" "" at(1)
+-.xx "" "comm \- select or reject lines" "common to two sorted files" "" comm(1)
+-.xx "" "diff \- differential file" "comparator" "" diff(1)
+-.xx "" "cmp \-" "compare two files" "" cmp(1)
+-.xx "" "diff3 \- 3-way differential file" "comparison" "" diff3(1)
+-.xx "" "cc, pcc \- C" "compiler" "" cc(1)
+-.xx "" "f77 \- Fortran 77" "compiler" "" f77(1)
+-.xx "" "yacc \- yet another compiler-" "compiler" "" yacc(1)
+-.xx "" "wait \- await" "completion of process" "" wait(1)
+-.xx "" "test \-" "condition command" "" test(1)
+-.xx "" "mkconf \- generate" "configuration tables" "" mkconf(1)
+-.xx "" "dcheck \- file system directory" "consistency check" "" dcheck(1)
+-.xx "" "icheck \- file system storage" "consistency check" "" icheck(1)
+-.xx "" "mkfs \-" "construct a file system" "" mkfs(1)
+-.xx "" "deroff \- remove nroff, troff, tbl and eqn" "constructs" "" deroff(1)
+-.xx "" "ls \- list" "contents of directory" "" ls(1)
+-.xx "login,/" "sh, for, case, if, while, break," "continue, cd, eval, exec, exit, export," "" sh(1)
+-.xx "" "ioctl, stty, gtty \-" "control device" "" ioctl(2)
+-.xx "" "init, rc \- process" "control initialization" "" init(8)
+-.xx "" "terminals\-" "conventional names" "" term(7)
+-.xx "" "ecvt, fcvt, gcvt \- output" "conversion" "" ecvt(3)
+-.xx "" "printf, fprintf, sprintf \- formatted output" "conversion" "" printf(3)
+-.xx "" "scanf, fscanf, sscanf \- formatted input" "conversion" "" scanf(3)
+-.xx "" "units \-" "conversion program" "" units(1)
+-.xx "" "dd \-" "convert and copy a file" "" dd(1)
+-.xx "" "arcv \-" "convert archives to new format" "" arcv(1)
+-.xx "" "atof, atoi, atol \-" "convert ASCII to numbers" "" atof(3)
+-.xx "integers" "l3tol, ltol3 \-" "convert between 3-byte integers and long" "" l3tol(3)
+-.xx "" "localtime, gmtime, asctime, timezone \-" "convert date and time to ASCII" "ctime," ctime(3)
+-.xx "" "bcd, ppt \-" "convert to antique media" "" bcd(6)
+-.xx "" "fortune \- the book of changes and other" "cookies" "ching," ching(6)
+-.xx "" "cp \-" "copy" "" cp(1)
+-.xx "" "uucp, uulog \- unix to unix" "copy" "" uucp(1)
+-.xx "" "dd \- convert and" "copy a file" "" dd(1)
+-.xx "" "" "core \- format of core image file" "" core(5)
+-.xx "" "brk, sbrk, break \- change" "core allocation" "" brk(2)
+-.xx "" "core \- format of" "core image file" "" core(5)
+-.xx "" "mem, kmem \-" "core memory" "" mem(4)
+-.xx "trigonometric functions" "sin," "cos, tan, asin, acos, atan, atan2 \-" "" sin(3)
+-.xx "" "sinh," "cosh, tanh \- hyperbolic functions" "" sinh(3)
+-.xx "" "wc \- word" "count" "" wc(1)
+-.xx "" "sum \- sum and" "count blocks in a file" "" sum(1)
+-.xx "" "" "cp \- copy" "" cp(1)
+-.xx "" "" "crash \- what to do when the system crashes" "" crash(8)
+-.xx "" "" "creat \- create a new file" "" creat(2)
+-.xx "" "pipe \-" "create an interprocess channel" "" pipe(2)
+-.xx "" "umask \- set file" "creation mode mask" "" umask(2)
+-.xx "" "" "cron \- clock daemon" "" cron(8)
+-.xx "" "" "crypt \- encode/decode" "" crypt(1)
+-.xx "" "" "crypt, setkey, encrypt \- DES encryption" "" crypt(3)
+-.xx "\- convert date and time to ASCII" "" "ctime, localtime, gmtime, asctime, timezone" "" ctime(3)
+-.xx "" "" "cu \- call UNIX" "" cu(1)
+-.xx "" "ttt," "cubic \- tic-tac-toe" "" ttt(6)
+-.xx "" "spline \- interpolate smooth" "curve" "" spline(1)
+-.xx "" "cron \- clock" "daemon" "" cron(8)
+-.xx "" "prof \- display profile" "data" "" prof(1)
+-.xx "" "ttys \- terminal initialization" "data" "" ttys(5)
+-.xx "" "fetch, store, delete, firstkey, nextkey \-" "data base subroutines" "dbminit," dbm(3)
+-.xx "" "null \-" "data sink" "" null(4)
+-.xx "" "types \- primitive system" "data types" "" types(5)
+-.xx "" "join \- relational" "database operator" "" join(1)
+-.xx "" "du, dp \- DU-11 201" "data-phone interface" "" du(4)
+-.xx "" "date \- print and set the" "date" "" date(1)
+-.xx "" "time, ftime \- get" "date and time" "" time(2)
+-.xx "" "gmtime, asctime, timezone \- convert" "date and time to ASCII" "ctime, localtime," ctime(3)
+-.xx "" "touch \- update" "date last modified of a file" "" touch(1)
+-.xx "nextkey \- data base subroutines" "" "dbminit, fetch, store, delete, firstkey," "" dbm(3)
+-.xx "" "" "dc \- desk calculator" "" dc(1)
+-.xx "check" "" "dcheck \- file system directory consistency" "" dcheck(1)
+-.xx "" "" "dd \- convert and copy a file" "" dd(1)
+-.xx "" "dump," "ddate \- incremental dump format" "" dump(5)
+-.xx "" "adb \-" "debugger" "" adb(1)
+-.xx "" "tp \-" "DEC/mag tape formats" "" tp(5)
+-.xx "" "crypt \- encode/" "decode" "" crypt(1)
+-.xx "" "tc \- TC-11/TU56" "DECtape" "" tc(4)
+-.xx "" "chdir \- change" "default directory" "" chdir(2)
+-.xx "" "eqnchar \- special character" "definitions for eqn" "" eqnchar(7)
+-.xx "subroutines" "dbminit, fetch, store," "delete, firstkey, nextkey \- data base" "" dbm(3)
+-.xx "" "tail \-" "deliver the last part of a file" "" tail(1)
+-.xx "" "mesg \- permit or" "deny messages" "" mesg(1)
+-.xx "constructs" "" "deroff \- remove nroff, troff, tbl and eqn" "" deroff(1)
+-.xx "" "crypt, setkey, encrypt \-" "DES encryption" "" crypt(3)
+-.xx "" "dup, dup2 \- duplicate an open file" "descriptor" "" dup(2)
+-.xx "" "dc \-" "desk calculator" "" dc(1)
+-.xx "" "access \-" "determine accessibility of file" "" access(2)
+-.xx "" "file \-" "determine file type" "" file(1)
+-.xx "" "ioctl, stty, gtty \- control" "device" "" ioctl(2)
+-.xx "" "" "df \- disk free" "" df(1)
+-.xx "" "" "diff \- differential file comparator" "" diff(1)
+-.xx "" "" "diff3 \- 3-way differential file comparison" "" diff3(1)
+-.xx "" "diff \-" "differential file comparator" "" diff(1)
+-.xx "" "diff3 \- 3-way" "differential file comparison" "" diff3(1)
+-.xx "" "" "dir \- format of directories" "" dir(5)
+-.xx "" "mv \- move or rename files and" "directories" "" mv(1)
+-.xx "" "cd \- change working" "directory" "" cd(1)
+-.xx "" "chdir \- change default" "directory" "" chdir(2)
+-.xx "" "ls \- list contents of" "directory" "" ls(1)
+-.xx "" "mkdir \- make a" "directory" "" mkdir(1)
+-.xx "" "dcheck \- file system" "directory consistency check" "" dcheck(1)
+-.xx "" "unlink \- remove" "directory entry" "" unlink(2)
+-.xx "" "pwd \- working" "directory name" "" pwd(1)
+-.xx "" "mknod \- make a" "directory or a special file" "" mknod(2)
+-.xx "" "hp \- RH-11/RP04, RP05, RP06 moving-head" "disk" "" hp(4)
+-.xx "" "rk \- RK-11/RK03 or RK05" "disk" "" rk(4)
+-.xx "" "rp \- RP-11/RP03 moving-head" "disk" "" rp(4)
+-.xx "" "hs \- RH11/RS03-RS04 fixed-head" "disk file" "" hs(4)
+-.xx "" "rf \- RF11/RS11 fixed-head" "disk file" "" rf(4)
+-.xx "" "df \-" "disk free" "" df(1)
+-.xx "" "du \- summarize" "disk usage" "" du(1)
+-.xx "" "mount, umount \- mount and" "dismount file system" "" mount(1)
+-.xx "" "prof \-" "display profile data" "" prof(1)
+-.xx "" "hypot, cabs \- euclidean" "distance" "" hypot(3)
+-.xx "" "" "dn \- DN-11 ACU interface" "" dn(4)
+-.xx "" "\- find and insert literature references in" "documents" "refer, lookbib" refer(1)
+-.xx "" "du," "dp \- DU-11 201 data-phone interface" "" du(4)
+-.xx "" "reversi \- a game of" "dramatic reversals" "" reversi(6)
+-.xx "" "graph \-" "draw a graph" "" graph(1)
+-.xx "" "arithmetic \- provide" "drill in number facts" "" arithmetic(6)
+-.xx "" "pk \- packet" "driver" "" pk(4)
+-.xx "" "pkclose, pkread, pkwrite, pkfail \- packet" "driver simulator" "pkopen," pkopen(3)
+-.xx "" "" "du \- summarize disk usage" "" du(1)
+-.xx "" "" "du, dp \- DU-11 201 data-phone interface" "" du(4)
+-.xx "" "dump \- incremental file system" "dump" "" dump(1)
+-.xx "" "od \- octal" "dump" "" od(1)
+-.xx "" "" "dump \- incremental file system dump" "" dump(1)
+-.xx "" "" "dump, ddate \- incremental dump format" "" dump(5)
+-.xx "" "dumpdir \- print the names of files on a" "dump tape" "" dumpdir(1)
+-.xx "descriptor" "" "dup, dup2 \- duplicate an open file" "" dup(2)
+-.xx "" "" "echo \- echo arguments" "" echo(1)
+-.xx "" "" "ecvt, fcvt, gcvt \- output conversion" "" ecvt(3)
+-.xx "" "" "ed \- text editor" "" ed(1)
+-.xx "" "end, etext," "edata \- last locations in program" "" end(3)
+-.xx "" "ed \- text" "editor" "" ed(1)
+-.xx "" "sed \- stream" "editor" "" sed(1)
+-.xx "" "a.out \- assembler and link" "editor output" "" a.out(5)
+-.xx "" "grep," "egrep, fgrep \- search a file for a pattern" "" grep(1)
+-.xx "" "crypt \-" "encode/decode" "" crypt(1)
+-.xx "" "crypt, setkey," "encrypt \- DES encryption" "" crypt(3)
+-.xx "" "makekey \- generate" "encryption key" "" makekey(8)
+-.xx "program" "" "end, etext, edata \- last locations in" "" end(3)
+-.xx "" "getgrent, getgrgid, getgrnam, setgrent," "endgrent \- get group file entry" "" getgrent(3)
+-.xx "" "getpwent, getpwuid, getpwnam, setpwent," "endpwent \- get password file entry" "" getpwent(3)
+-.xx "" "xsend, xget," "enroll \- secret mail" "" xsend(1)
+-.xx "" "nlist \- get" "entries from name list" "" nlist(3)
+-.xx "" "setgrent, endgrent \- get group file" "entry" "getgrent, getgrgid, getgrnam," getgrent(3)
+-.xx "" "setpwent, endpwent \- get password file" "entry" "getpwent, getpwuid, getpwnam," getpwent(3)
+-.xx "" "unlink \- remove directory" "entry" "" unlink(2)
+-.xx "" "execle, execve, execlp, execvp, exec, exece," "environ \- execute a file" "execl, execv," exec(2)
+-.xx "" "" "environ \- user environment" "" environ(5)
+-.xx "" "getenv \- value for" "environment name" "" getenv(3)
+-.xx "" "eqnchar \- special character definitions for" "eqn" "" eqnchar(7)
+-.xx "" "deroff \- remove nroff, troff, tbl and" "eqn constructs" "" deroff(1)
+-.xx "" "" "eqn, neqn, checkeq \- typeset mathematics" "" eqn(1)
+-.xx "eqn" "" "eqnchar \- special character definitions for" "" eqnchar(7)
+-.xx "error numbers" "intro," "errno \- introduction to system calls and" "" intro(2)
+-.xx "" "perror, sys_errlist, sys_nerr \- system" "error messages" "" perror(3)
+-.xx "" "errno \- introduction to system calls and" "error numbers" "intro," intro(2)
+-.xx "" "spell, spellin, spellout \- find spelling" "errors" "" spell(1)
+-.xx "" "pkon, pkoff \-" "establish packet protocol" "" pkon(2)
+-.xx "" "end," "etext, edata \- last locations in program" "" end(3)
+-.xx "" "hypot, cabs \-" "euclidean distance" "" hypot(3)
+-.xx "" "for, case, if, while, break, continue, cd," "eval, exec, exit, export, login, newgrp,/" "sh," sh(1)
+-.xx "" "expr \-" "evaluate arguments as an expression" "" expr(1)
+-.xx "" "execl, execv, execle, execve, execlp, execvp," "exec, exece, environ \- execute a file" "" exec(2)
+-.xx "" "/case, if, while, break, continue, cd, eval," "exec, exit, export, login, newgrp, read,/" "" sh(1)
+-.xx "" "execv, execle, execve, execlp, execvp, exec," "exece, environ \- execute a file" "execl," exec(2)
+-.xx "" "at \-" "execute commands at a later time" "" at(1)
+-.xx "" "uux \- unix to unix command" "execution" "" uux(1)
+-.xx "" "acct \-" "execution accounting file" "" acct(5)
+-.xx "" "sleep \- suspend" "execution for an interval" "" sleep(1)
+-.xx "" "sleep \- suspend" "execution for interval" "" sleep(3)
+-.xx "" "monitor \- prepare" "execution profile" "" monitor(3)
+-.xx "" "profil \-" "execution time profile" "" profil(2)
+-.xx "exece, environ \- execute a file" "execl," "execv, execle, execve, execlp, execvp, exec," "" exec(2)
+-.xx "" "" "exit \- terminate process" "" exit(2)
+-.xx "" "/if, while, break, continue, cd, eval, exec," "exit, export, login, newgrp, read, readonly,/" "" sh(1)
+-.xx "logarithm, power, square root" "" "exp, log, log10, pow, sqrt \- exponential," "" exp(3)
+-.xx "" "frexp, ldexp, modf \- split into mantissa and" "exponent" "" frexp(3)
+-.xx "" "exp, log, log10, pow, sqrt \-" "exponential, logarithm, power, square root" "" exp(3)
+-.xx "" "/while, break, continue, cd, eval, exec, exit," "export, login, newgrp, read, readonly, set,/" "" sh(1)
+-.xx "" "" "expr \- evaluate arguments as an expression" "" expr(1)
+-.xx "" "" "f77 \- Fortran 77 compiler" "" f77(1)
+-.xx "ceiling functions" "" "fabs, floor, ceil \- absolute value, floor," "" floor(3)
+-.xx "" "factor, primes \-" "factor a number, generate large primes" "" factor(1)
+-.xx "" "true," "false \- provide truth values" "" true(1)
+-.xx "" "abort \- generate IOT" "fault" "" abort(3)
+-.xx "" "" "fclose, fflush \- close or flush a stream" "" fclose(3)
+-.xx "" "ecvt," "fcvt, gcvt \- output conversion" "" ecvt(3)
+-.xx "" "fopen, freopen," "fdopen \- open a stream" "" fopen(3)
+-.xx "status inquiries" "" "feof, ferror, clearerr, fileno \- stream" "" ferror(3)
+-.xx "data base subroutines" "dbminit," "fetch, store, delete, firstkey, nextkey \-" "" dbm(3)
+-.xx "" "fclose," "fflush \- close or flush a stream" "" fclose(3)
+-.xx "stream" "getc, getchar," "fgetc, getw \- get character or word from" "" getc(3)
+-.xx "" "gets," "fgets \- get a string from a stream" "" gets(3)
+-.xx "" "grep, egrep," "fgrep \- search a file for a pattern" "" grep(1)
+-.xx "" "access \- determine accessibility of" "file" "" access(2)
+-.xx "" "acct \- execution accounting" "file" "" acct(5)
+-.xx "" "chmod \- change mode of" "file" "" chmod(2)
+-.xx "" "chown \- change owner and group of a" "file" "" chown(2)
+-.xx "" "close \- close a" "file" "" close(2)
+-.xx "" "core \- format of core image" "file" "" core(5)
+-.xx "" "creat \- create a new" "file" "" creat(2)
+-.xx "" "dd \- convert and copy a" "file" "" dd(1)
+-.xx "" "execvp, exec, exece, environ \- execute a" "file" "execl, execv, execle, execve, execlp," exec(2)
+-.xx "" "group \- group" "file" "" group(5)
+-.xx "" "hs \- RH11/RS03-RS04 fixed-head disk" "file" "" hs(4)
+-.xx "" "link \- link to a" "file" "" link(2)
+-.xx "" "mknod \- build special" "file" "" mknod(1)
+-.xx "" "mknod \- make a directory or a special" "file" "" mknod(2)
+-.xx "" "passwd \- password" "file" "" passwd(5)
+-.xx "" "pr \- print" "file" "" pr(1)
+-.xx "" "read \- read from" "file" "" read(2)
+-.xx "" "rev \- reverse lines of a" "file" "" rev(1)
+-.xx "" "rf \- RF11/RS11 fixed-head disk" "file" "" rf(4)
+-.xx "" "size \- size of an object" "file" "" size(1)
+-.xx "" "sum \- sum and count blocks in a" "file" "" sum(1)
+-.xx "" "tail \- deliver the last part of a" "file" "" tail(1)
+-.xx "" "touch \- update date last modified of a" "file" "" touch(1)
+-.xx "" "uniq \- report repeated lines in a" "file" "" uniq(1)
+-.xx "" "write \- write on a" "file" "" write(2)
+-.xx "" "" "file \- determine file type" "" file(1)
+-.xx "" "diff \- differential" "file comparator" "" diff(1)
+-.xx "" "diff3 \- 3-way differential" "file comparison" "" diff3(1)
+-.xx "" "umask \- set" "file creation mode mask" "" umask(2)
+-.xx "" "dup, dup2 \- duplicate an open" "file descriptor" "" dup(2)
+-.xx "" "getgrnam, setgrent, endgrent \- get group" "file entry" "getgrent, getgrgid," getgrent(3)
+-.xx "" "getpwnam, setpwent, endpwent \- get password" "file entry" "getpwent, getpwuid," getpwent(3)
+-.xx "" "grep, egrep, fgrep \- search a" "file for a pattern" "" grep(1)
+-.xx "" "ar \- archive (library)" "file format" "" ar(5)
+-.xx "" "split \- split a" "file into pieces" "" split(1)
+-.xx "" "mktemp \- make a unique" "file name" "" mktemp(3)
+-.xx "" "stat, fstat \- get" "file status" "" stat(2)
+-.xx "" "mkfs \- construct a" "file system" "" mkfs(1)
+-.xx "" "mount, umount \- mount and dismount" "file system" "" mount(1)
+-.xx "" "mount, umount \- mount or remove" "file system" "" mount(2)
+-.xx "" "dcheck \-" "file system directory consistency check" "" dcheck(1)
+-.xx "" "dump \- incremental" "file system dump" "" dump(1)
+-.xx "" "hier \-" "file system hierarchy" "" hier(7)
+-.xx "" "quot \- summarize" "file system ownership" "" quot(1)
+-.xx "" "restor \- incremental" "file system restore" "" restor(1)
+-.xx "" "icheck \-" "file system storage consistency check" "" icheck(1)
+-.xx "" "mtab \- mounted" "file system table" "" mtab(5)
+-.xx "" "filsys, flblk, ino \- format of" "file system volume" "" filsys(5)
+-.xx "" "utime \- set" "file times" "" utime(2)
+-.xx "" "file \- determine" "file type" "" file(1)
+-.xx "" "basename \- strip" "filename affixes" "" basename(1)
+-.xx "" "feof, ferror, clearerr," "fileno \- stream status inquiries" "" ferror(3)
+-.xx "" "cmp \- compare two" "files" "" cmp(1)
+-.xx "" "select or reject lines common to two sorted" "files" "comm \-" comm(1)
+-.xx "" "find \- find" "files" "" find(1)
+-.xx "" "rm, rmdir \- remove (unlink)" "files" "" rm(1)
+-.xx "" "sort \- sort or merge" "files" "" sort(1)
+-.xx "" "mv \- move or rename" "files and directories" "" mv(1)
+-.xx "" "dumpdir \- print the names of" "files on a dump tape" "" dumpdir(1)
+-.xx "volume" "" "filsys, flblk, ino \- format of file system" "" filsys(5)
+-.xx "" "col \-" "filter reverse line feeds" "" col(1)
+-.xx "" "plot \- graphics" "filters" "" plot(1)
+-.xx "" "" "find \- find files" "" find(1)
+-.xx "documents" "refer, lookbib \-" "find and insert literature references in" "" refer(1)
+-.xx "" "find \-" "find files" "" find(1)
+-.xx "" "look \-" "find lines in a sorted list" "" look(1)
+-.xx "" "ttyname, isatty, ttyslot \-" "find name of a terminal" "" ttyname(3)
+-.xx "" "lorder \-" "find ordering relation for an object library" "" lorder(1)
+-.xx "" "spell, spellin, spellout \-" "find spelling errors" "" spell(1)
+-.xx "" "dbminit, fetch, store, delete," "firstkey, nextkey \- data base subroutines" "" dbm(3)
+-.xx "" "hs \- RH11/RS03-RS04" "fixed-head disk file" "" hs(4)
+-.xx "" "rf \- RF11/RS11" "fixed-head disk file" "" rf(4)
+-.xx "" "filsys," "flblk, ino \- format of file system volume" "" filsys(5)
+-.xx "functions" "fabs," "floor, ceil \- absolute value, floor, ceiling" "" floor(3)
+-.xx "" "fclose, fflush \- close or" "flush a stream" "" fclose(3)
+-.xx "" "" "fopen, freopen, fdopen \- open a stream" "" fopen(3)
+-.xx "" "" "fork \- spawn new process" "" fork(2)
+-.xx "" "ar \- archive (library) file" "format" "" ar(5)
+-.xx "" "arcv \- convert archives to new" "format" "" arcv(1)
+-.xx "" "dump, ddate \- incremental dump" "format" "" dump(5)
+-.xx "" "core \-" "format of core image file" "" core(5)
+-.xx "" "dir \-" "format of directories" "" dir(5)
+-.xx "" "filsys, flblk, ino \-" "format of file system volume" "" filsys(5)
+-.xx "" "tbl \-" "format tables for nroff or troff" "" tbl(1)
+-.xx "" "roff \-" "format text" "" roff(1)
+-.xx "" "tp \- DEC/mag tape" "formats" "" tp(5)
+-.xx "" "scanf, fscanf, sscanf \-" "formatted input conversion" "" scanf(3)
+-.xx "" "printf, fprintf, sprintf \-" "formatted output conversion" "" printf(3)
+-.xx "" "troff, nroff \- text" "formatting and typesetting" "" troff(1)
+-.xx "" "ms \- macros for" "formatting manuscripts" "" ms(7)
+-.xx "" "f77 \-" "Fortran 77 compiler" "" f77(1)
+-.xx "" "ratfor \- rational" "Fortran dialect" "" ratfor(1)
+-.xx "" "struct \- structure" "Fortran programs" "" struct(1)
+-.xx "cookies" "ching," "fortune \- the book of changes and other" "" ching(6)
+-.xx "conversion" "printf," "fprintf, sprintf \- formatted output" "" printf(3)
+-.xx "stream" "putc, putchar," "fputc, putw \- put character or word on a" "" putc(3)
+-.xx "" "puts," "fputs \- put a string on a stream" "" puts(3)
+-.xx "" "" "fread, fwrite \- buffered binary input/output" "" fread(3)
+-.xx "" "df \- disk" "free" "" df(1)
+-.xx "allocator" "malloc," "free, realloc, calloc \- main memory" "" malloc(3)
+-.xx "" "fopen," "freopen, fdopen \- open a stream" "" fopen(3)
+-.xx "exponent" "" "frexp, ldexp, modf \- split into mantissa and" "" frexp(3)
+-.xx "" "scanf," "fscanf, sscanf \- formatted input conversion" "" scanf(3)
+-.xx "" "" "fseek, ftell, rewind \- reposition a stream" "" fseek(3)
+-.xx "" "stat," "fstat \- get file status" "" stat(2)
+-.xx "" "fseek," "ftell, rewind \- reposition a stream" "" fseek(3)
+-.xx "" "time," "ftime \- get date and time" "" time(2)
+-.xx "" "floor, ceil \- absolute value, floor, ceiling" "functions" "fabs," floor(3)
+-.xx "" "intro \- introduction to library" "functions" "" intro(3)
+-.xx "" "j0, j1, jn, y0, y1, yn \- bessel" "functions" "" j0(3)
+-.xx "" "tan, asin, acos, atan, atan2 \- trigonometric" "functions" "sin, cos," sin(3)
+-.xx "" "sinh, cosh, tanh \- hyperbolic" "functions" "" sinh(3)
+-.xx "" "fread," "fwrite \- buffered binary input/output" "" fread(3)
+-.xx "" "backgammon \- the" "game" "" backgammon(6)
+-.xx "" "checkers \-" "game" "" checkers(6)
+-.xx "" "moo \- guessing" "game" "" moo(6)
+-.xx "" "bj \- the" "game of black jack" "" bj(6)
+-.xx "" "chess \- the" "game of chess" "" chess(6)
+-.xx "" "reversi \- a" "game of dramatic reversals" "" reversi(6)
+-.xx "" "wump \- the" "game of hunt-the-wumpus" "" wump(6)
+-.xx "" "hangman, words \- word" "games" "" words(6)
+-.xx "" "itom, madd, msub, mult, mdiv, min, mout, pow," "gcd, rpow \- multiple precision integer/" "" mp(3)
+-.xx "" "ecvt, fcvt," "gcvt \- output conversion" "" ecvt(3)
+-.xx "" "maze \-" "generate a maze problem" "" maze(6)
+-.xx "" "mkconf \-" "generate configuration tables" "" mkconf(1)
+-.xx "" "makekey \-" "generate encryption key" "" makekey(8)
+-.xx "" "abort \-" "generate IOT fault" "" abort(3)
+-.xx "" "factor, primes \- factor a number," "generate large primes" "" factor(1)
+-.xx "" "ncheck \-" "generate names from i-numbers" "" ncheck(1)
+-.xx "" "rand, srand \- random number" "generator" "" rand(3)
+-.xx "" "lex \-" "generator of lexical analysis programs" "" lex(1)
+-.xx "or word from stream" "" "getc, getchar, fgetc, getw \- get character" "" getc(3)
+-.xx "" "getuid, getgid, geteuid," "getegid \- get user and group identity" "" getuid(2)
+-.xx "" "" "getenv \- value for environment name" "" getenv(3)
+-.xx "identity" "getuid, getgid," "geteuid, getegid \- get user and group" "" getuid(2)
+-.xx "endgrent \- get group file entry" "" "getgrent, getgrgid, getgrnam, setgrent," "" getgrent(3)
+-.xx "" "" "getlogin \- get login name" "" getlogin(3)
+-.xx "" "" "getpass \- read a password" "" getpass(3)
+-.xx "" "" "getpid \- get process identification" "" getpid(2)
+-.xx "" "" "getpw \- get name from UID" "" getpw(3)
+-.xx "endpwent \- get password file entry" "" "getpwent, getpwuid, getpwnam, setpwent," "" getpwent(3)
+-.xx "" "" "gets, fgets \- get a string from a stream" "" gets(3)
+-.xx "" "" "getty \- set typewriter mode" "" getty(8)
+-.xx "and group identity" "" "getuid, getgid, geteuid, getegid \- get user" "" getuid(2)
+-.xx "" "getc, getchar, fgetc," "getw \- get character or word from stream" "" getc(3)
+-.xx "time to ASCII" "ctime, localtime," "gmtime, asctime, timezone \- convert date and" "" ctime(3)
+-.xx "" "setjmp, longjmp \- non-local" "goto" "" setjmp(3)
+-.xx "" "graph \- draw a" "graph" "" graph(1)
+-.xx "" "plot \-" "graphics filters" "" plot(1)
+-.xx "" "plot: openpl et al. \-" "graphics interface" "" plot(3)
+-.xx "" "plot \-" "graphics interface" "" plot(5)
+-.xx "pattern" "" "grep, egrep, fgrep \- search a file for a" "" grep(1)
+-.xx "" "chown, chgrp \- change owner or" "group" "" chown(1)
+-.xx "" "newgrp \- log in to a new" "group" "" newgrp(1)
+-.xx "" "" "group \- group file" "" group(5)
+-.xx "" "getgrgid, getgrnam, setgrent, endgrent \- get" "group file entry" "getgrent," getgrent(3)
+-.xx "" "setuid, setgid \- set user and" "group ID" "" setuid(2)
+-.xx "" "getgid, geteuid, getegid \- get user and" "group identity" "getuid," getuid(2)
+-.xx "" "chown \- change owner and" "group of a file" "" chown(2)
+-.xx "" "make \- maintain program" "groups" "" make(1)
+-.xx "" "ioctl, stty," "gtty \- control device" "" ioctl(2)
+-.xx "" "moo \-" "guessing game" "" moo(6)
+-.xx "" "" "hangman, words \- word games" "" words(6)
+-.xx "" "" "hier \- file system hierarchy" "" hier(7)
+-.xx "" "" "hp \- RH-11/RP04, RP05, RP06 moving-head disk" "" hp(4)
+-.xx "" "" "hs \- RH11/RS03-RS04 fixed-head disk file" "" hs(4)
+-.xx "" "" "ht \- RH-11/TU-16 magtape interface" "" ht(4)
+-.xx "" "wump \- the game of" "hunt-the-wumpus" "" wump(6)
+-.xx "" "sinh, cosh, tanh \-" "hyperbolic functions" "" sinh(3)
+-.xx "" "" "hypot, cabs \- euclidean distance" "" hypot(3)
+-.xx "check" "" "icheck \- file system storage consistency" "" icheck(1)
+-.xx "" "setuid, setgid \- set user and group" "ID" "" setuid(2)
+-.xx "" "su \- substitute user" "id temporarily" "" su(1)
+-.xx "" "getpid \- get process" "identification" "" getpid(2)
+-.xx "" "geteuid, getegid \- get user and group" "identity" "getuid, getgid," getuid(2)
+-.xx "exit, export, login, newgrp,/" "sh, for, case," "if, while, break, continue, cd, eval, exec," "" sh(1)
+-.xx "" "signal \- catch or" "ignore signals" "" signal(2)
+-.xx "" "core \- format of core" "image file" "" core(5)
+-.xx "" "dump, ddate \-" "incremental dump format" "" dump(5)
+-.xx "" "dump \-" "incremental file system dump" "" dump(1)
+-.xx "" "restor \-" "incremental file system restore" "" restor(1)
+-.xx "" "ptx \- permuted" "index" "" ptx(1)
+-.xx "" "strcmp, strncmp, strcpy, strncpy, strlen," "index, rindex \- string operations" "/strncat," string(3)
+-.xx "" "" "indir \- indirect system call" "" indir(2)
+-.xx "" "" "init, rc \- process control initialization" "" init(8)
+-.xx "" "ttys \- terminal" "initialization data" "" ttys(5)
+-.xx "" "popen, pclose \-" "initiate I/O to/from a process" "" popen(3)
+-.xx "" "filsys, flblk," "ino \- format of file system volume" "" filsys(5)
+-.xx "" "clri \- clear" "i-node" "" clri(1)
+-.xx "" "scanf, fscanf, sscanf \- formatted" "input conversion" "" scanf(3)
+-.xx "" "ungetc \- push character back into" "input stream" "" ungetc(3)
+-.xx "" "fread, fwrite \- buffered binary" "input/output" "" fread(3)
+-.xx "" "stdio \- standard buffered" "input/output package" "" stdio(3)
+-.xx "" "ferror, clearerr, fileno \- stream status" "inquiries" "feof," ferror(3)
+-.xx "" "refer, lookbib \- find and" "insert literature references in documents" "" refer(1)
+-.xx "" "cat \- phototypesetter" "interface" "" cat(4)
+-.xx "" "dn \- DN-11 ACU" "interface" "" dn(4)
+-.xx "" "du, dp \- DU-11 201 data-phone" "interface" "" du(4)
+-.xx "" "ht \- RH-11/TU-16 magtape" "interface" "" ht(4)
+-.xx "" "plot: openpl et al. \- graphics" "interface" "" plot(3)
+-.xx "" "plot \- graphics" "interface" "" plot(5)
+-.xx "" "tm \- TM-11/TU-10 magtape" "interface" "" tm(4)
+-.xx "" "tty \- general terminal" "interface" "" tty(4)
+-.xx "" "spline \-" "interpolate smooth curve" "" spline(1)
+-.xx "" "pipe \- create an" "interprocess channel" "" pipe(2)
+-.xx "" "intro \-" "introduction to commands" "" intro(1)
+-.xx "" "intro \-" "introduction to library functions" "" intro(3)
+-.xx "numbers" "intro, errno \-" "introduction to system calls and error" "" intro(2)
+-.xx "" "ncheck \- generate names from" "i-numbers" "" ncheck(1)
+-.xx "" "iostat \- report" "I/O statistics" "" iostat(1)
+-.xx "" "popen, pclose \- initiate" "I/O to/from a process" "" popen(3)
+-.xx "" "" "ioctl, stty, gtty \- control device" "" ioctl(2)
+-.xx "" "" "iostat \- report I/O statistics" "" iostat(1)
+-.xx "" "abort \- generate" "IOT fault" "" abort(3)
+-.xx "isascii/" "isalpha, isupper, islower, isdigit," "isalnum, isspace, ispunct, isprint, iscntrl," "" ctype(3)
+-.xx "" "ttyname," "isatty, ttyslot \- find name of a terminal" "" ttyname(3)
+-.xx "" "/isdigit, isalnum, isspace, ispunct, isprint," "iscntrl, isascii \- character classification" "" ctype(3)
+-.xx "" "system \-" "issue a shell command" "" system(3)
+-.xx "ispunct, isprint, iscntrl, isascii/" "isalpha," "isupper, islower, isdigit, isalnum, isspace," "" ctype(3)
+-.xx "gcd, rpow \- multiple precision integer/" "" "itom, madd, msub, mult, mdiv, min, mout, pow," "" mp(3)
+-.xx "" "" "j0, j1, jn, y0, y1, yn \- bessel functions" "" j0(3)
+-.xx "" "bj \- the game of black" "jack" "" bj(6)
+-.xx "" "j0, j1," "jn, y0, y1, yn \- bessel functions" "" j0(3)
+-.xx "" "" "join \- relational database operator" "" join(1)
+-.xx "" "makekey \- generate encryption" "key" "" makekey(8)
+-.xx "" "" "kill \- send signal to a process" "" kill(2)
+-.xx "prejudice" "" "kill \- terminate a process with extreme" "" kill(1)
+-.xx "" "mem," "kmem \- core memory" "" mem(4)
+-.xx "integers and long integers" "" "l3tol, ltol3 \- convert between 3-byte" "" l3tol(3)
+-.xx "" "awk \- pattern scanning and processing" "language" "" awk(1)
+-.xx "" "bc \- arbitrary-precision arithmetic" "language" "" bc(1)
+-.xx "" "shift, times, trap, umask, wait \- command" "language" "/login, newgrp, read, readonly, set," sh(1)
+-.xx "" "" "ld \- loader" "" ld(1)
+-.xx "exponent" "frexp," "ldexp, modf \- split into mantissa and" "" frexp(3)
+-.xx "" "" "lex \- generator of lexical analysis programs" "" lex(1)
+-.xx "" "\- find ordering relation for an object" "library" "lorder" lorder(1)
+-.xx "" "ar \- archive (" "library) file format" "" ar(5)
+-.xx "" "intro \- introduction to" "library functions" "" intro(3)
+-.xx "" "ar \- archive and" "library maintainer" "" ar(1)
+-.xx "" "col \- filter reverse" "line feeds" "" col(1)
+-.xx "" "comm \- select or reject" "lines common to two sorted files" "" comm(1)
+-.xx "" "uniq \- report repeated" "lines in a file" "" uniq(1)
+-.xx "" "look \- find" "lines in a sorted list" "" look(1)
+-.xx "" "rev \- reverse" "lines of a file" "" rev(1)
+-.xx "" "ln \- make a" "link" "" ln(1)
+-.xx "" "" "link \- link to a file" "" link(2)
+-.xx "" "a.out \- assembler and" "link editor output" "" a.out(5)
+-.xx "" "link \-" "link to a file" "" link(2)
+-.xx "" "" "lint \- a C program verifier" "" lint(1)
+-.xx "" "look \- find lines in a sorted" "list" "" look(1)
+-.xx "" "nlist \- get entries from name" "list" "" nlist(3)
+-.xx "" "nm \- print name" "list" "" nm(1)
+-.xx "" "ls \-" "list contents of directory" "" ls(1)
+-.xx "" "refer, lookbib \- find and insert" "literature references in documents" "" refer(1)
+-.xx "" "" "ln \- make a link" "" ln(1)
+-.xx "" "ld \-" "loader" "" ld(1)
+-.xx "convert date and time to ASCII" "ctime," "localtime, gmtime, asctime, timezone \-" "" ctime(3)
+-.xx "" "end, etext, edata \- last" "locations in program" "" end(3)
+-.xx "" "" "lock \- lock a process in primary memory" "" lock(2)
+-.xx "" "newgrp \-" "log in to a new group" "" newgrp(1)
+-.xx "logarithm, power, square root" "exp," "log, log10, pow, sqrt \- exponential," "" exp(3)
+-.xx "" "" "login \- sign on" "" login(1)
+-.xx "" "ac \-" "login accounting" "" ac(1)
+-.xx "" "getlogin \- get" "login name" "" getlogin(3)
+-.xx "" "/continue, cd, eval, exec, exit, export," "login, newgrp, read, readonly, set, shift,/" "" sh(1)
+-.xx "" "passwd \- change" "login password" "" passwd(1)
+-.xx "" "utmp, wtmp \-" "login records" "" utmp(5)
+-.xx "" "setjmp," "longjmp \- non-local goto" "" setjmp(3)
+-.xx "" "" "look \- find lines in a sorted list" "" look(1)
+-.xx "references in documents" "refer," "lookbib \- find and insert literature" "" refer(1)
+-.xx "object library" "" "lorder \- find ordering relation for an" "" lorder(1)
+-.xx "" "" "ls \- list contents of directory" "" ls(1)
+-.xx "" "" "lseek, tell \- move read/write pointer" "" lseek(2)
+-.xx "long integers" "l3tol," "ltol3 \- convert between 3-byte integers and" "" l3tol(3)
+-.xx "" "" "m4 \- macro processor" "" m4(1)
+-.xx "" "ms \-" "macros for formatting manuscripts" "" ms(7)
+-.xx "" "man \-" "macros to typeset manual" "" man(7)
+-.xx "rpow \- multiple precision integer/" "itom," "madd, msub, mult, mdiv, min, mout, pow, gcd," "" mp(3)
+-.xx "" "tp \- DEC/" "mag tape formats" "" tp(5)
+-.xx "" "ht \- RH-11/TU-16" "magtape interface" "" ht(4)
+-.xx "" "tm \- TM-11/TU-10" "magtape interface" "" tm(4)
+-.xx "" "xsend, xget, enroll \- secret" "mail" "" xsend(1)
+-.xx "" "" "mail \- send or receive mail among users" "" mail(1)
+-.xx "" "malloc, free, realloc, calloc \-" "main memory allocator" "" malloc(3)
+-.xx "" "make \-" "maintain program groups" "" make(1)
+-.xx "" "ar \- archive and library" "maintainer" "" ar(1)
+-.xx "" "" "make \- maintain program groups" "" make(1)
+-.xx "" "mkdir \-" "make a directory" "" mkdir(1)
+-.xx "" "mknod \-" "make a directory or a special file" "" mknod(2)
+-.xx "" "ln \-" "make a link" "" ln(1)
+-.xx "" "mktemp \-" "make a unique file name" "" mktemp(3)
+-.xx "" "banner \-" "make long posters" "" banner(6)
+-.xx "" "" "makekey \- generate encryption key" "" makekey(8)
+-.xx "allocator" "" "malloc, free, realloc, calloc \- main memory" "" malloc(3)
+-.xx "" "" "man \- macros to typeset manual" "" man(7)
+-.xx "" "" "man \- print sections of this manual" "" man(1)
+-.xx "" "tp \-" "manipulate tape archive" "" tp(1)
+-.xx "" "frexp, ldexp, modf \- split into" "mantissa and exponent" "" frexp(3)
+-.xx "" "man \- print sections of this" "manual" "" man(1)
+-.xx "" "man \- macros to typeset" "manual" "" man(7)
+-.xx "" "ms \- macros for formatting" "manuscripts" "" ms(7)
+-.xx "" "umask \- set file creation mode" "mask" "" umask(2)
+-.xx "" "eqn, neqn, checkeq \- typeset" "mathematics" "" eqn(1)
+-.xx "" "" "maze \- generate a maze problem" "" maze(6)
+-.xx "precision integer/" "itom, madd, msub, mult," "mdiv, min, mout, pow, gcd, rpow \- multiple" "" mp(3)
+-.xx "" "bcd, ppt \- convert to antique" "media" "" bcd(6)
+-.xx "" "" "mem, kmem \- core memory" "" mem(4)
+-.xx "" "lock \- lock a process in primary" "memory" "" lock(2)
+-.xx "" "mem, kmem \- core" "memory" "" mem(4)
+-.xx "" "malloc, free, realloc, calloc \- main" "memory allocator" "" malloc(3)
+-.xx "" "sort \- sort or" "merge files" "" sort(1)
+-.xx "" "" "mesg \- permit or deny messages" "" mesg(1)
+-.xx "" "perror, sys_errlist, sys_nerr \- system error" "messages" "" perror(3)
+-.xx "precision/" "itom, madd, msub, mult, mdiv," "min, mout, pow, gcd, rpow \- multiple" "" mp(3)
+-.xx "" "" "mkconf \- generate configuration tables" "" mkconf(1)
+-.xx "" "" "mkdir \- make a directory" "" mkdir(1)
+-.xx "" "" "mkfs \- construct a file system" "" mkfs(1)
+-.xx "" "" "mknod \- build special file" "" mknod(1)
+-.xx "" "" "mknod \- make a directory or a special file" "" mknod(2)
+-.xx "" "" "mktemp \- make a unique file name" "" mktemp(3)
+-.xx "" "chmod \- change" "mode" "" chmod(1)
+-.xx "" "getty \- set typewriter" "mode" "" getty(8)
+-.xx "" "umask \- set file creation" "mode mask" "" umask(2)
+-.xx "" "chmod \- change" "mode of file" "" chmod(2)
+-.xx "" "frexp, ldexp," "modf \- split into mantissa and exponent" "" frexp(3)
+-.xx "" "touch \- update date last" "modified of a file" "" touch(1)
+-.xx "" "" "monitor \- prepare execution profile" "" monitor(3)
+-.xx "" "" "moo \- guessing game" "" moo(6)
+-.xx "" "mount, umount \-" "mount and dismount file system" "" mount(1)
+-.xx "" "mount, umount \-" "mount or remove file system" "" mount(2)
+-.xx "system" "" "mount, umount \- mount and dismount file" "" mount(1)
+-.xx "" "" "mount, umount \- mount or remove file system" "" mount(2)
+-.xx "" "mtab \-" "mounted file system table" "" mtab(5)
+-.xx "integer/" "itom, madd, msub, mult, mdiv, min," "mout, pow, gcd, rpow \- multiple precision" "" mp(3)
+-.xx "" "mv \-" "move or rename files and directories" "" mv(1)
+-.xx "" "lseek, tell \-" "move read/write pointer" "" lseek(2)
+-.xx "" "hp \- RH-11/RP04, RP05, RP06" "moving-head disk" "" hp(4)
+-.xx "" "rp \- RP-11/RP03" "moving-head disk" "" rp(4)
+-.xx "" "" "ms \- macros for formatting manuscripts" "" ms(7)
+-.xx "\- multiple precision integer/" "itom, madd," "msub, mult, mdiv, min, mout, pow, gcd, rpow" "" mp(3)
+-.xx "" "" "mtab \- mounted file system table" "" mtab(5)
+-.xx "multiple precision integer/" "itom, madd, msub," "mult, mdiv, min, mout, pow, gcd, rpow \-" "" mp(3)
+-.xx "" "" "mv \- move or rename files and directories" "" mv(1)
+-.xx "" "getenv \- value for environment" "name" "" getenv(3)
+-.xx "" "getlogin \- get login" "name" "" getlogin(3)
+-.xx "" "mktemp \- make a unique file" "name" "" mktemp(3)
+-.xx "" "pwd \- working directory" "name" "" pwd(1)
+-.xx "" "tty \- get terminal" "name" "" tty(1)
+-.xx "" "getpw \- get" "name from UID" "" getpw(3)
+-.xx "" "nlist \- get entries from" "name list" "" nlist(3)
+-.xx "" "nm \- print" "name list" "" nm(1)
+-.xx "" "ttyname, isatty, ttyslot \- find" "name of a terminal" "" ttyname(3)
+-.xx "" "terminals\- conventional" "names" "" term(7)
+-.xx "" "ncheck \- generate" "names from i-numbers" "" ncheck(1)
+-.xx "" "dumpdir \- print the" "names of files on a dump tape" "" dumpdir(1)
+-.xx "" "" "ncheck \- generate names from i-numbers" "" ncheck(1)
+-.xx "" "eqn," "neqn, checkeq \- typeset mathematics" "" eqn(1)
+-.xx "" "creat \- create a" "new file" "" creat(2)
+-.xx "" "arcv \- convert archives to" "new format" "" arcv(1)
+-.xx "" "newgrp \- log in to a" "new group" "" newgrp(1)
+-.xx "" "fork \- spawn" "new process" "" fork(2)
+-.xx "" "" "newgrp \- log in to a new group" "" newgrp(1)
+-.xx "trap,/" "/cd, eval, exec, exit, export, login," "newgrp, read, readonly, set, shift, times," "" sh(1)
+-.xx "" "dbminit, fetch, store, delete, firstkey," "nextkey \- data base subroutines" "" dbm(3)
+-.xx "" "" "nice \- set program priority" "" nice(2)
+-.xx "" "" "nice, nohup \- run a command at low priority" "" nice(1)
+-.xx "" "" "nlist \- get entries from name list" "" nlist(3)
+-.xx "" "" "nm \- print name list" "" nm(1)
+-.xx "" "clri \- clear i-" "node" "" clri(1)
+-.xx "" "nice," "nohup \- run a command at low priority" "" nice(1)
+-.xx "" "setjmp, longjmp \-" "non-local goto" "" setjmp(3)
+-.xx "" "troff," "nroff \- text formatting and typesetting" "" troff(1)
+-.xx "" "tbl \- format tables for" "nroff or troff" "" tbl(1)
+-.xx "" "deroff \- remove" "nroff, troff, tbl and eqn constructs" "" deroff(1)
+-.xx "" "" "null \- data sink" "" null(4)
+-.xx "" "arithmetic \- provide drill in" "number facts" "" arithmetic(6)
+-.xx "" "factor, primes \- factor a" "number, generate large primes" "" factor(1)
+-.xx "" "rand, srand \- random" "number generator" "" rand(3)
+-.xx "" "atof, atoi, atol \- convert ASCII to" "numbers" "" atof(3)
+-.xx "" "\- introduction to system calls and error" "numbers" "intro, errno" intro(2)
+-.xx "" "ncheck \- generate names from i-" "numbers" "" ncheck(1)
+-.xx "" "size \- size of an" "object file" "" size(1)
+-.xx "" "lorder \- find ordering relation for an" "object library" "" lorder(1)
+-.xx "" "od \-" "octal dump" "" od(1)
+-.xx "" "" "open \- open for reading or writing" "" open(2)
+-.xx "" "fopen, freopen, fdopen \-" "open a stream" "" fopen(3)
+-.xx "" "dup, dup2 \- duplicate an" "open file descriptor" "" dup(2)
+-.xx "" "open \-" "open for reading or writing" "" open(2)
+-.xx "" "plot:" "openpl et al. \- graphics interface" "" plot(3)
+-.xx "" "strncpy, strlen, index, rindex \- string" "operations" "/strncat, strcmp, strncmp, strcpy," string(3)
+-.xx "" "join \- relational database" "operator" "" join(1)
+-.xx "" "stty \- set terminal" "options" "" stty(1)
+-.xx "" "lorder \- find" "ordering relation for an object library" "" lorder(1)
+-.xx "" "a.out \- assembler and link editor" "output" "" a.out(5)
+-.xx "" "fread, fwrite \- buffered binary input/" "output" "" fread(3)
+-.xx "" "ecvt, fcvt, gcvt \-" "output conversion" "" ecvt(3)
+-.xx "" "printf, fprintf, sprintf \- formatted" "output conversion" "" printf(3)
+-.xx "" "stdio \- standard buffered input/" "output package" "" stdio(3)
+-.xx "" "chown \- change" "owner and group of a file" "" chown(2)
+-.xx "" "chown, chgrp \- change" "owner or group" "" chown(1)
+-.xx "" "quot \- summarize file system" "ownership" "" quot(1)
+-.xx "" "pk \-" "packet driver" "" pk(4)
+-.xx "" "pkopen, pkclose, pkread, pkwrite, pkfail \-" "packet driver simulator" "" pkopen(3)
+-.xx "" "pkon, pkoff \- establish" "packet protocol" "" pkon(2)
+-.xx "" "tk \-" "paginator for the Tektronix 4014" "" tk(1)
+-.xx "" "" "passwd \- change login password" "" passwd(1)
+-.xx "" "" "passwd \- password file" "" passwd(5)
+-.xx "" "getpass \- read a" "password" "" getpass(3)
+-.xx "" "passwd \- change login" "password" "" passwd(1)
+-.xx "" "passwd \-" "password file" "" passwd(5)
+-.xx "" "getpwuid, getpwnam, setpwent, endpwent \- get" "password file entry" "getpwent," getpwent(3)
+-.xx "" "grep, egrep, fgrep \- search a file for a" "pattern" "" grep(1)
+-.xx "" "awk \-" "pattern scanning and processing language" "" awk(1)
+-.xx "" "" "pause \- stop until signal" "" pause(2)
+-.xx "" "cc," "pcc \- C compiler" "" cc(1)
+-.xx "" "popen," "pclose \- initiate I/O to/from a process" "" popen(3)
+-.xx "" "mesg \-" "permit or deny messages" "" mesg(1)
+-.xx "" "ptx \-" "permuted index" "" ptx(1)
+-.xx "messages" "" "perror, sys_errlist, sys_nerr \- system error" "" perror(3)
+-.xx "" "du, dp \- DU-11 201 data-" "phone interface" "" du(4)
+-.xx "" "cat \-" "phototypesetter interface" "" cat(4)
+-.xx "" "tc \-" "photypesetter simulator" "" tc(1)
+-.xx "addresses" "" "phys \- allow a process to access physical" "" phys(2)
+-.xx "" "" "pipe \- create an interprocess channel" "" pipe(2)
+-.xx "" "tee \-" "pipe fitting" "" tee(1)
+-.xx "" "" "pk \- packet driver" "" pk(4)
+-.xx "driver simulator" "pkopen," "pkclose, pkread, pkwrite, pkfail \- packet" "" pkopen(3)
+-.xx "" "pkon," "pkoff \- establish packet protocol" "" pkon(2)
+-.xx "packet driver simulator" "" "pkopen, pkclose, pkread, pkwrite, pkfail \-" "" pkopen(3)
+-.xx "" "" "plot \- graphics filters" "" plot(1)
+-.xx "" "" "plot \- graphics interface" "" plot(5)
+-.xx "" "" "plot: openpl et al. \- graphics interface" "" plot(3)
+-.xx "" "vp \- Versatec printer-" "plotter" "" vp(4)
+-.xx "" "lseek, tell \- move read/write" "pointer" "" lseek(2)
+-.xx "process" "" "popen, pclose \- initiate I/O to/from a" "" popen(3)
+-.xx "" "banner \- make long" "posters" "" banner(6)
+-.xx "" "itom, madd, msub, mult, mdiv, min, mout," "pow, gcd, rpow \- multiple precision integer/" "" mp(3)
+-.xx "square root" "exp, log, log10," "pow, sqrt \- exponential, logarithm, power," "" exp(3)
+-.xx "" "bcd," "ppt \- convert to antique media" "" bcd(6)
+-.xx "" "" "pr \- print file" "" pr(1)
+-.xx "" "bc \- arbitrary-" "precision arithmetic language" "" bc(1)
+-.xx "" "mdiv, min, mout, pow, gcd, rpow \- multiple" "precision integer arithmetic" "/msub, mult," mp(3)
+-.xx "" "monitor \-" "prepare execution profile" "" monitor(3)
+-.xx "" "lock \- lock a process in" "primary memory" "" lock(2)
+-.xx "" "primes \- factor a number, generate large" "primes" "factor," factor(1)
+-.xx "" "types \-" "primitive system data types" "" types(5)
+-.xx "" "cat \- catenate and" "print" "" cat(1)
+-.xx "" "date \-" "print and set the date" "" date(1)
+-.xx "" "cal \-" "print calendar" "" cal(1)
+-.xx "" "pr \-" "print file" "" pr(1)
+-.xx "" "nm \-" "print name list" "" nm(1)
+-.xx "" "man \-" "print sections of this manual" "" man(1)
+-.xx "" "pstat \-" "print system facts" "" pstat(1)
+-.xx "" "dumpdir \-" "print the names of files on a dump tape" "" dumpdir(1)
+-.xx "" "vp \- Versatec" "printer-plotter" "" vp(4)
+-.xx "conversion" "" "printf, fprintf, sprintf \- formatted output" "" printf(3)
+-.xx "" "nice, nohup \- run a command at low" "priority" "" nice(1)
+-.xx "" "nice \- set program" "priority" "" nice(2)
+-.xx "" "boot \- startup" "procedures" "" boot(8)
+-.xx "" "exit \- terminate" "process" "" exit(2)
+-.xx "" "fork \- spawn new" "process" "" fork(2)
+-.xx "" "kill \- send signal to a" "process" "" kill(2)
+-.xx "" "popen, pclose \- initiate I/O to/from a" "process" "" popen(3)
+-.xx "" "wait \- await completion of" "process" "" wait(1)
+-.xx "" "init, rc \-" "process control initialization" "" init(8)
+-.xx "" "getpid \- get" "process identification" "" getpid(2)
+-.xx "" "lock \- lock a" "process in primary memory" "" lock(2)
+-.xx "" "ps \-" "process status" "" ps(1)
+-.xx "" "times \- get" "process times" "" times(2)
+-.xx "" "phys \- allow a" "process to access physical addresses" "" phys(2)
+-.xx "" "wait \- wait for" "process to terminate" "" wait(2)
+-.xx "" "ptrace \-" "process trace" "" ptrace(2)
+-.xx "" "kill \- terminate a" "process with extreme prejudice" "" kill(1)
+-.xx "" "awk \- pattern scanning and" "processing language" "" awk(1)
+-.xx "" "m4 \- macro" "processor" "" m4(1)
+-.xx "" "" "prof \- display profile data" "" prof(1)
+-.xx "" "" "profil \- execution time profile" "" profil(2)
+-.xx "" "monitor \- prepare execution" "profile" "" monitor(3)
+-.xx "" "profil \- execution time" "profile" "" profil(2)
+-.xx "" "prof \- display" "profile data" "" prof(1)
+-.xx "" "end, etext, edata \- last locations in" "program" "" end(3)
+-.xx "" "units \- conversion" "program" "" units(1)
+-.xx "" "cb \- C" "program beautifier" "" cb(1)
+-.xx "" "make \- maintain" "program groups" "" make(1)
+-.xx "" "nice \- set" "program priority" "" nice(2)
+-.xx "" "assert \-" "program verification" "" assert(3)
+-.xx "" "lint \- a C" "program verifier" "" lint(1)
+-.xx "" "lex \- generator of lexical analysis" "programs" "" lex(1)
+-.xx "" "struct \- structure Fortran" "programs" "" struct(1)
+-.xx "" "pkon, pkoff \- establish packet" "protocol" "" pkon(2)
+-.xx "" "arithmetic \-" "provide drill in number facts" "" arithmetic(6)
+-.xx "" "true, false \-" "provide truth values" "" true(1)
+-.xx "" "" "ps \- process status" "" ps(1)
+-.xx "" "" "pstat \- print system facts" "" pstat(1)
+-.xx "" "" "ptrace \- process trace" "" ptrace(2)
+-.xx "" "" "ptx \- permuted index" "" ptx(1)
+-.xx "" "ungetc \-" "push character back into input stream" "" ungetc(3)
+-.xx "" "puts, fputs \-" "put a string on a stream" "" puts(3)
+-.xx "" "putc, putchar, fputc, putw \-" "put character or word on a stream" "" putc(3)
+-.xx "" "" "puts, fputs \- put a string on a stream" "" puts(3)
+-.xx "" "putc, putchar, fputc," "putw \- put character or word on a stream" "" putc(3)
+-.xx "" "" "pwd \- working directory name" "" pwd(1)
+-.xx "" "" "qsort \- quicker sort" "" qsort(3)
+-.xx "" "" "quiz \- test your knowledge" "" quiz(6)
+-.xx "" "" "quot \- summarize file system ownership" "" quot(1)
+-.xx "" "" "rand, srand \- random number generator" "" rand(3)
+-.xx "" "" "ratfor \- rational Fortran dialect" "" ratfor(1)
+-.xx "" "init," "rc \- process control initialization" "" init(8)
+-.xx "" "" "read \- read from file" "" read(2)
+-.xx "" "getpass \-" "read a password" "" getpass(3)
+-.xx "" "read \-" "read from file" "" read(2)
+-.xx "" "/cd, eval, exec, exit, export, login, newgrp," "read, readonly, set, shift, times, trap,/" "" sh(1)
+-.xx "" "open \- open for" "reading or writing" "" open(2)
+-.xx "" "/exec, exit, export, login, newgrp, read," "readonly, set, shift, times, trap, umask,/" "" sh(1)
+-.xx "" "lseek, tell \- move" "read/write pointer" "" lseek(2)
+-.xx "" "malloc, free," "realloc, calloc \- main memory allocator" "" malloc(3)
+-.xx "" "mail \- send or" "receive mail among users" "" mail(1)
+-.xx "" "utmp, wtmp \- login" "records" "" utmp(5)
+-.xx "references in documents" "" "refer, lookbib \- find and insert literature" "" refer(1)
+-.xx "" "comm \- select or" "reject lines common to two sorted files" "" comm(1)
+-.xx "" "lorder \- find ordering" "relation for an object library" "" lorder(1)
+-.xx "" "join \-" "relational database operator" "" join(1)
+-.xx "" "strip \- remove symbols and" "relocation bits" "" strip(1)
+-.xx "" "calendar \-" "reminder service" "" calendar(1)
+-.xx "" "unlink \-" "remove directory entry" "" unlink(2)
+-.xx "" "mount, umount \- mount or" "remove file system" "" mount(2)
+-.xx "" "deroff \-" "remove nroff, troff, tbl and eqn constructs" "" deroff(1)
+-.xx "" "strip \-" "remove symbols and relocation bits" "" strip(1)
+-.xx "" "rm, rmdir \-" "remove (unlink) files" "" rm(1)
+-.xx "" "mv \- move or" "rename files and directories" "" mv(1)
+-.xx "" "uniq \- report" "repeated lines in a file" "" uniq(1)
+-.xx "" "iostat \-" "report I/O statistics" "" iostat(1)
+-.xx "" "uniq \-" "report repeated lines in a file" "" uniq(1)
+-.xx "" "fseek, ftell, rewind \-" "reposition a stream" "" fseek(3)
+-.xx "" "" "restor \- incremental file system restore" "" restor(1)
+-.xx "" "" "rev \- reverse lines of a file" "" rev(1)
+-.xx "" "reversi \- a game of dramatic" "reversals" "" reversi(6)
+-.xx "" "col \- filter" "reverse line feeds" "" col(1)
+-.xx "" "rev \-" "reverse lines of a file" "" rev(1)
+-.xx "" "" "reversi \- a game of dramatic reversals" "" reversi(6)
+-.xx "" "fseek, ftell," "rewind \- reposition a stream" "" fseek(3)
+-.xx "" "" "rf \- RF11/RS11 fixed-head disk file" "" rf(4)
+-.xx "" "hp \-" "RH-11/RP04, RP05, RP06 moving-head disk" "" hp(4)
+-.xx "" "hs \-" "RH11/RS03-RS04 fixed-head disk file" "" hs(4)
+-.xx "" "ht \-" "RH-11/TU-16 magtape interface" "" ht(4)
+-.xx "" "strncmp, strcpy, strncpy, strlen, index," "rindex \- string operations" "/strncat, strcmp," string(3)
+-.xx "" "" "rk \- RK-11/RK03 or RK05 disk" "" rk(4)
+-.xx "" "" "rm, rmdir \- remove (unlink) files" "" rm(1)
+-.xx "" "" "roff \- format text" "" roff(1)
+-.xx "" "sqrt \- exponential, logarithm, power, square" "root" "exp, log, log10, pow," exp(3)
+-.xx "" "" "rp \- RP-11/RP03 moving-head disk" "" rp(4)
+-.xx "" "hp \- RH-11/" "RP04, RP05, RP06 moving-head disk" "" hp(4)
+-.xx "" "rp \-" "RP-11/RP03 moving-head disk" "" rp(4)
+-.xx "" "/madd, msub, mult, mdiv, min, mout, pow, gcd," "rpow \- multiple precision integer arithmetic" "" mp(3)
+-.xx "" "hs \- RH11/" "RS03-RS04 fixed-head disk file" "" hs(4)
+-.xx "" "rf \- RF11/" "RS11 fixed-head disk file" "" rf(4)
+-.xx "" "nice, nohup \-" "run a command at low priority" "" nice(1)
+-.xx "" "" "sa, accton \- system accounting" "" sa(1)
+-.xx "" "brk," "sbrk, break \- change core allocation" "" brk(2)
+-.xx "conversion" "" "scanf, fscanf, sscanf \- formatted input" "" scanf(3)
+-.xx "" "awk \- pattern" "scanning and processing language" "" awk(1)
+-.xx "" "alarm \-" "schedule signal after specified time" "" alarm(2)
+-.xx "" "grep, egrep, fgrep \-" "search a file for a pattern" "" grep(1)
+-.xx "" "xsend, xget, enroll \-" "secret mail" "" xsend(1)
+-.xx "" "man \- print" "sections of this manual" "" man(1)
+-.xx "" "" "sed \- stream editor" "" sed(1)
+-.xx "files" "comm \-" "select or reject lines common to two sorted" "" comm(1)
+-.xx "" "mail \-" "send or receive mail among users" "" mail(1)
+-.xx "" "kill \-" "send signal to a process" "" kill(2)
+-.xx "" "ascii \- map of ASCII character" "set" "" ascii(7)
+-.xx "" "umask \-" "set file creation mode mask" "" umask(2)
+-.xx "" "utime \-" "set file times" "" utime(2)
+-.xx "" "nice \-" "set program priority" "" nice(2)
+-.xx "" "/exit, export, login, newgrp, read, readonly," "set, shift, times, trap, umask, wait \-/" "" sh(1)
+-.xx "" "stty \-" "set terminal options" "" stty(1)
+-.xx "" "tabs \-" "set terminal tabs" "" tabs(1)
+-.xx "" "date \- print and" "set the date" "" date(1)
+-.xx "" "stime \-" "set time" "" stime(2)
+-.xx "" "getty \-" "set typewriter mode" "" getty(8)
+-.xx "" "setuid, setgid \-" "set user and group ID" "" setuid(2)
+-.xx "" "" "setbuf \- assign buffering to a stream" "" setbuf(3)
+-.xx "" "setuid," "setgid \- set user and group ID" "" setuid(2)
+-.xx "" "getgrent, getgrgid, getgrnam," "setgrent, endgrent \- get group file entry" "" getgrent(3)
+-.xx "" "" "setjmp, longjmp \- non-local goto" "" setjmp(3)
+-.xx "" "crypt," "setkey, encrypt \- DES encryption" "" crypt(3)
+-.xx "" "getpwent, getpwuid, getpwnam," "setpwent, endpwent \- get password file entry" "" getpwent(3)
+-.xx "" "" "setuid, setgid \- set user and group ID" "" setuid(2)
+-.xx "cd, eval, exec, exit, export, login, newgrp,/" "" "sh, for, case, if, while, break, continue," "" sh(1)
+-.xx "" "system \- issue a" "shell command" "" system(3)
+-.xx "" "/export, login, newgrp, read, readonly, set," "shift, times, trap, umask, wait \- command/" "" sh(1)
+-.xx "" "login \-" "sign on" "" login(1)
+-.xx "" "pause \- stop until" "signal" "" pause(2)
+-.xx "" "" "signal \- catch or ignore signals" "" signal(2)
+-.xx "" "alarm \- schedule" "signal after specified time" "" alarm(2)
+-.xx "" "kill \- send" "signal to a process" "" kill(2)
+-.xx "" "signal \- catch or ignore" "signals" "" signal(2)
+-.xx "" "pkread, pkwrite, pkfail \- packet driver" "simulator" "pkopen, pkclose," pkopen(3)
+-.xx "" "tc \- photypesetter" "simulator" "" tc(1)
+-.xx "trigonometric functions" "" "sin, cos, tan, asin, acos, atan, atan2 \-" "" sin(3)
+-.xx "" "" "sinh, cosh, tanh \- hyperbolic functions" "" sinh(3)
+-.xx "" "null \- data" "sink" "" null(4)
+-.xx "" "" "size \- size of an object file" "" size(1)
+-.xx "" "" "sleep \- suspend execution for an interval" "" sleep(1)
+-.xx "" "" "sleep \- suspend execution for interval" "" sleep(3)
+-.xx "" "spline \- interpolate" "smooth curve" "" spline(1)
+-.xx "" "qsort \- quicker" "sort" "" qsort(3)
+-.xx "" "tsort \- topological" "sort" "" tsort(1)
+-.xx "" "" "sort \- sort or merge files" "" sort(1)
+-.xx "" "comm \- select or reject lines common to two" "sorted files" "" comm(1)
+-.xx "" "look \- find lines in a" "sorted list" "" look(1)
+-.xx "" "fork \-" "spawn new process" "" fork(2)
+-.xx "" "alarm \- schedule signal after" "specified time" "" alarm(2)
+-.xx "errors" "" "spell, spellin, spellout \- find spelling" "" spell(1)
+-.xx "" "" "spline \- interpolate smooth curve" "" spline(1)
+-.xx "" "" "split \- split a file into pieces" "" split(1)
+-.xx "" "frexp, ldexp, modf \-" "split into mantissa and exponent" "" frexp(3)
+-.xx "" "printf, fprintf," "sprintf \- formatted output conversion" "" printf(3)
+-.xx "root" "exp, log, log10, pow," "sqrt \- exponential, logarithm, power, square" "" exp(3)
+-.xx "" "rand," "srand \- random number generator" "" rand(3)
+-.xx "" "scanf, fscanf," "sscanf \- formatted input conversion" "" scanf(3)
+-.xx "" "stdio \-" "standard buffered input/output package" "" stdio(3)
+-.xx "" "boot \-" "startup procedures" "" boot(8)
+-.xx "" "" "stat, fstat \- get file status" "" stat(2)
+-.xx "" "iostat \- report I/O" "statistics" "" iostat(1)
+-.xx "" "ps \- process" "status" "" ps(1)
+-.xx "" "stat, fstat \- get file" "status" "" stat(2)
+-.xx "" "feof, ferror, clearerr, fileno \- stream" "status inquiries" "" ferror(3)
+-.xx "package" "" "stdio \- standard buffered input/output" "" stdio(3)
+-.xx "" "" "stime \- set time" "" stime(2)
+-.xx "" "pause \-" "stop until signal" "" pause(2)
+-.xx "" "icheck \- file system" "storage consistency check" "" icheck(1)
+-.xx "subroutines" "dbminit, fetch," "store, delete, firstkey, nextkey \- data base" "" dbm(3)
+-.xx "strncpy, strlen, index, rindex \- string/" "" "strcat, strncat, strcmp, strncmp, strcpy," "" string(3)
+-.xx "" "fclose, fflush \- close or flush a" "stream" "" fclose(3)
+-.xx "" "fopen, freopen, fdopen \- open a" "stream" "" fopen(3)
+-.xx "" "fseek, ftell, rewind \- reposition a" "stream" "" fseek(3)
+-.xx "" "fgetc, getw \- get character or word from" "stream" "getc, getchar," getc(3)
+-.xx "" "gets, fgets \- get a string from a" "stream" "" gets(3)
+-.xx "" "fputc, putw \- put character or word on a" "stream" "putc, putchar," putc(3)
+-.xx "" "puts, fputs \- put a string on a" "stream" "" puts(3)
+-.xx "" "setbuf \- assign buffering to a" "stream" "" setbuf(3)
+-.xx "" "ungetc \- push character back into input" "stream" "" ungetc(3)
+-.xx "" "sed \-" "stream editor" "" sed(1)
+-.xx "" "feof, ferror, clearerr, fileno \-" "stream status inquiries" "" ferror(3)
+-.xx "" "gets, fgets \- get a" "string from a stream" "" gets(3)
+-.xx "" "puts, fputs \- put a" "string on a stream" "" puts(3)
+-.xx "" "strcpy, strncpy, strlen, index, rindex \-" "string operations" "/strncat, strcmp, strncmp," string(3)
+-.xx "" "" "strip \- remove symbols and relocation bits" "" strip(1)
+-.xx "" "basename \-" "strip filename affixes" "" basename(1)
+-.xx "" "/strncat, strcmp, strncmp, strcpy, strncpy," "strlen, index, rindex \- string operations" "" string(3)
+-.xx "" "" "struct \- structure Fortran programs" "" struct(1)
+-.xx "" "" "stty \- set terminal options" "" stty(1)
+-.xx "" "ioctl," "stty, gtty \- control device" "" ioctl(2)
+-.xx "" "" "su \- substitute user id temporarily" "" su(1)
+-.xx "" "store, delete, firstkey, nextkey \- data base" "subroutines" "dbminit, fetch," dbm(3)
+-.xx "" "su \-" "substitute user id temporarily" "" su(1)
+-.xx "" "" "sum \- sum and count blocks in a file" "" sum(1)
+-.xx "" "du \-" "summarize disk usage" "" du(1)
+-.xx "" "quot \-" "summarize file system ownership" "" quot(1)
+-.xx "" "sync \- update the" "super block" "" sync(1)
+-.xx "" "update \- periodically update the" "super block" "" update(8)
+-.xx "" "sync \- update" "super-block" "" sync(2)
+-.xx "" "sleep \-" "suspend execution for an interval" "" sleep(1)
+-.xx "" "sleep \-" "suspend execution for interval" "" sleep(3)
+-.xx "" "" "swab \- swap bytes" "" swab(3)
+-.xx "" "strip \- remove" "symbols and relocation bits" "" strip(1)
+-.xx "" "" "sync \- update super-block" "" sync(2)
+-.xx "" "" "sync \- update the super block" "" sync(1)
+-.xx "messages" "perror," "sys_errlist, sys_nerr \- system error" "" perror(3)
+-.xx "" "mtab \- mounted file system" "table" "" mtab(5)
+-.xx "" "mkconf \- generate configuration" "tables" "" mkconf(1)
+-.xx "" "tbl \- format" "tables for nroff or troff" "" tbl(1)
+-.xx "" "tabs \- set terminal" "tabs" "" tabs(1)
+-.xx "" "" "tail \- deliver the last part of a file" "" tail(1)
+-.xx "functions" "sin, cos," "tan, asin, acos, atan, atan2 \- trigonometric" "" sin(3)
+-.xx "" "sinh, cosh," "tanh \- hyperbolic functions" "" sinh(3)
+-.xx "" "dumpdir \- print the names of files on a dump" "tape" "" dumpdir(1)
+-.xx "" "tp \- manipulate" "tape archive" "" tp(1)
+-.xx "" "tar \-" "tape archiver" "" tar(1)
+-.xx "" "tp \- DEC/mag" "tape formats" "" tp(5)
+-.xx "" "" "tar \- tape archiver" "" tar(1)
+-.xx "" "" "tbl \- format tables for nroff or troff" "" tbl(1)
+-.xx "" "deroff \- remove nroff, troff," "tbl and eqn constructs" "" deroff(1)
+-.xx "" "" "tc \- photypesetter simulator" "" tc(1)
+-.xx "" "" "tc \- TC-11/TU56 DECtape" "" tc(4)
+-.xx "" "" "tee \- pipe fitting" "" tee(1)
+-.xx "" "tk \- paginator for the" "Tektronix 4014" "" tk(1)
+-.xx "" "lseek," "tell \- move read/write pointer" "" lseek(2)
+-.xx "" "su \- substitute user id" "temporarily" "" su(1)
+-.xx "" "ttyname, isatty, ttyslot \- find name of a" "terminal" "" ttyname(3)
+-.xx "" "ttys \-" "terminal initialization data" "" ttys(5)
+-.xx "" "tty \- general" "terminal interface" "" tty(4)
+-.xx "" "tty \- get" "terminal name" "" tty(1)
+-.xx "" "stty \- set" "terminal options" "" stty(1)
+-.xx "" "tabs \- set" "terminal tabs" "" tabs(1)
+-.xx "" "" "terminals\- conventional names" "" term(7)
+-.xx "" "wait \- wait for process to" "terminate" "" wait(2)
+-.xx "" "kill \-" "terminate a process with extreme prejudice" "" kill(1)
+-.xx "" "exit \-" "terminate process" "" exit(2)
+-.xx "" "" "test \- condition command" "" test(1)
+-.xx "" "quiz \-" "test your knowledge" "" quiz(6)
+-.xx "" "roff \- format" "text" "" roff(1)
+-.xx "" "ed \-" "text editor" "" ed(1)
+-.xx "" "troff, nroff \-" "text formatting and typesetting" "" troff(1)
+-.xx "" "ttt, cubic \-" "tic-tac-toe" "" ttt(6)
+-.xx "" "alarm \- schedule signal after specified" "time" "" alarm(2)
+-.xx "" "at \- execute commands at a later" "time" "" at(1)
+-.xx "" "stime \- set" "time" "" stime(2)
+-.xx "" "time, ftime \- get date and" "time" "" time(2)
+-.xx "" "" "time \- time a command" "" time(1)
+-.xx "" "" "time, ftime \- get date and time" "" time(2)
+-.xx "" "profil \- execution" "time profile" "" profil(2)
+-.xx "" "gmtime, asctime, timezone \- convert date and" "time to ASCII" "ctime, localtime," ctime(3)
+-.xx "" "times \- get process" "times" "" times(2)
+-.xx "" "utime \- set file" "times" "" utime(2)
+-.xx "" "" "times \- get process times" "" times(2)
+-.xx "" "/login, newgrp, read, readonly, set, shift," "times, trap, umask, wait \- command language" "" sh(1)
+-.xx "" "ctime, localtime, gmtime, asctime," "timezone \- convert date and time to ASCII" "" ctime(3)
+-.xx "" "" "tk \- paginator for the Tektronix 4014" "" tk(1)
+-.xx "" "" "tm \- TM-11/TU-10 magtape interface" "" tm(4)
+-.xx "" "tsort \-" "topological sort" "" tsort(1)
+-.xx "" "" "touch \- update date last modified of a file" "" touch(1)
+-.xx "" "" "tp \- DEC/mag tape formats" "" tp(5)
+-.xx "" "" "tp \- manipulate tape archive" "" tp(1)
+-.xx "" "" "tr \- translate characters" "" tr(1)
+-.xx "" "ptrace \- process" "trace" "" ptrace(2)
+-.xx "" "tr \-" "translate characters" "" tr(1)
+-.xx "" "newgrp, read, readonly, set, shift, times," "trap, umask, wait \- command language" "/login," sh(1)
+-.xx "" "sin, cos, tan, asin, acos, atan, atan2 \-" "trigonometric functions" "" sin(3)
+-.xx "" "tbl \- format tables for nroff or" "troff" "" tbl(1)
+-.xx "typesetting" "" "troff, nroff \- text formatting and" "" troff(1)
+-.xx "" "deroff \- remove nroff," "troff, tbl and eqn constructs" "" deroff(1)
+-.xx "" "" "true, false \- provide truth values" "" true(1)
+-.xx "" "" "tsort \- topological sort" "" tsort(1)
+-.xx "" "" "ttt, cubic \- tic-tac-toe" "" ttt(6)
+-.xx "" "" "tty \- general terminal interface" "" tty(4)
+-.xx "" "" "tty \- get terminal name" "" tty(1)
+-.xx "terminal" "" "ttyname, isatty, ttyslot \- find name of a" "" ttyname(3)
+-.xx "" "" "ttys \- terminal initialization data" "" ttys(5)
+-.xx "" "ttyname, isatty," "ttyslot \- find name of a terminal" "" ttyname(3)
+-.xx "" "tm \- TM-11/" "TU-10 magtape interface" "" tm(4)
+-.xx "" "ht \- RH-11/" "TU-16 magtape interface" "" ht(4)
+-.xx "" "tc \- TC-11/" "TU56 DECtape" "" tc(4)
+-.xx "" "file \- determine file" "type" "" file(1)
+-.xx "" "types \- primitive system data" "types" "" types(5)
+-.xx "" "man \- macros to" "typeset manual" "" man(7)
+-.xx "" "eqn, neqn, checkeq \-" "typeset mathematics" "" eqn(1)
+-.xx "" "troff, nroff \- text formatting and" "typesetting" "" troff(1)
+-.xx "" "getty \- set" "typewriter mode" "" getty(8)
+-.xx "" "getpw \- get name from" "UID" "" getpw(3)
+-.xx "" "" "umask \- set file creation mode mask" "" umask(2)
+-.xx "" "read, readonly, set, shift, times, trap," "umask, wait \- command language" "/newgrp," sh(1)
+-.xx "" "mount," "umount \- mount and dismount file system" "" mount(1)
+-.xx "" "mount," "umount \- mount or remove file system" "" mount(2)
+-.xx "stream" "" "ungetc \- push character back into input" "" ungetc(3)
+-.xx "" "" "uniq \- report repeated lines in a file" "" uniq(1)
+-.xx "" "mktemp \- make a" "unique file name" "" mktemp(3)
+-.xx "" "" "units \- conversion program" "" units(1)
+-.xx "" "cu \- call" "UNIX" "" cu(1)
+-.xx "" "uux \- unix to" "unix command execution" "" uux(1)
+-.xx "" "uucp, uulog \- unix to" "unix copy" "" uucp(1)
+-.xx "" "uux \-" "unix to unix command execution" "" uux(1)
+-.xx "" "uucp, uulog \-" "unix to unix copy" "" uucp(1)
+-.xx "" "" "unlink \- remove directory entry" "" unlink(2)
+-.xx "" "rm, rmdir \- remove (" "unlink) files" "" rm(1)
+-.xx "" "" "update \- periodically update the super block" "" update(8)
+-.xx "" "touch \-" "update date last modified of a file" "" touch(1)
+-.xx "" "sync \-" "update super-block" "" sync(2)
+-.xx "" "sync \-" "update the super block" "" sync(1)
+-.xx "" "update \- periodically" "update the super block" "" update(8)
+-.xx "" "du \- summarize disk" "usage" "" du(1)
+-.xx "" "write \- write to another" "user" "" write(1)
+-.xx "" "setuid, setgid \- set" "user and group ID" "" setuid(2)
+-.xx "" "getuid, getgid, geteuid, getegid \- get" "user and group identity" "" getuid(2)
+-.xx "" "environ \-" "user environment" "" environ(5)
+-.xx "" "su \- substitute" "user id temporarily" "" su(1)
+-.xx "" "mail \- send or receive mail among" "users" "" mail(1)
+-.xx "" "wall \- write to all" "users" "" wall(1)
+-.xx "" "" "utime \- set file times" "" utime(2)
+-.xx "" "" "utmp, wtmp \- login records" "" utmp(5)
+-.xx "" "" "uucp, uulog \- unix to unix copy" "" uucp(1)
+-.xx "" "" "uux \- unix to unix command execution" "" uux(1)
+-.xx "" "abs \- integer absolute" "value" "" abs(3)
+-.xx "" "fabs, floor, ceil \- absolute" "value, floor, ceiling functions" "" floor(3)
+-.xx "" "getenv \-" "value for environment name" "" getenv(3)
+-.xx "" "true, false \- provide truth" "values" "" true(1)
+-.xx "" "assert \- program" "verification" "" assert(3)
+-.xx "" "lint \- a C program" "verifier" "" lint(1)
+-.xx "" "vp \-" "Versatec printer-plotter" "" vp(4)
+-.xx "" "filsys, flblk, ino \- format of file system" "volume" "" filsys(5)
+-.xx "" "" "vp \- Versatec printer-plotter" "" vp(4)
+-.xx "" "" "wait \- await completion of process" "" wait(1)
+-.xx "" "readonly, set, shift, times, trap, umask," "wait \- command language" "/newgrp, read," sh(1)
+-.xx "" "" "wait \- wait for process to terminate" "" wait(2)
+-.xx "" "" "wall \- write to all users" "" wall(1)
+-.xx "" "" "wc \- word count" "" wc(1)
+-.xx "" "crash \-" "what to do when the system crashes" "" crash(8)
+-.xx "export, login, newgrp,/" "sh, for, case, if," "while, break, continue, cd, eval, exec, exit," "" sh(1)
+-.xx "" "" "who \- who is on the system" "" who(1)
+-.xx "" "wc \-" "word count" "" wc(1)
+-.xx "" "getchar, fgetc, getw \- get character or" "word from stream" "getc," getc(3)
+-.xx "" "hangman, words \-" "word games" "" words(6)
+-.xx "" "putchar, fputc, putw \- put character or" "word on a stream" "putc," putc(3)
+-.xx "" "hangman," "words \- word games" "" words(6)
+-.xx "" "cd \- change" "working directory" "" cd(1)
+-.xx "" "pwd \-" "working directory name" "" pwd(1)
+-.xx "" "" "write \- write on a file" "" write(2)
+-.xx "" "" "write \- write to another user" "" write(1)
+-.xx "" "write \-" "write on a file" "" write(2)
+-.xx "" "lseek, tell \- move read/" "write pointer" "" lseek(2)
+-.xx "" "wall \-" "write to all users" "" wall(1)
+-.xx "" "write \-" "write to another user" "" write(1)
+-.xx "" "open \- open for reading or" "writing" "" open(2)
+-.xx "" "utmp," "wtmp \- login records" "" utmp(5)
+-.xx "" "" "wump \- the game of hunt-the-wumpus" "" wump(6)
+-.xx "" "xsend," "xget, enroll \- secret mail" "" xsend(1)
+-.xx "" "j0, j1, jn," "y0, y1, yn \- bessel functions" "" j0(3)
+-.xx "" "" "yacc \- yet another compiler-compiler" "" yacc(1)
+//GO.SYSIN DD permindex
+echo pref
+sed 's/.//' >pref <<'//GO.SYSIN DD pref'
+-.TL
+-PREFACE
+-.LP
+-Although this Seventh Edition no longer bears their byline,
+-Ken Thompson and Dennis Ritchie remain the fathers
+-and preceptors of the
+-.UX
+-time-sharing system.
+-Many of the improvements here described bear their mark.
+-Among many, many other people who have contributed to
+-the further flowering of
+-\s-2UNIX\s0,
+-we wish especially to
+-acknowledge the contributions of
+-A. V. Aho,
+-S. R. Bourne,
+-L. L. Cherry,
+-G. L. Chesson,
+-S. I. Feldman,
+-C. B. Haley,
+-R. C. Haight,
+-S. C. Johnson,
+-M. E. Lesk,
+-T. L. Lyon,
+-L. E. McMahon,
+-R. Morris,
+-R. Muha,
+-D. A. Nowitz,
+-L. Wehr,
+-and
+-P. J. Weinberger.
+-We appreciate also 
+-the effective advice and criticism of
+-T. A. Dolotta,
+-A. G. Fraser,
+-J. F. Maranzano,
+-and
+-J. R. Mashey;
+-and we remember the important work of
+-the late Joseph F. Ossanna.
+-.sp 2
+-.in 4i
+-B. W. Kernighan
+-.br
+-M. D. McIlroy
+-.in 0
+//GO.SYSIN DD pref
+echo ptxmac
+sed 's/.//' >ptxmac <<'//GO.SYSIN DD ptxmac'
+-.de xx
+-.if !""\\$1" \\$1\fI\a\fR\\$2\t\\$3\fI\a\fR\t\\$5
+-.if !""\\$4" \t\\$2\t\\$3\fI\a\fR\\$4\t\\$5
+-.if ""\\$1\\$4" \t\\$2\t\\$3\fI\a\fR\t\\$5
+-..
+-.cs I 30
+-.TL
+-PERMUTED INDEX
+-.LP
+-.SM
+-.nr VS 9
+-.vs \n(VSp
+-.nf
+-.ta 2.7iR 2.85iL 5.65iR 6.5iR
+-.af PN i
+-.pn 9
+//GO.SYSIN DD ptxmac
+echo title
+sed 's/.//' >title <<'//GO.SYSIN DD title'
+-.de pg
+-.ps8
+---
+-.ps16
+-.fp 3 G
+-.sp 3.0i
+-.ti .25i
+-UNIX\s-4\fG\v'-6p'TM\v'6p'\fP\s0 TIME-SHARING SYSTEM:
+-.sp |4.0i
+-.ps 18
+-.ce
+-UNIX PROGRAMMER'S MANUAL
+-.ps12
+-.sp |4.5i
+-.ft I
+-.ce
+-Seventh Edition, Volume \\$1
+-.sp |5.0i
+-.ce
+-January, 1979
+-.ps 10
+-.sp |9.5i-1
+-.ft R
+-.ce
+-Bell Telephone Laboratories, Incorporated
+-.ce
+-Murray Hill, New Jersey
+-..
+-.pg 1
+-.bp
+-.pg 2A
+-.bp
+-.pg 2B
+//GO.SYSIN DD title
+echo xx
+sed 's/.//' >xx <<'//GO.SYSIN DD xx'
+-.TH NAME SECTION local
+-.SH NAME
+-.SH SYNOPSIS
+-.SH DESCRIPTION
+-.SH FILES
+-.SH SEE ALSO
+-.SH DIAGNOSTICS
+-.SH BUGS
+//GO.SYSIN DD xx
diff --git a/doc/7thEdMan/vol1/man1.bun b/doc/7thEdMan/vol1/man1.bun
new file mode 100644 (file)
index 0000000..8f59228
--- /dev/null
@@ -0,0 +1,14797 @@
+# To unbundle, run this file
+echo ac.1m
+sed 's/.//' >ac.1m <<'//GO.SYSIN DD ac.1m'
+-.TH AC 1M 
+-.SH NAME
+-ac \- login accounting
+-.SH SYNOPSIS
+-.B ac
+-[
+-.B \-w
+-wtmp ] [
+-.B \-p
+-] [
+-.B \-d
+-] [ people ] ...
+-.SH DESCRIPTION
+-.I Ac
+-produces a printout giving
+-connect time
+-for each user who has logged in
+-during the life of the current
+-.I wtmp
+-file.
+-A total is also produced.
+-.B \-w
+-is used to specify an alternate
+-.IR wtmp ""
+-file.
+-.B \-p
+-prints individual totals; without this option,
+-only totals are printed.
+-.B \-d
+-causes a printout for each midnight to midnight
+-period.
+-Any
+-.I people
+-will limit the
+-printout to only the specified login names.
+-If no
+-.IR wtmp ""
+-file is given,
+-.I /usr/adm/wtmp
+-is used.
+-.PP
+-The accounting file
+-.I /usr/adm/wtmp
+-is maintained by
+-.I init
+-and
+-.I login.
+-Neither of these programs creates the file,
+-so if it does not exist
+-no connect-time accounting is done.
+-To start accounting, it should be created with length 0.
+-On the other hand if the file is left undisturbed it will
+-grow without bound, so periodically any information
+-desired should be collected and the file truncated.
+-.SH FILES
+-/usr/adm/wtmp
+-.SH "SEE ALSO"
+-init(8), login(1), utmp(5).
+//GO.SYSIN DD ac.1m
+echo adb.1
+sed 's/.//' >adb.1 <<'//GO.SYSIN DD adb.1'
+-.ds TW \v'.25m'\s+2~\s-2\v'-.25m'
+-.ds ST \v'.25m'*\v'-.25m'
+-.ds IM \v'.1m'=\v'-.1m'\s-2\h'-.1m'>\h'.1m'\s+2
+-.ds LE \(<=
+-.ds LT \s-2<\s+2
+-.ds GT \s-2>\s+2
+-.TH ADB 1 
+-.SH NAME
+-adb \- debugger
+-.SH SYNOPSIS
+-.B adb
+-[\fB\-w\fR] [ objfil [ corfil ] ]
+-.SH DESCRIPTION
+-.I Adb
+-is a general purpose debugging program.
+-It may be used to examine files and to provide
+-a controlled environment for the execution
+-of UNIX programs.
+-.PP
+-.I Objfil
+-is normally an executable program file, preferably
+-containing a symbol table;
+-if not then the
+-symbolic features of
+-.I  adb
+-cannot be used although the file can still
+-be examined.
+-The default for
+-.I objfil
+-is
+-.B  a.out.
+-.I Corfil
+-is assumed to be a core image file produced after
+-executing
+-.IR objfil ;
+-the default for
+-.I corfil
+-is
+-.B  core.
+-.PP
+-Requests to
+-.I  adb
+-are read from the standard input and
+-responses are to the standard output.
+-If the
+-.B  \-w
+-flag is present then both
+-.I  objfil
+-and
+-.I corfil
+-are
+-created if necessary and
+-opened for reading and writing
+-so that files can be modified using
+-.IR adb .
+-.I Adb
+-ignores QUIT; INTERRUPT
+-causes return to the next
+-.I adb
+-command.
+-.PP
+-In general requests to
+-.I  adb
+-are of the form
+-.PP
+-.if n .ti 16
+-.if t .ti 1.6i
+-[\|\fIaddress\fR\|]  [\|,
+-.IR count \|]
+-[\|\fIcommand\fR\|] [\|;\|]
+-.PP
+-If
+-.I address
+-is present then
+-.I  dot
+-is set to
+-.IR address .
+-Initially
+-.I dot
+-is set to 0.
+-For most commands
+-.I count
+-specifies how many times
+-the command will be executed.
+-The default
+-.I count
+-is 1.
+-.I Address
+-and
+-.I count
+-are expressions.
+-.PP
+-The interpretation of an address depends
+-on the context it is used in.
+-If a subprocess is being debugged then
+-addresses are interpreted
+-in the usual way in the address space of the subprocess.
+-For further details of address mapping see
+-.SM ADDRESSES.
+-.SH EXPRESSIONS
+-.TP 7.2n
+-.B .
+-The value of
+-.IR dot .
+-.TP 7.2n
+-+
+-The value of
+-.I dot
+-incremented by the current increment.
+-.TP 7.2n
+-^
+-The value of
+-.I dot
+-decremented by the current increment.
+-.TP 7.2n
+-"
+-The last
+-.I address
+-typed.
+-.TP 7.2n
+-.I integer
+-An octal number if
+-.I integer
+-begins with a 0;
+-a hexadecimal number if preceded by
+-.BR # ;
+-otherwise a decimal number.
+-.TP 7.2n
+-.IB integer . fraction
+-A 32 bit floating point number.
+-.TP 7.2n
+-.I \'cccc\|\'
+-The ASCII value of up to 4 characters.
+-\\ may be used to escape a \'.
+-.TP 7.2n
+-.I \*(LT name
+-The value of
+-.IR name ,
+-which is either a variable name or a register name.
+-.I Adb
+-maintains a number of variables
+-(see
+-.SM VARIABLES\*S)
+-named by single letters or digits.
+-If
+-.I name
+-is a register name then
+-the value of the register is obtained from
+-the system header in
+-.IR corfil .
+-The register names are
+-.BR "r0 ... r5 sp pc ps" "."
+-.TP 7.2n
+-.I symbol
+-A
+-.I symbol
+-is a sequence
+-of upper or lower case letters, underscores or
+-digits, not starting with a digit.
+-.BR \\ " may be used to escape other characters."
+-The value of the
+-.I symbol
+-is taken from the symbol table
+-in
+-.IR objfil .
+-An initial \_ or \*(TW will be prepended to
+-.I symbol
+-if needed.
+-.TP
+-.I _ symbol
+-In C, the `true name' of an external symbol begins with _.
+-It may be necessary to utter this name to disinguish it
+-from internal or hidden variables of a program.
+-.TP 7.2n
+-.IB routine . name
+-The address of the variable
+-.I name
+-in the specified
+-C routine.
+-Both
+-.I routine
+-and
+-.I name
+-are
+-.IR symbols .
+-If
+-.I name
+-is omitted the value is the address of the
+-most recently activated C stack frame
+-corresponding to
+-.IR routine .
+-.TP 7.2n
+-.RI ( exp \|)
+-The value of the expression
+-.IR exp .
+-.LP
+-.SM
+-.B  "Monadic\ operators"
+-.TP 7.2n
+-.RI \*(ST exp
+-The contents of the location addressed
+-by
+-.I exp
+-in
+-.IR corfil .
+-.TP 7.2n
+-.RI @ exp
+-The contents of the location addressed by
+-.I exp
+-in
+-.IR objfil .
+-.TP 7.2n
+-.RI \- exp
+-Integer negation.
+-.TP 7.2n
+-.RI \*(TW exp
+-Bitwise complement.
+-.LP
+-.B  "Dyadic\ operators"
+-are left associative
+-and are less binding than monadic operators.
+-.TP 7.2n
+-.IR e1 + e2
+-Integer addition.
+-.TP 7.2n
+-.IR e1 \- e2
+-Integer subtraction.
+-.TP 7.2n
+-.IR e1 \*(ST e2
+-Integer multiplication.
+-.TP 7.2n
+-.IR e1 % e2
+-Integer division.
+-.TP 7.2n
+-.IR e1 & e2
+-Bitwise conjunction.
+-.TP 7.2n
+-.IR e1 \(bv e2
+-Bitwise disjunction.
+-.TP 7.2n
+-.IR e1 # e2
+-.I E1
+-rounded up to the next multiple of
+-.IR e2 .
+-.DT
+-.SH COMMANDS
+-Most commands consist of a verb followed by a modifier or list
+-of modifiers.
+-The following verbs are available.
+-(The commands `?' and `/' may be followed by `\*(ST';
+-see
+-.SM ADDRESSES
+-for further details.)
+-.TP .5i
+-.RI ? f
+-Locations starting at
+-.I address
+-in
+-.I  objfil
+-are printed according to the format
+-.IR f .
+-.TP
+-.RI / f
+-Locations starting at
+-.I address
+-in
+-.I  corfil
+-are printed according to the format
+-.IR f .
+-.TP
+-.RI  = f
+-The value of
+-.I address
+-itself is printed in the
+-styles indicated by the format
+-.IR f .
+-(For
+-.B i 
+-format `?' is printed for the parts of the instruction that reference
+-subsequent words.)
+-.PP
+-A
+-.I format
+-consists of one or more characters that specify a style
+-of printing.
+-Each format character may be preceded by a decimal integer
+-that is a repeat count for the format character.
+-While stepping through a format
+-.I dot
+-is incremented temporarily
+-by the amount given for each format letter.
+-If no format is given then the last format is used.
+-The format letters available are as follows.
+-.ta 2.5n .5i
+-.RS
+-.TP
+-.BR o "       2"
+-Print 2 bytes in octal.
+-All octal numbers output by
+-.I adb
+-are preceded by 0.
+-.br
+-.ns
+-.TP
+-.BR O "       4"
+-Print 4 bytes in octal.
+-.br
+-.ns
+-.TP
+-.BR q "       2"
+-Print in signed octal.
+-.br
+-.ns
+-.TP
+-.BR Q "       4"
+-Print long signed octal.
+-.br
+-.ns
+-.TP
+-.BR d "       2"
+-Print in decimal.
+-.br
+-.ns
+-.TP
+-.BR D "       4"
+-Print long decimal.
+-.br
+-.ns
+-.TP
+-.BR x "       2"
+-Print 2 bytes in hexadecimal.
+-.br
+-.ns
+-.TP
+-.BR X "       4"
+-Print 4 bytes in hexadecimal.
+-.br
+-.ns
+-.TP
+-.BR u "       2"
+-Print as an unsigned decimal number.
+-.br
+-.ns
+-.TP
+-.BR U "       4"
+-Print long unsigned decimal.
+-.br
+-.ns
+-.TP
+-.BR f "       4"
+-Print the 32 bit value
+-as a floating point number.
+-.br
+-.ns
+-.TP
+-.BR F "       8"
+-Print double floating point.
+-.br
+-.ns
+-.TP
+-.BR b "       1"
+-Print the addressed byte in octal.
+-.br
+-.ns
+-.TP
+-.BR c "       1"
+-Print the addressed character.
+-.br
+-.ns
+-.TP
+-.BR C "       1"
+-Print the addressed character using
+-the following escape convention.
+-Character values 000 to 040 are printed as @ followed by the corresponding
+-character in the range 0100 to 0140.
+-The character @ is printed as @@.
+-.br
+-.ns
+-.TP
+-.BI s "       n"
+-Print the addressed characters until a zero character
+-is reached.
+-.br
+-.ns
+-.TP
+-.BI S "       n"
+-Print a string using 
+-the @ escape convention.
+-.I n
+-is the length of the string including its zero terminator.
+-.br
+-.ns
+-.TP
+-.BR Y "       4"
+-Print 4 bytes in date format (see
+-.IR ctime (3)).
+-.br
+-.ns
+-.TP
+-.BR i "       n"
+-Print as PDP11 instructions.
+-.I n
+-is the number of bytes occupied by the instruction.
+-This style of printing causes variables 1 and 2 to be set
+-to the offset parts of the source and destination respectively.
+-.br
+-.ns
+-.TP
+-.BR a "       0"
+-Print the value of
+-.I dot
+-in symbolic form.
+-Symbols are checked to ensure that they have an appropriate
+-type as indicated below.
+-.LP
+-      /       local or global data symbol
+-.br
+-      ?       local or global text symbol
+-.br
+-      =       local or global absolute symbol
+-.TP
+-.BR p "       2"
+-Print the addressed value in symbolic form using
+-the same rules for symbol lookup as
+-.BR a .
+-.br
+-.ns
+-.TP
+-.BR t "       0"
+-When preceded by an integer tabs to the next
+-appropriate tab stop.
+-For example,
+-.B 8t 
+-moves to the next 8-space tab stop.
+-.br
+-.ns
+-.TP
+-.BR r "       0"
+-Print a space.
+-.br
+-.ns
+-.TP
+-.BR n "       0"
+-Print a newline.
+-.br
+-.ns
+-.tr '"
+-.TP
+-.BR '...' " 0"
+-Print the enclosed string.
+-.br
+-.tr ''
+-.br
+-.ns
+-.TP
+-.B ^
+-.I Dot
+-is decremented by the current increment.
+-Nothing is printed.
+-.br
+-.ns
+-.TP
+-+
+-.I Dot
+-is incremented by 1.
+-Nothing is printed.
+-.br
+-.ns
+-.TP
+-\-
+-.I Dot
+-is decremented by 1.
+-Nothing is printed.
+-.RE
+-.TP
+-newline
+-If the previous command temporarily incremented
+-.IR dot ,
+-make the increment permanent.
+-Repeat the previous command with a
+-.I count
+-of 1.
+-.TP
+-.RB [ ?/ ] l "\fI value mask\fR"
+-Words starting at
+-.I  dot
+-are masked with
+-.I mask
+-and compared with
+-.I value
+-until
+-a match is found.
+-If
+-.B L
+-is used then the match is for 4 bytes at a time instead of 2.
+-If no match is found then
+-.I dot
+-is unchanged; otherwise
+-.I dot
+-is set to the matched location.
+-If
+-.I mask
+-is omitted then \-1 is used.
+-.TP
+-.RB [ ?/ ] w "\fI value ...\fR"
+-Write the 2-byte
+-.I value
+-into the addressed
+-location.
+-If the command is
+-.BR W ,
+-write 4 bytes.
+-Odd addresses are not allowed when writing to the subprocess
+-address space.
+-.TP
+-[\fB?/\fR]\fBm\fI b1 e1 f1\fR[\fB?/\fR]
+-.br
+-New values for
+-.RI ( b1,\ e1,\ f1 )
+-are recorded.
+-If less than three expressions are given then
+-the remaining map parameters are left unchanged.
+-If the `?' or `/' is followed by `\*(ST' then
+-the second segment (\fIb2\fR\|,\|\fIe2\fR\|,\|\fIf2\fR)
+-of the mapping is changed.
+-If the list is terminated by `?' or `/' then the file
+-(\fIobjfil\fR or
+-.I corfil
+-respectively) is used
+-for subsequent requests.
+-(So that, for example, `/m?' will cause `/' to refer to
+-.IR objfil .)
+-.TP
+-.BI \*(GT name
+-.I Dot
+-is assigned to the variable or register named.
+-.TP
+-.B !
+-A shell is called to read the
+-rest of the line following `!'.
+-.TP
+-.RI $ modifier
+-Miscellaneous commands.
+-The available 
+-.I modifiers 
+-are:
+-.RS
+-.TP
+-.BI < f
+-Read commands from the file
+-.I f
+-and return.
+-.br
+-.ns
+-.TP
+-.BI > f
+-Send output to the file
+-.I  f,
+-which is created if it does not exist.
+-.br
+-.ns
+-.TP
+-.B r
+-Print the general registers and
+-the instruction addressed by
+-.BR pc .
+-.I Dot
+-is set to \fBpc\fR.
+-.br
+-.ns
+-.TP
+-.B f
+-Print the floating registers in
+-single or double length.
+-If the floating point status of
+-.B ps
+-is set to double (0200 bit)
+-then double length is used anyway.
+-.br
+-.ns
+-.TP
+-.B b
+-Print all breakpoints
+-and their associated counts and commands.
+-.br
+-.ns
+-.TP
+-.B a
+-ALGOL 68 stack backtrace.
+-If
+-.I address
+-is given then it is taken to be the
+-address of the current frame (instead of
+-.BR r4 ).
+-If
+-.I count
+-is given then only the first
+-.I count
+-frames are printed.
+-.br
+-.ns
+-.TP
+-.B c
+-C stack backtrace.
+-If
+-.I address
+-is given then it is taken as the
+-address of the current frame (instead of
+-.BR r5 ).
+-If
+-.B C 
+-is used then the names and (16 bit) values of all automatic
+-and static variables are printed for each active function.
+-If
+-.I count
+-is given then only the first
+-.I count
+-frames are printed.
+-.br
+-.ns
+-.TP
+-.B e
+-The names and values of
+-external variables are printed.
+-.br
+-.ns
+-.TP
+-.B w
+-Set the page width for output to
+-.I address
+-(default 80).
+-.br
+-.ns
+-.TP
+-.B s
+-Set the limit for symbol matches to
+-.I address
+-(default 255).
+-.br
+-.ns
+-.TP
+-.B o
+-All integers input are regarded as octal.
+-.br
+-.ns
+-.TP
+-.B d
+-Reset integer input as described in
+-.SM EXPRESSIONS.
+-.br
+-.ns
+-.TP
+-.B q
+-Exit from
+-.IR adb .
+-.br
+-.ns
+-.TP
+-.B v
+-Print all non zero variables in octal.
+-.br
+-.ns
+-.TP
+-.B m
+-Print the address map.
+-.RE
+-.TP
+-.BI : modifier
+-Manage a subprocess.
+-Available modifiers are:
+-.RS
+-.TP
+-.BI b c
+-Set breakpoint at
+-.IR address .
+-The breakpoint is executed
+-.IR count \-1
+-times before
+-causing a stop.
+-Each time the breakpoint is encountered
+-the command
+-.I c
+-is executed.
+-If this command sets
+-.I dot
+-to zero
+-then the breakpoint causes a stop.
+-.TP
+-.B d
+-Delete breakpoint at
+-.IR address .
+-.TP
+-.B r
+-Run
+-.I objfil
+-as a subprocess.
+-If
+-.I address
+-is given explicitly then the
+-program is entered at this point; otherwise
+-the program is entered at its standard entry point.
+-.I count
+-specifies how many breakpoints are to be
+-ignored before stopping.
+-Arguments to the subprocess may be supplied on the
+-same line as the command.
+-An argument starting with < or > causes the standard
+-input or output to be established for the command.
+-All signals are turned on on entry to the subprocess.
+-.TP
+-.BI c s
+-The subprocess is continued
+-with signal
+-.I s
+-c
+-.I s,
+-see
+-.IR signal (2).
+-If
+-.I address
+-is given then the subprocess
+-is continued at this address.
+-If no signal is specified then the signal
+-that caused the subprocess to stop is sent.
+-Breakpoint skipping is the same
+-as for
+-.BR r .
+-.TP
+-.BI s s
+-As for
+-.B c 
+-except that
+-the subprocess is single stepped
+-.I count
+-times.
+-If there is no current subprocess then
+-.I objfil
+-is run
+-as a subprocess as for
+-.BR r .
+-In this case no signal can be sent; the remainder of the line
+-is treated as arguments to the subprocess.
+-.TP
+-.B k
+-The current subprocess, if any, is terminated.
+-.RE
+-.SH VARIABLES
+-.I Adb
+-provides a number of variables.
+-Named variables are set initially by
+-.I  adb
+-but are not used subsequently.
+-Numbered variables are reserved for communication
+-as follows.
+-.TP
+-0
+-The last value printed.
+-.br
+-.ns
+-.TP
+-1
+-The last offset part of an instruction source.
+-.br
+-.ns
+-.TP
+-2
+-The previous value of variable 1.
+-.PP
+-On entry the following are set
+-from the system header in the
+-.IR corfil .
+-If
+-.I corfil
+-does not appear to be a
+-.B core 
+-file then
+-these values are set from
+-.IR objfil .
+-.TP
+-b
+-The base address of the data segment.
+-.br
+-.ns
+-.TP
+-d
+-The data segment size.
+-.br
+-.ns
+-.TP
+-e
+-The entry point.
+-.br
+-.ns
+-.TP
+-m
+-The `magic' number (0405, 0407, 0410 or 0411).
+-.br
+-.ns
+-.TP
+-s
+-The stack segment size.
+-.br
+-.ns
+-.TP
+-t
+-The text segment size.
+-.SH ADDRESSES
+-The address in a file associated with
+-a written address is determined by a mapping
+-associated with that file.
+-Each mapping is represented by two triples
+-.RI ( "b1, e1, f1" )
+-and
+-.RI ( "b2, e2, f2" )
+-and the
+-.I file address
+-corresponding to a written
+-.I address
+-is calculated as follows.
+-.PP
+-.if t .ti 1.5i
+-.if n .ti 8
+-.IR b1 \*(LE address < e1
+-\*(IM
+-.IR "file address" = address + f1\-b1,
+-otherwise,
+-.PP
+-.if t .ti 1.5i
+-.if n .ti 8
+-.IR b2 \*(LE address < e2
+-\*(IM
+-.IR "file address" = address + f2\-b2,
+-.PP
+-otherwise, the requested
+-.I address
+-is not legal.
+-In some cases (e.g. for programs with separated I and D
+-space) the two segments for a file may overlap.
+-If a
+-.B ? 
+-or
+-.B / 
+-is followed by an
+-.B \*(ST 
+-then only the second
+-triple is used.
+-.PP
+-The initial setting of both mappings is suitable for
+-normal
+-.B a.out 
+-and
+-.B core 
+-files.
+-If either file is not of the kind expected then, for that file,
+-.I b1
+-is set to 0,
+-.I e1
+-is set to
+-the maximum file size
+-and
+-.I f1
+-is set to 0; in this way the whole
+-file can be examined with no address translation.
+-.PP
+-So that
+-.I adb
+-may be used on large files
+-all appropriate values are kept as signed 32 bit integers.
+-.SH FILES
+-/dev/mem
+-.br
+-/dev/swap
+-.br
+-a.out
+-.br
+-core
+-.SH SEE\ ALSO
+-ptrace(2),
+-a.out(5),
+-core(5)
+-.SH DIAGNOSTICS
+-`Adb' when there is no current command or format.
+-Comments about inaccessible files, syntax errors,
+-abnormal termination of commands, etc.
+-Exit status is 0, unless last command failed or
+-returned nonzero status.
+-.SH BUGS
+-A breakpoint set at the entry point is not effective
+-on initial entry to the program.
+-.br
+-When single stepping, system calls do not count as an
+-executed instruction.
+-.br
+-Local variables whose names are the same as an external
+-variable may foul up the accessing of the external.
+//GO.SYSIN DD adb.1
+echo ar.1
+sed 's/.//' >ar.1 <<'//GO.SYSIN DD ar.1'
+-.TH AR 1 
+-.SH NAME
+-ar \- archive and library maintainer
+-.SH SYNOPSIS
+-.B ar
+-key [ posname ] afile name ...
+-.SH DESCRIPTION
+-.I Ar
+-maintains groups of files
+-combined into a single archive file.
+-Its main use
+-is to create and update library files as used by the loader.
+-It can be used, though, for any similar purpose.
+-.PP
+-.I Key
+-is one character from the set
+-.B drqtpmx,
+-optionally concatenated with
+-one or more of
+-.B vuaibcl.
+-.I Afile
+-is the archive file.
+-The
+-.I names
+-are constituent files in the archive file.
+-The meanings of the
+-.I key
+-characters are:
+-.TP
+-.B d
+-Delete the named files from the archive file.
+-.TP
+-.B r
+-Replace the named files in the archive file.
+-If the optional character
+-.B u
+-is used with
+-.B r,
+-then only those files with
+-modified dates later than
+-the archive files are replaced.
+-If an optional positioning character from the set
+-.B abi
+-is used, then the
+-.I posname
+-argument must be present
+-and specifies that new files are to be placed
+-after
+-.RB ( a )
+-or before
+-.RB ( b
+-or
+-.BR i )
+-.IR posname .
+-Otherwise
+-new files are placed at the end.
+-.TP
+-.B q
+-Quickly append the named files to the end of the archive file.
+-Optional positioning characters are invalid.
+-The command does not check whether the added members
+-are already in the archive.
+-Useful only to avoid quadratic behavior when creating a large
+-archive piece-by-piece.
+-.TP
+-.B t
+-Print a table of contents of the archive file.
+-If no names are given, all files in the archive are tabled.
+-If names are given, only those files are tabled.
+-.TP
+-.B p
+-Print the named files in the archive.
+-.TP
+-.B m
+-Move the named files to the end of the archive.
+-If a positioning character is present,
+-then the
+-.I posname
+-argument must be present and,
+-as in
+-.B r,
+-specifies where the files are to be moved.
+-.TP
+-.B x
+-Extract the named files.
+-If no names are given, all files in the archive are
+-extracted.
+-In neither case does
+-.B x
+-alter the archive file.
+-.TP
+-.B v
+-Verbose.
+-Under the verbose option,
+-.I ar
+-gives a file-by-file
+-description of the making of a
+-new archive file from the old archive and the constituent files.
+-When used with
+-.B t,
+-it gives a long listing of all information about the files.
+-When used with
+-.BR p ,
+-it precedes each file with a name.
+-.TP
+-.B c
+-Create.
+-Normally
+-.I ar
+-will create
+-.I afile
+-when it needs to.
+-The create option suppresses the
+-normal message that is produced when
+-.I afile
+-is created.
+-.TP
+-.B l
+-Local.
+-Normally
+-.I ar
+-places its temporary files in the directory /tmp.
+-This option causes them to be placed in the local directory.
+-.SH FILES
+-/tmp/v*       temporaries
+-.SH "SEE ALSO"
+-ld(1), ar(5),
+-lorder(1)
+-.SH BUGS
+-If the same file is mentioned twice in an argument list,
+-it may be put in the archive twice.
+//GO.SYSIN DD ar.1
+echo arcv.1m
+sed 's/.//' >arcv.1m <<'//GO.SYSIN DD arcv.1m'
+-.TH ARCV 1M
+-.SH NAME
+-arcv \- convert archives to new format
+-.SH SYNOPSIS
+-.B arcv
+-file ...
+-.SH DESCRIPTION
+-.I Arcv
+-converts archive files
+-(see
+-.IR ar (1),
+-.IR ar (5))
+-from 6th edition to 7th edition format.
+-The conversion is done in place, and the command
+-refuses to alter a file not in old archive format.
+-.PP
+-Old archives are marked with a magic number of 0177555 at the start;
+-new archives have 0177545.
+-.SH FILES
+-/tmp/v*, temporary copy
+-.SH SEE ALSO
+-ar(1), ar(5)
+//GO.SYSIN DD arcv.1m
+echo as.1
+sed 's/.//' >as.1 <<'//GO.SYSIN DD as.1'
+-.TH AS 1  PDP11
+-.SH NAME
+-as \- assembler
+-.SH SYNOPSIS
+-.B as
+-[
+-.B \-
+-] [
+-.B \-o
+-objfile
+-] file ...
+-.SH DESCRIPTION
+-.I As
+-assembles the concatenation of the named files.
+-If the optional first argument
+-.B \-
+-is used,
+-all undefined symbols in the assembly
+-are treated as global.
+-.PP
+-The output of the assembly is left on the file
+-.I objfile;
+-if that is omitted,
+-.B a.out
+-is used.
+-It is executable if no errors occurred
+-during the assembly,
+-and if there were no unresolved external references.
+-.SH FILES
+-/lib/as2      pass 2 of the assembler
+-.br
+-/tmp/atm[1-3]?        temporary
+-.br
+-a.out         object
+-.SH "SEE ALSO"
+-ld(1),
+-nm(1),
+-adb(1),
+-a.out(5)
+-.br
+-.I "UNIX Assembler Manual"
+-by D. M. Ritchie
+-.SH DIAGNOSTICS
+-When
+-an input file cannot be read, its name
+-followed by a question mark is typed and assembly
+-ceases.
+-When syntactic or semantic errors occur, a single-character diagnostic is typed out
+-together with the line number and the file name in which it
+-occurred.
+-Errors in pass 1 cause cancellation of pass 2.
+-The possible errors are:
+-.PP
+-.ta 3
+-)     Parentheses error
+-.br
+-]     Parentheses error
+-.br
+-<     String not terminated properly
+-.br
+-*     Indirection used illegally
+-.br
+-.li
+-\fB.\fR       Illegal assignment to `\fB.\fR'
+-.br
+-a     Error in address
+-.br
+-b     Branch instruction is odd or too remote
+-.br
+-e     Error in expression
+-.br
+-f     Error in local (`f' or `b') type symbol
+-.br
+-g     Garbage (unknown) character
+-.br
+-i     End of file inside an if
+-.br
+-m     Multiply defined symbol as label
+-.br
+-o     Word quantity assembled at odd address
+-.br
+-p     `\fB.\fR' different in pass 1 and 2
+-.br
+-r     Relocation error
+-.br
+-u     Undefined symbol
+-.br
+-x     Syntax error
+-.br
+-.SH BUGS
+-Syntax errors can cause incorrect line numbers
+-in following diagnostics.
+//GO.SYSIN DD as.1
+echo at.1
+sed 's/.//' >at.1 <<'//GO.SYSIN DD at.1'
+-.TH AT 1 
+-.SH NAME
+-at \- execute commands at a later time
+-.SH SYNOPSIS
+-.B at
+-time
+-[
+-day
+-]
+-[
+-file
+-]
+-.SH DESCRIPTION
+-.I At
+-squirrels away a copy of the named
+-.I file
+-(standard input default)
+-to be used as input to
+-.IR sh (1)
+-at a specified later time.
+-A
+-.IR cd (1)
+-command to the current directory is inserted
+-at the beginning,
+-followed by assignments to all environment variables.
+-When the script is run, it uses the user and group ID
+-of the creator of the copy file.
+-.PP
+-The
+-.I time
+-is 1 to 4 digits, with an optional following
+-`A', `P', `N' or `M' for
+-AM, PM, noon or midnight.
+-One and two digit numbers are taken to be hours, three and four digits
+-to be hours and minutes.
+-If no letters follow the digits, a 24 hour clock time is understood.
+-.PP
+-The optional
+-.I day
+-is either
+-(1) a month name followed by a day number,
+-or
+-(2) a day of the week; if the word `week' follows
+-invocation is moved seven days further off.
+-Names of months and days may be recognizably truncated.
+-Examples of legitimate commands are
+-.IP
+-at 8am jan 24
+-.br
+-at 1530 fr week
+-.PP
+-.I At
+-programs are executed by periodic execution
+-of the command
+-.I /usr/lib/atrun
+-from
+-.IR cron (8).
+-The granularity of
+-.I at
+-depends upon how often
+-.I atrun
+-is executed.
+-.PP
+-Standard output or error output is lost unless redirected.
+-.SH FILES
+-/usr/spool/at/yy.ddd.hhhh.uu
+-.br
+-activity to be performed at hour
+-.I hhhh
+-of year day
+-.I ddd
+-of year
+-.IR yy .
+-.I uu
+-is a unique number.
+-.br
+-/usr/spool/at/lasttimedone contains
+-.I hhhh
+-for last hour of activity.
+-.br
+-/usr/spool/at/past directory of activities now in progress
+-.br
+-/usr/lib/atrun program that executes activities that
+-are due
+-.br
+-pwd(1)
+-.SH "SEE ALSO"
+-calendar(1),
+-cron(8)
+-.SH DIAGNOSTICS
+-Complains about various syntax errors and times out of range.
+-.SH BUGS
+-Due to the granularity of the execution of
+-.I /usr/lib/atrun,
+-there may be bugs in scheduling things almost
+-exactly 24 hours into the future.
+//GO.SYSIN DD at.1
+echo awk.1
+sed 's/.//' >awk.1 <<'//GO.SYSIN DD awk.1'
+-.TH AWK 1 
+-.SH NAME
+-awk \- pattern scanning and processing language
+-.SH SYNOPSIS
+-.B awk
+-[
+-.BI \-F c
+-]
+-[ prog ] [ file ] ...
+-.SH DESCRIPTION
+-.I Awk
+-scans each input
+-.I file
+-for lines that match any of a set of patterns specified in
+-.IR prog .
+-With each pattern in
+-.I prog
+-there can be an associated action that will be performed
+-when a line of a
+-.I file
+-matches the pattern.
+-The set of patterns may appear literally as
+-.I prog,
+-or in a file
+-specified as
+-.B \-f
+-.IR file .
+-.PP
+-Files are read in order;
+-if there are no files, the standard input is read.
+-The file name `\-'
+-means the standard input.
+-Each line is matched against the
+-pattern portion of every pattern-action statement;
+-the associated action is performed for each matched pattern.
+-.PP
+-An input line is made up of fields separated by white space.
+-(This default can be changed by using FS,
+-.IR "vide infra" ".)"
+-The fields are denoted $1, $2, ... ;
+-$0 refers to the entire line.
+-.PP
+-.PP
+-A pattern-action statement has the form
+-.PP
+-      pattern { action }
+-.PP
+-A missing { action } means print the line;
+-a missing pattern always matches.
+-.PP
+-An action is a sequence of statements.
+-A statement can be one of the following:
+-.PP
+-.nf
+-      if ( conditional ) statement [ else statement ]
+-      while ( conditional ) statement
+-      for ( expression ; conditional ; expression ) statement
+-      break
+-      continue
+-      { [ statement ] ... }
+-      variable = expression
+-      print [ expression-list ] [ >expression ]
+-      printf format [ , expression-list ] [ >expression ]
+-      next    # skip remaining patterns on this input line 
+-      exit    # skip the rest of the input
+-.fi
+-.PP
+-Statements are terminated by
+-semicolons, newlines or right braces.
+-An empty expression-list stands for the whole line.
+-Expressions take on string or numeric values as appropriate,
+-and are built using the operators
+-+, \-, *, /, %,  and concatenation (indicated by a blank).
+-The C operators ++, \-\-, +=, \-=, *=, /=, and %=
+-are also available in expressions.
+-Variables may be scalars, array elements
+-(denoted
+-x[i])
+-or fields.
+-Variables are initialized to the null string.
+-Array subscripts may be any string,
+-not necessarily numeric;
+-this allows for a form of associative memory.
+-String constants are quoted "...".
+-.PP
+-The 
+-.I print
+-statement prints its arguments on the standard output
+-(or on a file if 
+-.I >file
+-is present), separated by the current output field separator,
+-and terminated by the output record separator.
+-The
+-.I printf
+-statement formats its expression list according to the format
+-(see
+-.IR printf (3)).
+-.PP
+-The built-in function
+-.I length
+-returns the length of its argument
+-taken as a string,
+-or of the whole line if no argument.
+-There are also built-in functions
+-.I exp,
+-.I log,
+-.I sqrt,
+-and
+-.IR int .
+-The last truncates its argument to an integer.
+-.IR substr(s,\ m,\ n)
+-returns the 
+-.IR n -character
+-substring of
+-.I s
+-that begins at position
+-.IR m .
+-The function
+-.IR sprintf(fmt,\ expr,\ expr,\ ...)
+-formats the expressions
+-according to the
+-.IR printf (3)
+-format given by
+-.I fmt
+-and returns the resulting string.
+-.PP
+-Patterns are arbitrary Boolean combinations
+-(!, \(or\(or, &&, and parentheses) of 
+-regular expressions and
+-relational expressions.
+-Regular expressions must be surrounded
+-by slashes and are as in
+-.IR egrep .
+-Isolated regular expressions
+-in a pattern apply to the entire line.
+-Regular expressions may also occur in
+-relational expressions.
+-.PP
+-A pattern may consist of two patterns separated by a comma;
+-in this case, the action is performed for all lines
+-between an occurrence of the first pattern
+-and the next occurrence of the second.
+-.PP
+-.nf
+-A relational expression is one of the following:
+-.PP
+-.nf
+-      expression matchop regular-expression
+-      expression relop expression
+-.PP
+-.fi
+-where a relop is any of the six relational operators in C,
+-and a matchop is either ~ (for contains)
+-or !~ (for does not contain).
+-A conditional is an arithmetic expression,
+-a relational expression,
+-or a Boolean combination
+-of these.
+-.PP
+-The special patterns
+-BEGIN
+-and
+-END
+-may be used to capture control before the first input line is read
+-and after the last.
+-BEGIN must be the first pattern, END the last.
+-.PP
+-A single character
+-.I c
+-may be used to separate the fields by starting
+-the program with
+-.PP
+-      BEGIN { FS = "c" }
+-.PP
+-or by using the
+-.BI \-F c
+-option.
+-.PP
+-Other variable names with special meanings
+-include NF, the number of fields in the current record;
+-NR, the ordinal number of the current record;
+-FILENAME, the name of the current input file;
+-OFS, the output field separator (default blank);
+-ORS, the output record separator (default newline);
+-and
+-OFMT, the output format for numbers (default "%.6g").
+-.PP
+-.SH EXAMPLES
+-.PP
+-Print lines longer than 72 characters:
+-.PP
+-.nf
+-      length > 72
+-.fi
+-.PP
+-Print first two fields in opposite order:
+-.PP
+-.nf
+-      { print $2, $1 }
+-.fi
+-.PP
+-Add up first column, print sum and average:
+-.PP
+-.nf
+-              { s += $1 }
+-      END     { print "sum is", s, " average is", s/NR }
+-.fi
+-.PP
+-Print fields in reverse order:
+-.PP
+-.nf
+-      { for (i = NF; i > 0; \-\-i) print $i }
+-.fi
+-.PP
+-Print all lines between start/stop pairs:
+-.PP
+-.nf
+-      /start/, /stop/
+-.fi
+-.PP
+-Print all lines whose first field is different from previous one:
+-.PP
+-.nf
+-      $1 != prev { print; prev = $1 }
+-.fi
+-.SH SEE ALSO
+-.PP
+-lex(1), sed(1)
+-.br
+-A. V. Aho, B. W. Kernighan, P. J. Weinberger,
+-.I
+-Awk \- a pattern scanning and processing language
+-.SH BUGS
+-There are no explicit conversions between numbers and strings.
+-To force an expression to be treated as a number add 0 to it;
+-to force it to be treated as a string concatenate ""
+-to it.
+//GO.SYSIN DD awk.1
+echo bas.1
+sed 's/.//' >bas.1 <<'//GO.SYSIN DD bas.1'
+-.TH BAS 1 
+-.SH NAME
+-bas \- basic
+-.SH SYNOPSIS
+-.B bas
+-[ file ]
+-.SH DESCRIPTION
+-.I Bas
+-is a dialect of Basic.
+-If a file argument is provided,
+-the file is used for input before the terminal
+-is read.
+-.I Bas
+-accepts lines of the form:
+-.PP
+-   statement
+-   integer statement
+-.PP
+-Integer numbered statements
+-(known as internal statements)
+-are stored for later execution.
+-They are stored in sorted ascending order.
+-Non-numbered statements are immediately executed.
+-The result of an immediate expression statement
+-(that does not have `=' as its highest operator) is printed.
+-Interrupts suspend computation.
+-.PP
+-Statements have the following syntax:
+-.HP 5
+-expression
+-.br
+-The expression is executed for its side
+-effects (assignment or function call)
+-or for printing as described above.
+-.HP 5
+-.B comment
+-.li
+-...
+-.br
+-This statement is ignored.
+-It is used to interject commentary in a program.
+-.HP 5
+-.B done
+-.br
+-Return to system level.
+-.HP 5
+-.B dump
+-.br
+-The name and current value of every
+-variable is printed.
+-.HP 5
+-.B edit
+-.br
+-The UNIX editor,
+-.I ed,
+-is invoked with the
+-.I file
+-argument.
+-After the editor exits,
+-this file is recompiled.
+-.HP 5
+-.B for
+-name
+-.B =
+-expression expression statement
+-.br
+-.br
+-.ns
+-.HP 5
+-.B for
+-name
+-.B =
+-expression expression
+-.br
+-.li
+-...
+-.br
+-.ns
+-.HP 5
+-.B next
+-.br
+-The
+-.I for
+-statement
+-repetitively executes a
+-statement (first form)
+-or a group of statements (second form)
+-under control of a named variable.
+-The variable takes on the value of
+-the first expression,
+-then is incremented by one on each loop,
+-not to exceed the value of
+-the second expression.
+-.HP 5
+-.B goto
+-expression
+-.br
+-The expression is evaluated, truncated to an integer
+-and execution goes to the corresponding integer numbered statment.
+-If executed from immediate mode,
+-the internal statements are compiled first.
+-.HP 5
+-.B if
+-expression statement
+-.br
+-.br
+-.ns
+-.HP 5
+-.B if
+-expression
+-.br
+-.li
+-...
+-.br
+-.ns
+-.HP 5
+-[
+-.B else
+-.br
+-.li
+-... ]
+-.br
+-.ns
+-.HP 5
+-.B fi
+-.br
+-The statement (first form)
+-or group of statements (second form)
+-is executed if the expression evaluates
+-to non-zero.
+-In the second form,
+-an optional
+-.B else
+-allows for a group of statements to be
+-executed when the first group is not.
+-.HP 5
+-.B list
+-[expression [expression]]
+-.br
+-.br list
+-is used to print out the stored internal statements.
+-If no arguments are given, all internal statements are printed.
+-If one argument is given, only that
+-internal statement is listed.
+-If two arguments are given, all internal statements
+-inclusively between the arguments are printed.
+-.HP 5
+-.B print
+-list
+-.br
+-The list of expressions and strings are concatenated and
+-printed.
+-(A string is delimited by " characters.)
+-.HP 5
+-.B prompt
+-list
+-.br
+-.I Prompt 
+-is the same as
+-.I print
+-except that no newline character is
+-printed.
+-.HP 5
+-.B return
+-[expression]
+-.br
+-The expression is evaluated and the result is passed
+-back as the value of a function call.
+-If no expression is given, zero is returned.
+-.HP 5
+-.B run
+-.br
+-The internal statements are compiled.
+-The symbol table is re-initialized.
+-The random number generator is reset.
+-Control is passed to the lowest numbered internal
+-statement.
+-.HP 5
+-.B save
+-[expression [expression]]
+-.br
+-.I Save
+-is like
+-.I list
+-except that the output
+-is written on the
+-.I file
+-argument.
+-If no argument is given on the command,
+-.B b.out
+-is used.
+-.PP
+-Expressions have the following syntax:
+-.HP 5
+-name
+-.br
+-A name is used to specify a variable.
+-Names are composed of a letter
+-followed by letters and digits.
+-The first four characters of a name are significant.
+-.HP 5
+-number
+-.br
+-A number is used to represent a constant value.
+-A number is written in Fortran style,
+-and contains digits, an optional decimal point,
+-and possibly a scale factor consisting
+-of an
+-.B e
+-followed by a possibly signed exponent.
+-.HP 5
+-.B (
+-expression
+-.B )
+-.br
+-Parentheses are used to alter normal order of evaluation.
+-.HP 5
+-_ expression
+-.br
+-The result is the negation of the expression.
+-.HP 5
+-expression operator expression
+-.br
+-Common functions of two arguments are abbreviated
+-by the two arguments separated by an operator denoting the function.
+-A complete list of operators is given below.
+-.HP 5
+-expression
+-.B (
+-[expression [
+-.B ,
+-expression] ... ]
+-.B )
+-.br
+-Functions of an arbitrary number of arguments
+-can be called by an expression followed by the arguments
+-in parentheses separated by commas.
+-The expression evaluates to the
+-line number of the entry of the function in the
+-internally stored statements.
+-This causes the internal statements to be compiled.
+-If the expression evaluates negative,
+-a builtin function is called.
+-The list of builtin functions appears below.
+-.HP 5
+-name
+-.B [
+-expression
+-[
+-.B ,
+-expression
+-] ...
+-.B ]
+-.br
+-Each expression is truncated to an integer
+-and used as a specifier for the name.
+-The result is syntactically identical to a name.
+-.B a[1,2]
+-is the same as
+-.B a[1][2].
+-The truncated expressions are restricted to 
+-values between 0 and 32767.
+-.PP
+-The following is the list of operators:
+-.TP
+-=
+-=
+-is the assignment operator.
+-The left operand must be a name or an array element.
+-The result is the right operand.
+-Assignment binds right to left,
+-.TP
+-&  |
+-&
+-(logical and)
+-has result zero if either of its arguments are zero.
+-It has result one if both its arguments are non-zero.
+-|
+-(logical or)
+-has result zero if both of its arguments are zero.
+-It has result one if either of its arguments are non-zero.
+-.TP
+-<  <=  >  >=  ==  <>
+-The relational operators
+-(< less than, <= less than or equal,
+-> greater than,
+->= greater than or equal,
+-== equal to,
+-<> not equal to)
+-return one if their arguments are in the specified
+-relation.
+-They return zero otherwise.
+-Relational operators at the same level extend as follows:
+-a>b>c is the same as a>b&b>c.
+-.TP
+-+ \-
+-Add and subtract.
+-.TP
+-* /
+-Multiply and divide.
+-.TP
+-^
+-Exponentiation.
+-.PP
+-The following is a list of builtin functions:
+-.TP 7
+-.B arg(i)
+-is the value of the
+-.IR i " -th"
+-actual parameter on the current level
+-of function call.
+-.TP 7
+-.B exp(x)
+-is the exponential function of
+-.IR x .
+-.TP 7
+-.B log(x)
+-is the natural logarithm of
+-.IR x .
+-.TP 7
+-.B sqr(x)
+-is the square root of
+-.IR x .
+-.TP 7
+-.B sin(x)
+-is the sine of
+-.IR x ""
+-(radians).
+-.TP 7
+-.B cos(x)
+-is the cosine of
+-.IR x ""
+-(radians).
+-.TP 7
+-.B atn(x)
+-is the arctangent of
+-.IR x .
+-Its value
+-is between \-\(*p/2 and \(*p/2.
+-.TP 7
+-.B "rnd( )"
+-is a uniformly distributed random
+-number between zero and one.
+-.TP 7
+-.B "expr( )"
+-is the only form of program input.
+-A line is read from the input and
+-evaluated as an expression.
+-The resultant value is returned.
+-.TP 7
+-.B abs(x)
+-is the absolute value of
+-.IR x .
+-.TP 7
+-.B int(x)
+-returns
+-.I x
+-truncated (towards 0) to an integer.
+-.SH FILES
+-/tmp/btm?     temporary
+-.br
+-b.out         save file
+-.br
+-/bin/ed       for
+-.B edit
+-.SH DIAGNOSTICS
+-Syntax
+-errors cause the incorrect line to be typed
+-with an underscore where the parse failed.
+-All other diagnostics are self explanatory.
+-.SH BUGS
+-Has been known to give core images.
+-.br
+-Catches interrupts even when they are turned off.
+//GO.SYSIN DD bas.1
+echo basename.1
+sed 's/.//' >basename.1 <<'//GO.SYSIN DD basename.1'
+-.TH BASENAME 1 
+-.SH NAME
+-basename \- strip filename affixes
+-.SH SYNOPSIS
+-.B basename
+-string [ suffix ]
+-.SH DESCRIPTION
+-.I Basename
+-deletes any prefix ending in `/' and the
+-.I suffix,
+-if present in
+-.I string,
+-from
+-.I string,
+-and prints the result on the standard output.
+-It is normally used inside substitution marks \`\ \`
+-in shell procedures.
+-.PP
+-This shell procedure invoked with the argument
+-.I /usr/src/cmd/cat.c
+-compiles the named file and moves the output to
+-.I cat
+-in the current directory:
+-.IP "" 15n
+-cc $1
+-.br
+-mv a.out \`basename $1 .c\`
+-.SH "SEE ALSO"
+-sh(1)
+//GO.SYSIN DD basename.1
+echo bc.1
+sed 's/.//' >bc.1 <<'//GO.SYSIN DD bc.1'
+-.TH BC 1 
+-.SH NAME
+-bc \- arbitrary-precision arithmetic language
+-.SH SYNOPSIS
+-.B bc
+-[
+-.B \-c
+-] [
+-.B \-l
+-] [ file ... ]
+-.SH DESCRIPTION
+-.I Bc
+-is an interactive processor for a language which resembles
+-C but provides unlimited precision arithmetic.
+-It takes input from any files given, then reads
+-the standard input.
+-The
+-.B \-l
+-argument stands for the name
+-of an arbitrary precision math library.
+-The syntax for 
+-.I bc
+-programs is as follows;
+-L means letter a-z,
+-E means expression, S means statement.
+-.HP 6
+-Comments
+-.br
+-are enclosed in /* and */.
+-.HP 6
+-Names
+-.br
+-simple variables: L
+-.br
+-array elements: L [ E ]
+-.br
+-The words `ibase', `obase', and `scale'
+-.HP 6
+-Other operands
+-.br
+-arbitrarily long numbers with optional sign and decimal point.
+-.br
+-( E )
+-.br
+-sqrt ( E )
+-.br
+-length ( E )  number of significant decimal digits
+-.br
+-scale ( E )   number of digits right of decimal point
+-.br
+-L ( E , ... , E )
+-.HP 6
+-Operators
+-.br
+-+  \-  *  /  %  ^
+-(% is remainder; ^ is power)
+-.br
+-++   \-\-         (prefix and postfix; apply to names)
+-.br
+-==  <=  >=  !=  <  >
+-.br
+-=  =+  =\-  =*  =/  =%  =^
+-.br
+-.HP 6
+-Statements
+-.br
+-E
+-.br
+-{ S ; ... ; S }
+-.br
+-if ( E ) S
+-.br
+-while ( E ) S
+-.br
+-for ( E ; E ; E ) S
+-.br
+-null statement
+-.br
+-break
+-.br
+-quit
+-.HP 6
+-Function definitions
+-.br
+-define L ( L ,..., L ) {
+-.br
+-      auto L, ... , L
+-.br
+-      S; ... S
+-.br
+-      return ( E )
+-.br
+-}
+-.HP 6
+-Functions in 
+-.B \-l
+-math library
+-.br
+-s(x)  sine
+-.br
+-c(x)  cosine
+-.br
+-e(x)  exponential
+-.br
+-l(x)  log
+-.br
+-a(x)  arctangent
+-.br
+-j(n,x)        Bessel function
+-.PP
+-.DT
+-All function arguments are passed by value.
+-.PP
+-The value of a statement that is an expression is printed
+-unless the main operator is an assignment.
+-Either semicolons or newlines may separate statements.
+-Assignment to
+-.I scale
+-influences the number of digits to be retained on arithmetic
+-operations in the manner of
+-.IR dc (1).
+-Assignments to
+-.I ibase
+-or
+-.I obase
+-set the input and output number radix respectively.
+-.PP
+-The same letter may be used as an array, a function,
+-and a simple variable simultaneously.
+-All variables are global to the program.
+-`Auto' variables are pushed down during function calls.
+-When using arrays as function arguments
+-or defining them as automatic variables
+-empty square brackets must follow the array name.
+-.PP
+-For example
+-.PP
+-.nf
+-scale = 20
+-define e(x){
+-      auto a, b, c, i, s
+-      a = 1
+-      b = 1
+-      s = 1
+-      for(i=1; 1==1; i++){
+-              a = a*x
+-              b = b*i
+-              c = a/b
+-              if(c == 0) return(s)
+-              s = s+c
+-      }
+-}
+-.PP
+-.fi
+-defines a function to compute an approximate value of
+-the exponential function and
+-.PP
+-.nf
+-      for(i=1; i<=10; i++) e(i)
+-.fi
+-.PP
+-prints approximate values of the exponential function of
+-the first ten integers.
+-.PP
+-.I Bc
+-is actually a preprocessor for
+-.IR dc (1),
+-which it invokes automatically, unless the
+-.B \-c
+-(compile only)
+-option is present.
+-In this case the
+-.I dc
+-input is sent to the standard output instead.
+-.SH FILES
+-.ta \w'/usr/lib/lib.b 'u
+-/usr/lib/lib.b        mathematical library
+-.br
+-dc(1) desk calculator proper
+-.SH "SEE ALSO"
+-dc(1)
+-.br
+-L. L. Cherry and R. Morris,
+-.I
+-BC \- An arbitrary precision desk-calculator language
+-.SH BUGS
+-No &&, \(or\|\(or, or ! operators.
+-.br
+-.I For
+-statement must have all three E's.
+-.br
+-.I \11\11Quit
+-is interpreted when read, not when executed.
+//GO.SYSIN DD bc.1
+echo cal.1
+sed 's/.//' >cal.1 <<'//GO.SYSIN DD cal.1'
+-.TH CAL 1 
+-.SH NAME
+-cal \- print calendar
+-.SH SYNOPSIS
+-.B cal
+-[ month ] year
+-.SH DESCRIPTION
+-.I Cal
+-prints a calendar for the specified year.
+-If a month is also specified, a calendar
+-just for that month is printed.
+-.I Year
+-can be between 1
+-and 9999.
+-The
+-.I month
+-is a number between 1 and 12.
+-The calendar
+-produced is that for England and her colonies.
+-.PP
+-Try September 1752.
+-.SH BUGS
+-The year is always considered to start in January even though this
+-is historically naive.
+-.br
+-Beware that `cal 78' refers to the early Christian era,
+-not the 20th century.
+//GO.SYSIN DD cal.1
+echo calendar.1
+sed 's/.//' >calendar.1 <<'//GO.SYSIN DD calendar.1'
+-.TH CALENDAR 1 
+-.SH NAME
+-calendar \- reminder service
+-.SH SYNOPSIS
+-.B calendar
+-[ \- ]
+-.SH DESCRIPTION
+-.I Calendar 
+-consults the file `calendar' in the current directory
+-and prints out lines that contain today's or
+-tomorrow's date anywhere in the line.
+-Most reasonable month-day dates such as `Dec. 7,'
+-`december 7,' `12/7,' etc., are recognized, but not
+-`7 December' or `7/12'.
+-On weekends `tomorrow' extends through Monday.
+-.PP
+-When 
+-an argument is present,
+-.I calendar
+-does its job for every user
+-who has a file `calendar' in his login directory
+-and sends him any positive results by
+-.IR mail (1).
+-Normally this is done daily in the wee hours under control of
+-.IR cron (8).
+-.SH FILES
+-calendar
+-.br
+-/usr/lib/calendar to figure out today's and tomorrow's dates
+-.br
+-/etc/passwd
+-.br
+-/tmp/cal*
+-.br
+-egrep, sed, mail subprocesses
+-.SH "SEE ALSO"
+-at(1), cron(8), mail(1)
+-.SH BUGS
+-Your calendar must be public information for you
+-to get reminder service.
+-.br
+-.I Calendar's
+-extended idea of `tomorrow' doesn't account for
+-holidays.
+//GO.SYSIN DD calendar.1
+echo cat.1
+sed 's/.//' >cat.1 <<'//GO.SYSIN DD cat.1'
+-.TH CAT 1
+-.SH NAME
+-cat \- catenate and print
+-.SH SYNOPSIS
+-.B cat
+-[
+-.B \-u
+-] file ...
+-.SH DESCRIPTION
+-.I Cat
+-reads each
+-.I file
+-in sequence and writes it on the standard output.
+-Thus
+-.IP
+-cat file
+-.LP
+-prints the file and
+-.IP
+-cat file1 file2 >file3
+-.LP
+-concatenates the first two files and places the result
+-on the third.
+-.PP
+-If no
+-.I file
+-is given, or if the argument `\-' is encountered,
+-.I cat 
+-reads from the standard input.
+-Output is buffered in 512-byte blocks unless the
+-standard output is a terminal or the
+-.B \-u
+-option is present.
+-.SH SEE ALSO
+-pr(1), cp(1)
+-.SH BUGS
+-Beware of `cat a b >a' and `cat a b >b', which
+-destroy input files before reading them.
+//GO.SYSIN DD cat.1
+echo cb.1
+sed 's/.//' >cb.1 <<'//GO.SYSIN DD cb.1'
+-.TH CB 1
+-.SH NAME
+-cb \- C program beautifier
+-.SH SYNOPSIS
+-.B cb
+-.SH DESCRIPTION
+-.I Cb
+-places a copy of the C program from the standard input
+-on the standard output with spacing and indentation
+-that displays the structure of the program.
+-.SH BUGS
+//GO.SYSIN DD cb.1
+echo cc.1
+sed 's/.//' >cc.1 <<'//GO.SYSIN DD cc.1'
+-.TH CC 1  PDP11
+-.SH NAME
+-cc, pcc \- C compiler
+-.SH SYNOPSIS
+-.B cc
+-[ option ] ... file ...
+-.PP
+-.B pcc
+-[ option ] ... file ...
+-.SH DESCRIPTION
+-.I Cc
+-is the UNIX C compiler.
+-It accepts several types of arguments:
+-.PP
+-Arguments whose names end with `.c' are taken to be
+-C source programs; they are compiled, and
+-each object program is left on the file
+-whose name is that of the source with `.o' substituted
+-for `.c'.
+-The `.o' file is normally deleted, however, if a single
+-C program is compiled and loaded all at one go.
+-.PP
+-In the same way,
+-arguments whose names end with `.s' are taken to be assembly source programs
+-and are assembled, producing a `.o' file.
+-.PP
+-The following options are interpreted by
+-.IR cc .
+-See
+-.IR ld (1)
+-for load-time options.
+-.TP 8
+-.B \-c
+-Suppress the loading phase of the compilation, and force
+-an object file to be produced even if only one program is compiled.
+-.TP
+-.B \-p
+-Arrange for the compiler to produce code
+-which counts the number of times each routine is called;
+-also, if loading takes place, replace the standard startup
+-routine by one which automatically calls
+-.IR monitor (3)
+-at the start and arranges to write out a
+-.I mon.out
+-file at normal termination of execution of the object program.
+-An execution profile can then be generated by
+-use of
+-.IR  prof (1).
+-.TP
+-.B \-f
+-In systems without hardware floating-point,
+-use a version of the C compiler which handles floating-point
+-constants and
+-loads the object program with the floating-point interpreter.
+-Do not use if the hardware is present.
+-.TP
+-.SM
+-.B \-O
+-Invoke an
+-object-code optimizer.
+-.TP
+-.SM
+-.B \-S
+-Compile the named C programs, and leave the
+-assembler-language output on corresponding files suffixed `.s'.
+-.TP
+-.SM
+-.B \-P
+-Run only the macro preprocessor and place the result for
+-each `.c' file in a corresponding `.i' file
+-and has no `#' lines in it.
+-.TP
+-.SM
+-.B \-E
+-Run only the macro preprocessor
+-and send the result to the
+-standard output.
+-The output is intended for compiler debugging; it 
+-is unacceptable as input to
+-.IR cc .
+-.TP
+-.BI \-o " output"
+-Name the final output file
+-.IR output .
+-If this option is used the file `a.out' will be left undisturbed.
+-.TP
+-.BI \-D name=def
+-.br
+-.ns
+-.TP
+-.SM
+-.BI \-D \*Sname
+-Define the
+-.I name
+-to the preprocessor,
+-as if by
+-`#define'.
+-If no definition is given, the name is defined as 1.
+-.TP
+-.SM
+-.BI \-U \*Sname
+-Remove any initial definition of
+-.IR name .
+-.TP
+-.SM
+-.BI \-I \*Sdir
+-`#include' files
+-whose names do not begin with `/' are always
+-sought first in the directory 
+-of the
+-.I file
+-argument,
+-then in directories named in 
+-.B \-I
+-options,
+-then in directories on a standard list.
+-.TP
+-.SM
+-.BI \-B \*Sstring
+-Find substitute compiler passes in the files named
+-.I string
+-with the suffixes cpp, c0, c1 and c2.
+-If 
+-.I string 
+-is empty, use a standard backup version.
+-.TP
+-.BR \-t [ p012 ]
+-Find only the designated compiler passes in the
+-files whose names are constructed by a
+-.B \-B
+-option.
+-In the absence of a
+-.B \-B 
+-option, the
+-.I string
+-is taken to be `/usr/c/'.
+-.PP
+-Other arguments
+-are taken
+-to be either loader option arguments, or C-compatible
+-object programs, typically produced by an earlier
+-.I cc
+-run,
+-or perhaps libraries of C-compatible routines.
+-These programs, together with the results of any
+-compilations specified, are loaded (in the order
+-given) to produce an executable program with name
+-.B a.out.
+-.PP
+-The major purpose of the `portable C compiler',
+-.I pcc,
+-is to serve as a model
+-on which to base other compilers.
+-.I Pcc
+-does not support options
+-.BR \-f ,
+-.BR \-E ,
+-.BR \-B ,
+-and
+-.BR \-t .
+-It provides, in addition to the language of
+-.I cc,
+-unsigned char type data and initialized bit fields.
+-.SH FILES
+-.ta \w'/usr/c/oc[102]  'u
+-file.c        input file
+-.br
+-file.o        object file
+-.br
+-a.out loaded output
+-.br
+-/tmp/ctm?     temporaries for
+-.I cc
+-.br
+-/lib/cpp      preprocessor
+-.br
+-/lib/c[01]    compiler for
+-.I cc
+-.br
+-/usr/c/oc[012]        backup compiler for
+-.I cc
+-.br
+-/usr/c/ocpp   backup preprocessor
+-.br
+-/lib/fc[01]   floating-point compiler
+-.br
+-/lib/c2       optional optimizer
+-.br
+-/lib/crt0.o   runtime startoff
+-.br
+-/lib/mcrt0.o  startoff for profiling
+-.br
+-/lib/fcrt0.o  startoff for floating-point interpretation
+-.br
+-/lib/libc.a   standard library, see
+-.IR intro (3)
+-.br
+-/usr/include  standard directory for `#include' files
+-.br
+-/tmp/pc*      temporaries for
+-.I pcc
+-.br
+-/usr/lib/ccom compiler for
+-.I pcc
+-.SH "SEE ALSO"
+-B. W. Kernighan and D. M. Ritchie,
+-.I The C Programming Language,
+-Prentice-Hall,
+-1978
+-.br
+-D. M. Ritchie,
+-.I
+-C Reference Manual
+-.br
+-monitor(3), prof(1), adb(1), ld(1)
+-.SH DIAGNOSTICS
+-The diagnostics produced by C itself are intended to be
+-self-explanatory.
+-Occasional messages may be produced by the assembler
+-or loader.
+-Of these, the most mystifying are from the assembler,
+-.IR as (1),
+-in particular `m', which means
+-a multiply-defined external symbol (function
+-or data).
+-.SH BUGS
+-.I Pcc
+-is little tried on the PDP11; specialized
+-code generated for that machine has not been
+-well shaken down.
+-The
+-.B \-O
+-optimizer was designed to work with
+-.IR cc ;
+-its use with
+-.I pcc
+-is suspect.
+//GO.SYSIN DD cc.1
+echo cd.1
+sed 's/.//' >cd.1 <<'//GO.SYSIN DD cd.1'
+-.TH CD 1 
+-.SH NAME
+-cd \- change working directory
+-.SH SYNOPSIS
+-.B cd
+-directory
+-.SH DESCRIPTION
+-.I Directory
+-becomes the new working directory.
+-The process must have execute (search)
+-permission in
+-.IR directory .
+-.PP
+-Because a new process is created to execute each command,
+-.I cd
+-would be ineffective if it were written as a
+-normal command.  It is therefore recognized and executed
+-by the Shell.
+-.SH "SEE ALSO"
+-sh(1), pwd(1), chdir(2)
+//GO.SYSIN DD cd.1
+echo chmod.1
+sed 's/.//' >chmod.1 <<'//GO.SYSIN DD chmod.1'
+-.TH CHMOD 1 
+-.SH NAME
+-chmod \- change mode
+-.SH SYNOPSIS
+-.B chmod
+-mode file ...
+-.SH DESCRIPTION
+-The mode of
+-each named file
+-is changed
+-according to
+-.I mode,
+-which may be absolute or symbolic.
+-An absolute
+-.I mode
+-is an octal
+-number constructed
+-from the OR of the
+-following modes:
+-.TP 10
+-4000
+-set user ID on execution
+-.br
+-.br
+-.ns
+-.TP 10
+-2000
+-set group ID on execution
+-.br
+-.br
+-.ns
+-.TP 10
+-1000
+-sticky bit, see
+-.IR  chmod (2)
+-.br
+-.br
+-.ns
+-.TP 10
+-0400
+-read by owner
+-.br
+-.br
+-.ns
+-.TP 10
+-0200
+-write by owner
+-.br
+-.br
+-.ns
+-.TP 10
+-0100
+-execute (search in directory) by owner
+-.br
+-.br
+-.ns
+-.TP 10
+-0070
+-read, write, execute (search) by group
+-.br
+-.br
+-.ns
+-.TP 10
+-0007
+-read, write, execute (search) by others
+-.PP
+-A symbolic
+-.I mode
+-has the form:
+-.IP
+-.RI [ who ]
+-.I op permission
+-.RI [ "op permission" "] ..."
+-.PP
+-The
+-.I who
+-part is a combination
+-of the letters 
+-.B u
+-(for user's permissions),
+-.B g
+-(group)
+-and
+-.B o
+-(other).
+-The letter
+-.B a
+-stands for
+-.B ugo.
+-If
+-.I who
+-is omitted,
+-the default is
+-.I a
+-but the setting of
+-the file creation mask
+-(see umask(2))
+-is taken into account.
+-.PP
+-.I Op
+-can be
+-.B +
+-to add
+-.I permission
+-to the file's mode,
+-.B \-
+-to take away
+-.I permission
+-and
+-.B =
+-to assign
+-.I permission
+-absolutely
+-(all other bits will
+-be reset).
+-.PP
+-.I Permission
+-is any combination of the letters
+-.B r
+-(read),
+-.B w
+-(write),
+-.B x
+-(execute),
+-.B s
+-(set owner or group id)
+-and
+-.B t
+-(save text \- sticky).
+-Letters
+-.BR u,
+-.B g
+-or
+-.B o
+-indicate that
+-.I permission
+-is to be taken
+-from the current
+-mode.
+-Omitting
+-.I permission
+-is only useful
+-with
+-.B =
+-to take away
+-all permissions.
+-.PP
+-The first example denies write permission to others,
+-the second makes a file executable:
+-.IP
+-chmod o\-w file
+-.br
+-chmod +x file
+-.PP
+-Multiple symbolic modes separated by commas may be given.
+-Operations are performed
+-in the order specified.
+-The letter
+-.B s
+-is only useful
+-with
+-.B u
+-or
+-.B g.
+-.PP
+-Only the owner of a file (or the super-user) may change its mode.
+-.SH "SEE ALSO"
+-ls(1),
+-chmod(2),
+-chown (1),
+-stat(2),
+-umask(2)
+//GO.SYSIN DD chmod.1
+echo chown.1
+sed 's/.//' >chown.1 <<'//GO.SYSIN DD chown.1'
+-.TH CHOWN 1 
+-.SH NAME
+-chown, chgrp \- change owner or group
+-.SH SYNOPSIS
+-.B chown
+-owner file ...
+-.PP
+-.B chgrp
+-group file ...
+-.SH DESCRIPTION
+-.I Chown
+-changes the owner of the
+-.I files
+-to
+-.IR owner .
+-The owner may be either a decimal UID or
+-a login name found in the password file.
+-.PP
+-.I Chgrp
+-changes the group-ID of the
+-.I files
+-to
+-.IR group .
+-The group may be either a decimal GID or
+-a group name found in the group-ID file.
+-.PP
+-Only the super-user can change owner or group,
+-in order to simplify as yet unimplemented accounting procedures.
+-.SH FILES
+-/etc/passwd
+-.br
+-/etc/group
+-.SH "SEE ALSO"
+-chown(2),
+-passwd(5), group(5)
+//GO.SYSIN DD chown.1
+echo clri.1m
+sed 's/.//' >clri.1m <<'//GO.SYSIN DD clri.1m'
+-.TH CLRI 1M 
+-.SH NAME
+-clri \- clear i-node
+-.SH SYNOPSIS
+-.B clri
+-filesystem i-number ...
+-.SH DESCRIPTION
+-.I Clri
+-writes zeros on the i-nodes
+-with the decimal
+-.I i-numbers
+-on the
+-.I filesystem.
+-After
+-.I clri,
+-any blocks
+-in the affected file
+-will show up as `missing' in an
+-.IR icheck (1)
+-of the
+-.I filesystem.
+-.PP
+-Read and write permission is required on the specified
+-file system device.
+-The i-node becomes allocatable.
+-.PP
+-The primary purpose of this routine
+-is to remove a file which
+-for some reason appears in no
+-directory.
+-If it is used to zap an i-node
+-which does appear in a directory, care should be taken to track down
+-the entry and remove it.
+-Otherwise, when the i-node is reallocated to some new file,
+-the old entry will still point to that file.
+-At that point removing the old entry will destroy the new file.
+-The new entry will again point to an unallocated i-node,
+-so the whole cycle is likely to be repeated again and again.
+-.SH "SEE ALSO"
+-icheck(1)
+-.SH BUGS
+-If the file is open,
+-.I clri
+-is likely to be ineffective.
+//GO.SYSIN DD clri.1m
+echo cmp.1
+sed 's/.//' >cmp.1 <<'//GO.SYSIN DD cmp.1'
+-.TH CMP 1 
+-.SH NAME
+-cmp \- compare two files
+-.SH SYNOPSIS
+-.B cmp
+-[
+-.B \-l
+-] [
+-.B \-s
+-]
+-file1 file2
+-.SH DESCRIPTION
+-The two files are
+-compared.
+-(If
+-.I file1
+-is `\-',
+-the standard input is used.)
+-Under default options,
+-.I cmp
+-makes no comment if the files are the same;
+-if they differ, it announces the byte and line number
+-at which the difference occurred.
+-If one file is an initial subsequence
+-of the other, that fact is noted.
+-.PP
+-Options:
+-.TP 6
+-.B  \-l
+-Print the byte number (decimal) and the
+-differing bytes (octal) for each difference.
+-.TP 6
+-.B  \-s
+-Print nothing for differing files;
+-return codes only.
+-.dt
+-.SH "SEE ALSO"
+-diff(1), comm(1)
+-.SH DIAGNOSTICS
+-Exit code 0 is returned for identical
+-files, 1 for different files, and 2 for an
+-inaccessible or missing argument.
+//GO.SYSIN DD cmp.1
+echo col.1
+sed 's/.//' >col.1 <<'//GO.SYSIN DD col.1'
+-.TH COL 1
+-.SH NAME
+-col \- filter reverse line feeds
+-.SH SYNOPSIS
+-.B col [\|\-bfx\|]
+-.SH DESCRIPTION
+-.I Col
+-reads the standard input and writes the standard output.
+-It performs the line overlays implied by reverse line
+-feeds (ESC-7 in ASCII)
+-and by forward and reverse half line feeds (ESC-9 and ESC-8).
+-.I Col
+-is particularly useful for filtering multicolumn
+-output made with the `.rt' command of
+-.I nroff
+-and output resulting from use of the
+-.IR tbl (1)
+-preprocessor.
+-.PP
+-Although
+-.I col
+-accepts half line motions in its input, it normally does not
+-emit them on output.
+-Instead, text that would appear between lines is moved to the next lower
+-full line boundary.
+-This treatment can be suppressed by the
+-.B \-f
+-(fine) option; in this case
+-the output from
+-.I col
+-may contain forward half line feeds (ESC-9), but will still never contain
+-either kind of reverse line motion.
+-.PP
+-If the
+-.B \-b
+-option is given,
+-.I col
+-assumes that the output device in use is not capable of backspacing.
+-In this case, if several characters are to appear in the same place,
+-only the last one read will be taken.
+-.PP
+-The control characters SO (ASCII code 017),
+-and SI (016) are assumed
+-to start and end text in an alternate character set.
+-The character set (primary or alternate) associated with each printing
+-character read is remembered; on output, SO and SI characters are generated
+-where necessary to maintain the correct treatment of each character.
+-.PP
+-.I Col
+-normally converts white space to tabs to shorten printing time.
+-If the
+-.B \-x
+-option is given, this conversion is suppressed.
+-.PP
+-All control characters are removed from the input except space,
+-backspace,
+-tab, return, newline, ESC (033) followed by one of 789, SI, SO, and VT
+-(013).
+-This last character is an alternate form of full reverse line feed, for
+-compatibility with some other hardware conventions.
+-All other non-printing characters are ignored.
+-.SH "SEE ALSO"
+-troff(1), tbl(1), greek(1)
+-.SH BUGS
+-Can't back up more than 128 lines.
+-.br
+-No more than 800 characters, including backspaces, on a line.
+//GO.SYSIN DD col.1
+echo comm.1
+sed 's/.//' >comm.1 <<'//GO.SYSIN DD comm.1'
+-.TH COMM 1 
+-.SH NAME
+-comm \- select or reject lines common to two sorted files
+-.SH SYNOPSIS
+-.B comm
+-[
+-.B \-
+-[
+-.B 123
+-]
+-] file1 file2
+-.SH DESCRIPTION
+-.I Comm
+-reads
+-.I file1
+-and
+-.I file2,
+-which should be ordered in ASCII collating sequence,
+-and produces a three column output: lines only in
+-.I file1;
+-lines only in
+-.I file2;
+-and lines in both files.
+-The filename `\-' means the standard input.
+-.PP
+-Flags 1, 2, or 3 suppress printing of the corresponding
+-column.
+-Thus
+-.B comm
+-.B \-12
+-prints only the lines common to the two files;
+-.B comm
+-.B \-23
+-prints only lines in the first file but not in the second;
+-.B comm
+-.B \-123
+-is a no-op.
+-.PP
+-.SH "SEE ALSO"
+-cmp(1), diff(1), uniq(1)
+//GO.SYSIN DD comm.1
+echo cp.1
+sed 's/.//' >cp.1 <<'//GO.SYSIN DD cp.1'
+-.TH CP 1 
+-.SH  NAME
+-cp \- copy
+-.SH SYNOPSIS
+-.B cp
+-file1 file2
+-.PP
+-.B cp
+-file ... directory
+-.SH DESCRIPTION
+-.I File1
+-is copied onto
+-.IR file2 .
+-The mode and owner of  
+-.I file2
+-are preserved if it already
+-existed; the mode of the source file
+-is used otherwise.
+-.PP
+-In the second form, one or more
+-.I files
+-are copied into the
+-.I directory
+-with their original file-names.
+-.PP
+-.I Cp
+-refuses to copy a file onto itself.
+-.SH "SEE ALSO"
+-cat(1), pr(1), mv(1)
+//GO.SYSIN DD cp.1
+echo crypt.1
+sed 's/.//' >crypt.1 <<'//GO.SYSIN DD crypt.1'
+-.TH CRYPT 1 
+-.SH NAME
+-crypt \- encode/decode
+-.SH SYNOPSIS
+-.B crypt
+-[ password ]
+-.SH DESCRIPTION
+-.I Crypt
+-reads from the standard input and writes
+-on the standard output.
+-The
+-.I password
+-is a key that selects a particular transformation.
+-If no
+-.I password 
+-is given,
+-.I crypt
+-demands a key from the terminal and turns
+-off printing while the key is being typed in.
+-.I Crypt
+-encrypts and decrypts with the same key:
+-.PP
+-      crypt key <clear >cypher
+-.br
+-      crypt key <cypher | pr
+-.PP
+-will print the clear.
+-.PP
+-Files encrypted by
+-.I crypt
+-are compatible with those treated by the editor
+-.I ed
+-in encryption mode.
+-.PP
+-The security of encrypted files depends on three factors:
+-the fundamental method must be hard to solve;
+-direct search of the key space must be infeasible;
+-`sneak paths' by which keys or cleartext can become
+-visible must be minimized.
+-.PP
+-.I Crypt
+-implements a one-rotor machine designed along the lines
+-of the German Enigma, but with a 256-element rotor.
+-Methods of attack on such machines are known, but not widely;
+-moreover the amount of work required is likely to be large.
+-.PP
+-The transformation of a key into the internal
+-settings of the machine is deliberately designed to
+-be expensive, i.e. to take a substantial fraction of
+-a second to compute.
+-However,
+-if keys are restricted to (say)
+-three lower-case letters,
+-then encrypted files can be read by expending only
+-a substantial fraction of
+-five minutes of machine time.
+-.PP
+-Since the key is an argument to the
+-.I crypt
+-command,
+-it is potentially visible to users executing
+-.IR ps (1)
+-or a derivative.
+-To minimize this possibility,
+-.I crypt
+-takes care to destroy any record of the key
+-immediately upon entry.
+-No doubt the choice of keys and key security
+-are the most vulnerable aspect of
+-.I crypt.
+-.SH FILES
+-/dev/tty for typed key
+-.SH "SEE ALSO"
+-ed(1),
+-makekey(8)
+-.SH BUGS
+-There is no warranty of merchantability nor any warranty
+-of fitness for a particular purpose nor any other warranty,
+-either express or implied, as to the accuracy of the
+-enclosed materials or as to their suitability for any
+-particular purpose.  Accordingly, Bell Telephone
+-Laboratories assumes no responsibility for their use by the
+-recipient.   Further, Bell Laboratories assumes no obligation
+-to furnish any assistance of any kind whatsoever, or to
+-furnish any additional information or documentation.
+//GO.SYSIN DD crypt.1
+echo cu.1c
+sed 's/.//' >cu.1c <<'//GO.SYSIN DD cu.1c'
+-.TH CU 1C 
+-.SH NAME
+-cu \- call UNIX
+-.SH SYNOPSIS
+-.B cu
+-telno
+-[
+-.BR \-t ""
+-]
+-[
+-.BR \-s ""
+-speed ]
+-[
+-.BR \-a ""
+-acu ]
+-[
+-.BR \-l ""
+-line ]
+-.SH DESCRIPTION
+-.I Cu
+-calls up another UNIX system,
+-a terminal,
+-or possibly a non-UNIX system.
+-It manages an interactive conversation with possible
+-transfers of text files.
+-.I Telno
+-is the telephone number,
+-with minus signs at appropriate places for delays.
+-The
+-.BR \-t ""
+-flag is used to dial out to a terminal.
+-.I Speed
+-gives the transmission speed (110, 134, 150, 300, 1200);
+-300 is the default value.
+-.PP
+-The
+-.BR \-a ""
+-and
+-.BR \-l ""
+-values may be used to
+-specify pathnames
+-for the ACU and communications line devices.
+-They can be used to override the following
+-built-in choices:
+-.PP
+-.BR \-a " /dev/cua0"
+-.BR \-l " /dev/cul0"
+-.PP
+-After making the connection,
+-.I cu
+-runs as two processes:
+-the
+-.I send
+-process reads the standard input and
+-passes most of it to the remote system;
+-the
+-.I receive
+-process reads from the remote system and passes
+-most data to the standard output.
+-Lines beginning with `~' have special meanings.
+-.PP
+-The
+-.I send
+-process interprets the following:
+-.TP 18
+-~\|\fB.\|
+-terminate the conversation.
+-.br
+-.ns
+-.TP 18
+-~EOT
+-terminate the conversation
+-.TP 18
+-~<file
+-send the contents of
+-.I file
+-to the remote system,
+-as though typed at the terminal.
+-.TP 18
+-~!
+-invoke an interactive shell on the local system.
+-.TP 18
+-~!cmd ...
+-run the command on the local system
+-(via
+-.BR "sh \-c" ")."
+-.TP 18
+-~$cmd ...
+-run the command locally and send its output
+-to the remote system.
+-.TP 18
+-~%take from [to]
+-copy file `from' (on the remote system)
+-to file `to' on the local system.
+-If `to' is omitted,
+-the `from' name is used both places.
+-.TP 18
+-~%put from [to]
+-copy file `from' (on local system)
+-to file `to' on remote system.
+-If `to' is omitted, the `from' name is used both places.
+-.TP 18
+-~~\fB\|.\|.\|.\fR
+-send
+-the line `~\|.\|.\|.'.
+-.PP
+-The
+-.I receive
+-process handles output diversions of the following form:
+-.PP
+-\&~>[>][:]file
+-.br
+-zero or more lines to be written to file
+-.br
+-\&~>
+-.PP
+-In any case, output is diverted (or appended, if `>>' used) to the file.
+-If `:' is used,
+-the diversion is
+-.I silent,
+-i.e., it is written only to the file.
+-If `:' is omitted,
+-output is written both to the file and to the standard output.
+-The trailing `~>' terminates the diversion.
+-.PP
+-The use of
+-.B  ~%put
+-requires
+-.I stty
+-and
+-.I cat
+-on the remote side.
+-It also requires that the
+-current erase and kill characters on the remote
+-system be identical to the current ones on the local system.
+-Backslashes are inserted at appropriate places.
+-.PP
+-The use of
+-.B  ~%take
+-requires the existence of
+-.I echo
+-and
+-.I tee
+-on the remote system.
+-Also,
+-.B "stty tabs"
+-mode is required on the remote system if
+-tabs are to be copied without expansion.
+-.SH FILES
+-/dev/cua0
+-.br
+-/dev/cul0
+-.br
+-/dev/null
+-.SH "SEE ALSO"
+-dn(4), tty(4)
+-.SH DIAGNOSTICS
+-Exit code is
+-zero for normal exit,
+-nonzero (various values) otherwise.
+-.SH BUGS
+-The syntax is unique.
+//GO.SYSIN DD cu.1c
+echo date.1
+sed 's/.//' >date.1 <<'//GO.SYSIN DD date.1'
+-.TH DATE 1 
+-.SH NAME
+-date \- print and set the date
+-.SH SYNOPSIS
+-.B date
+-.RB "[ yymmddhhmm [ " . "ss ] ]"
+-.SH DESCRIPTION
+-If no argument is given, the current date and time are printed.
+-If an argument is given, the current date is set.
+-.I yy
+-is the last two digits of the year;
+-the first
+-.I mm
+-is the month number;
+-.I dd
+-is the day number in the month;
+-.I hh
+-is the hour number (24 hour system);
+-the second
+-.I mm
+-is the minute number;
+-.BI . ss
+-is optional and is the seconds.
+-For example:
+-.IP
+-date 10080045
+-.PP
+-sets the date to Oct 8, 12:45 AM.
+-The year, month and day may be omitted, the current
+-values being the defaults.
+-The system operates in GMT.
+-.I Date
+-takes care of the conversion to and from
+-local standard and daylight time.
+-.SH FILES
+-/usr/adm/wtmp to record time-setting
+-.SH SEE ALSO
+-utmp(5)
+-.SH DIAGNOSTICS
+-`No permission' if
+-you aren't the super-user and you try to change the date;
+-`bad conversion' if the date set is syntactically incorrect.
+//GO.SYSIN DD date.1
+echo dc.1
+sed 's/.//' >dc.1 <<'//GO.SYSIN DD dc.1'
+-.TH DC 1 
+-.SH NAME
+-dc \- desk calculator
+-.SH SYNOPSIS
+-.B dc
+-[ file ]
+-.SH DESCRIPTION
+-.I Dc
+-is an arbitrary precision arithmetic package.
+-Ordinarily it operates on decimal integers,
+-but one may specify an input base, output base,
+-and a number of fractional digits to be maintained.
+-The overall structure of
+-.I dc
+-is
+-a stacking (reverse Polish) calculator.
+-If an argument is given,
+-input is taken from that file until its end,
+-then from the standard input.
+-The following constructions are recognized:
+-.HP 6
+-number
+-.br
+-The value of the number is pushed on the stack.
+-A number is an unbroken string of the digits 0-9.
+-It may be preceded by an underscore _ to input a
+-negative number.
+-Numbers may contain decimal points.
+-.HP 6
+-+  \- /  *  %  ^
+-.br
+-The
+-top two values on the stack are added
+-(+),
+-subtracted
+-(\-),
+-multiplied (*),
+-divided (/),
+-remaindered (%),
+-or exponentiated (^).
+-The two entries are popped off the stack;
+-the result is pushed on the stack in their place.
+-Any fractional part of an exponent is ignored.
+-.TP
+-.BI s x
+-The
+-top of the stack is popped and stored into
+-a register named
+-.I x,
+-where
+-.I x
+-may be any character.
+-If
+-the
+-.B s
+-is capitalized,
+-.I x
+-is treated as a stack and the value is pushed on it.
+-.TP
+-.BI l x
+-The
+-value in register
+-.I x
+-is pushed on the stack.
+-The register
+-.I x
+-is not altered.
+-All registers start with zero value.
+-If the
+-.B l
+-is capitalized,
+-register
+-.I x
+-is treated as a stack and its top value is popped onto the main stack.
+-.TP
+-.B  d
+-The
+-top value on the stack is duplicated.
+-.TP
+-.B  p
+-The top value on the stack is printed.
+-The top value remains unchanged.
+-.B P
+-interprets the top of the stack as an ascii string,
+-removes it, and prints it.
+-.TP
+-.B  f
+-All values on the stack and in registers are printed.
+-.TP
+-.B  q
+-exits the program.
+-If executing a string, the recursion level is
+-popped by two.
+-If
+-.B q
+-is capitalized,
+-the top value on the stack is popped and the string execution level is popped
+-by that value.
+-.TP
+-.B  x
+-treats the top element of the stack as a character string
+-and executes it as a string of dc commands.
+-.TP
+-.B  X
+-replaces the number on the top of the stack with its scale factor.
+-.TP
+-.B  "[ ... ]"
+-puts the bracketed ascii string onto the top of the stack.
+-.HP 6
+-.I  "<x  >x  =x"
+-.br
+-The
+-top two elements of the stack are popped and compared.
+-Register
+-.I x
+-is executed if they obey the stated
+-relation.
+-.TP
+-.B  v
+-replaces the top element on the stack by its square root.
+-Any existing fractional part of the argument is taken
+-into account, but otherwise the scale factor is ignored.
+-.TP
+-.B  !
+-interprets the rest of the line as a UNIX command.
+-.TP
+-.B  c
+-All values on the stack are popped.
+-.TP
+-.B  i
+-The top value on the stack is popped and used as the
+-number radix for further input.
+-.B I
+-pushes the input base on the top of the stack.
+-.TP
+-.B  o
+-The top value on the stack is popped and used as the
+-number radix for further output.
+-.TP
+-.SM
+-.B O
+-pushes the output base on the top of the stack.
+-.TP
+-.B  k
+-the top of the stack is popped, and that value is used as
+-a non-negative scale factor:
+-the appropriate number of places
+-are printed on output,
+-and maintained during multiplication, division, and exponentiation.
+-The interaction of scale factor,
+-input base, and output base will be reasonable if all are changed
+-together.
+-.TP
+-.B  z
+-The stack level is pushed onto the stack.
+-.TP
+-.SM
+-.B  Z
+-replaces the number on the top of the stack with its length.
+-.TP
+-.B  ?
+-A line of input is taken from the input source (usually the terminal)
+-and executed.
+-.TP
+-.B "; :"
+-are used by 
+-.I bc
+-for array operations.
+-.PP
+-An example which prints the first ten values of n! is
+-.nf
+-.PP
+-.in +3
+-[la1+dsa*pla10>y]sy
+-.br
+-0sa1
+-.br
+-lyx
+-.fi
+-.SH "SEE ALSO"
+-bc(1),
+-which is a preprocessor for
+-.I dc
+-providing infix notation and a C-like syntax
+-which implements functions and reasonable control
+-structures for programs.
+-.SH DIAGNOSTICS
+-`x is unimplemented' where x is an octal number.
+-.br
+-`stack empty' for not enough elements on the stack to do what was asked.
+-.br
+-`Out of space' when the free list is exhausted (too many digits).
+-.br
+-`Out of headers' for too many numbers being kept around.
+-.br
+-`Out of pushdown' for too many items on the stack.
+-.br
+-`Nesting Depth' for too many levels of nested execution.
+//GO.SYSIN DD dc.1
+echo dcheck.1m
+sed 's/.//' >dcheck.1m <<'//GO.SYSIN DD dcheck.1m'
+-.TH DCHECK 1M 
+-.SH NAME
+-dcheck \- file system directory consistency check
+-.SH SYNOPSIS
+-.B dcheck
+-[
+-.B \-i
+-numbers ]
+-[ filesystem ]
+-.SH DESCRIPTION
+-.I Dcheck
+-reads the directories in a file system
+-and compares
+-the link-count in each i-node with the number of directory
+-entries by which it is referenced.
+-If the file system is not specified,
+-a set of default file systems
+-is checked.
+-.PP
+-The
+-.B \-i
+-flag
+-is followed by a list of i-numbers;
+-when one of those i-numbers turns up
+-in a directory,
+-the number, the i-number of the directory,
+-and the name of the entry are reported.
+-.PP
+-The program is fastest if the
+-raw version of the special file is used,
+-since the i-list is read in large chunks.
+-.SH FILES
+-Default file systems vary with installation.
+-.SH "SEE ALSO"
+-icheck(1), filsys(5), clri(1), ncheck(1)
+-.SH DIAGNOSTICS
+-When a file turns up for which the link-count and the number
+-of directory entries disagree,
+-the relevant facts are reported.
+-Allocated files which have 0 link-count and no entries are also
+-listed.
+-The only dangerous situation
+-occurs when there are more entries than links;
+-if entries are removed,
+-so the link-count drops to 0,
+-the remaining entries point to thin air.
+-They should be removed.
+-When there are more links than entries, or there is
+-an allocated file with neither links nor entries,
+-some disk space may be lost but the situation will not degenerate.
+-.SH BUGS
+-Since
+-.I dcheck
+-is inherently two-pass in nature, extraneous diagnostics
+-may be produced if applied to active file systems.
+//GO.SYSIN DD dcheck.1m
+echo dd.1
+sed 's/.//' >dd.1 <<'//GO.SYSIN DD dd.1'
+-.TH DD 1 
+-.SH NAME
+-dd \- convert and copy a file
+-.SH SYNOPSIS
+-.B dd
+-[option=value] ...
+-.SH DESCRIPTION
+-.I Dd
+-copies the specified input file
+-to the specified output with
+-possible conversions.
+-The standard input and output are used by default.
+-The input and output block size may be
+-specified to take advantage of raw physical I/O.
+-.PP
+-.br
+-.ns
+-.TP 15
+-.I option
+-.I values
+-.br
+-.ns
+-.TP 
+-if=
+-input file name; standard input is default
+-.br
+-.ns
+-.TP 
+-of=
+-output file name; standard output is default
+-.br
+-.ns
+-.TP 
+-.RI ibs= n
+-input block size
+-.I n
+-bytes (default 512)
+-.br
+-.ns
+-.TP 
+-.RI obs= n
+-output block size (default 512)
+-.br
+-.ns
+-.TP 
+-.RI bs= n
+-set both input and output block size,
+-superseding
+-.I ibs
+-and
+-.I obs;
+-also, if no conversion is specified,
+-it is particularly efficient since no copy need be done
+-.br
+-.ns
+-.TP 
+-.RI cbs= n
+-conversion buffer size
+-.br
+-.ns
+-.TP 
+-.RI skip= n
+-skip
+-.IR n ""
+-input records before starting copy
+-.br
+-.ns
+-.TP
+-.RI files= n
+-copy
+-.I n
+-files from (tape) input
+-.br
+-.ns
+-.TP 
+-.RI seek= n
+-seek
+-.I n
+-records from beginning of output file before copying
+-.br
+-.ns
+-.TP 
+-count=\fIn\fR
+-copy only
+-.IR n ""
+-input records
+-.br
+-.ns
+-.TP 
+-conv=ascii
+-.ds h \h'\w'conv='u'
+-convert EBCDIC to ASCII
+-.br
+-.ns
+-.IP \*hebcdic
+-convert ASCII to EBCDIC
+-.br
+-.ns
+-.IP \*hibm
+-slightly different map of ASCII to EBCDIC
+-.br
+-.ns
+-.IP \*hlcase
+-map alphabetics to lower case
+-.br
+-.ns
+-.IP \*hucase
+-map alphabetics to upper case
+-.br
+-.ns
+-.IP \*hswab
+-swap every pair of bytes
+-.br
+-.ns
+-.IP \*hnoerror
+-do not stop processing on an error
+-.br
+-.ns
+-.IP \*hsync
+-pad every input record to
+-.I  ibs
+-.br
+-.ns
+-.IP "\*h... , ..."
+-several comma-separated conversions
+-.PP
+-.fi
+-Where sizes are specified,
+-a number of bytes is expected.
+-A number may end with
+-.B "k, b"
+-or
+-.B w
+-to specify multiplication by
+-1024, 512, or 2 respectively;
+-a pair of numbers may be separated by
+-.B x
+-to indicate a product.
+-.PP
+-.I Cbs
+-is used only if
+-.I ascii
+-or
+-.I ebcdic
+-conversion is specified.
+-In the former case
+-.I cbs
+-characters are placed into the conversion buffer, converted to
+-ASCII, and trailing blanks trimmed and new-line added
+-before sending the line to the output.
+-In the latter case ASCII characters are read into the
+-conversion buffer, converted to EBCDIC, and blanks added
+-to make up an
+-output record of size
+-.IR cbs .
+-.PP
+-After completion,
+-.I dd
+-reports the number of whole and partial input and output
+-blocks.
+-.PP
+-For example, to read an EBCDIC tape blocked ten 80-byte
+-EBCDIC card images per record into the ASCII file
+-.IR x :
+-.IP ""
+-dd if=/dev/rmt0 of=x ibs=800 cbs=80 conv=ascii,lcase
+-.PP
+-Note the use of raw magtape.
+-.I Dd
+-is especially suited to I/O on the raw
+-physical devices because it allows reading
+-and writing in arbitrary record sizes.
+-.PP
+-To skip over a file before copying from magnetic tape do
+-.IP""
+-(dd of=/dev/null; dd of=x) </dev/rmt0
+-.SH "SEE ALSO"
+-cp(1), tr(1)
+-.SH DIAGNOSTICS
+-f+p records in(out): numbers of full and partial records read(written)
+-.SH BUGS
+-The ASCII/EBCDIC conversion tables are
+-taken
+-from the 256 character standard in
+-the CACM Nov, 1968.
+-The `ibm' conversion, while less blessed as a standard,
+-corresponds better to certain IBM print train conventions.
+-There is no universal solution.
+-.PP
+-Newlines are inserted only on conversion to ASCII;
+-padding is done only on conversion to EBCDIC.
+-These should be separate options.
+//GO.SYSIN DD dd.1
+echo deroff.1
+sed 's/.//' >deroff.1 <<'//GO.SYSIN DD deroff.1'
+-.TH DEROFF 1 
+-.SH NAME
+-deroff \- remove nroff, troff, tbl and eqn constructs
+-.SH SYNOPSIS
+-.B deroff
+-[
+-.B \-w
+-]
+-file ...
+-.SH DESCRIPTION
+-.I Deroff
+-reads each file in sequence
+-and removes all
+-.I nroff
+-and
+-.I troff
+-command lines, backslash constructions, macro definitions,
+-.I eqn
+-constructs
+-(between `.EQ' and `.EN' lines or between 
+-delimiters),
+-and table descriptions
+-and writes the remainder on the standard output.
+-.I Deroff
+-follows chains of included files
+-(`.so' and `.nx' commands);
+-if a file has already been included, a `.so' is ignored and a `.nx' terminates execution.
+-If no input file is given,
+-.I deroff
+-reads from the standard input file.
+-.PP
+-If the
+-.B \-w
+-flag is given, the output is a word list, one `word' (string of letters, digits, and apostrophes,
+-beginning with a letter; apostrophes are removed) per line, and all other characters ignored.
+-Otherwise, the output follows the original, with the deletions mentioned above.
+-.SH "SEE ALSO"
+-troff(1), eqn(1), tbl(1)
+-.SH BUGS
+-.I Deroff
+-is not a complete
+-.I troff
+-interpreter,
+-so it can be confused by subtle constructs.
+-Most errors result in too much rather than too little output.
+//GO.SYSIN DD deroff.1
+echo df.1m
+sed 's/.//' >df.1m <<'//GO.SYSIN DD df.1m'
+-.TH DF 1M 
+-.SH NAME
+-df \- disk free
+-.SH SYNOPSIS
+-.B df
+-[ filesystem ] ...
+-.SH DESCRIPTION
+-.I Df
+-prints out the number of free blocks
+-available on the
+-.I filesystems.
+-If no file system is specified,
+-the free space on all of
+-the normally mounted file systems
+-is printed.
+-.SH FILES
+-Default file systems vary with installation.
+-.SH "SEE ALSO"
+-icheck(1)
+//GO.SYSIN DD df.1m
+echo diff.1
+sed 's/.//' >diff.1 <<'//GO.SYSIN DD diff.1'
+-.TH DIFF 1 
+-.SH NAME
+-diff \- differential file comparator
+-.SH SYNOPSIS
+-.B diff
+-[
+-.B \-efbh
+-] file1 file2
+-.SH DESCRIPTION
+-.I Diff
+-tells what lines must be changed in two files to bring them
+-into agreement.
+-If
+-.I file1
+-.RI ( file2 )
+-is `\-', the standard input is used.
+-If
+-.I file1
+-.RI ( file2 )
+-is a directory, then a file in that directory
+-whose file-name is the same as the file-name of 
+-.I file2
+-.RI ( file1 )
+-is used.
+-The normal output contains lines of these forms:
+-.IP "" 5
+-.I n1
+-a
+-.I n3,n4
+-.br
+-.I n1,n2
+-d
+-.I n3
+-.br
+-.I n1,n2
+-c
+-.I n3,n4
+-.PP
+-These lines resemble
+-.I ed
+-commands to convert
+-.I file1
+-into
+-.IR file2 .
+-The numbers after the letters pertain to
+-.IR file2 .
+-In fact, by exchanging `a' for `d' and reading backward
+-one may ascertain equally how to convert 
+-.I file2
+-into
+-.IR file1 .
+-As in 
+-.I ed,
+-identical pairs where
+-.I n1
+-=
+-.I n2
+-or
+-.I n3
+-=
+-.I n4
+-are abbreviated as a single number.
+-.PP
+-Following each of these lines come all the lines that are
+-affected in the first file flagged by `<', 
+-then all the lines that are affected in the second file
+-flagged by `>'.
+-.PP
+-The
+-.B \-b
+-option causes
+-trailing blanks (spaces and tabs) to be ignored
+-and other strings of blanks to compare equal.
+-.PP
+-The
+-.B \-e
+-option produces a script of
+-.I "a, c"
+-and 
+-.I d
+-commands for the editor
+-.I ed,
+-which will recreate
+-.I file2
+-from
+-.IR file1 .
+-The
+-.B \-f
+-option produces a similar script,
+-not useful with
+-.I ed,
+-in the opposite order.
+-In connection with
+-.BR \-e ,
+-the following shell program may help maintain
+-multiple versions of a file.
+-Only an ancestral file ($1) and a chain of 
+-version-to-version
+-.I ed
+-scripts ($2,$3,...) made by
+-.I diff
+-need be on hand.
+-A `latest version' appears on
+-the standard output.
+-.IP "" 5
+-(shift; cat $*; echo \'1,$p\') \(bv ed \- $1
+-.PP
+-Except in rare circumstances,
+-.I diff
+-finds a smallest sufficient set of file
+-differences.
+-.PP
+-Option
+-.B \-h
+-does a fast, half-hearted job.
+-It works only when changed stretches are short
+-and well separated,
+-but does work on files of unlimited length.
+-Options 
+-.B \-e
+-and
+-.B \-f
+-are unavailable with
+-.BR \-h .
+-.SH FILES
+-/tmp/d?????
+-.br
+-/usr/lib/diffh for 
+-.B \-h
+-.SH "SEE ALSO"
+-cmp(1), comm(1), ed(1)
+-.SH DIAGNOSTICS
+-Exit status is 0 for no differences, 1 for some, 2 for trouble.
+-.SH BUGS
+-Editing scripts produced under the
+-.BR \-e " or"
+-.BR \-f " option are naive about"
+-creating lines consisting of a single `\fB.\fR'.
+//GO.SYSIN DD diff.1
+echo diff3.1
+sed 's/.//' >diff3.1 <<'//GO.SYSIN DD diff3.1'
+-.TH DIFF3 1 
+-.SH NAME
+-diff3 \- 3-way differential file comparison
+-.SH SYNOPSIS
+-.B diff3
+-[
+-.B \-ex3
+-]
+-file1 file2 file3
+-.SH DESCRIPTION
+-.I Diff3
+-compares three versions of a file,
+-and publishes disagreeing ranges of text
+-flagged with these codes:
+-.TP 16
+-====
+-all three files differ
+-.TP 16
+-====1
+-.IR file1 " is different"
+-.TP 16
+-====2
+-.IR file2 " is different"
+-.TP 16
+-====3
+-.IR file3 " is different"
+-.PP
+-The type of change suffered in converting a given range
+-of a given file to some other is
+-indicated in one of these ways:
+-.TP 16
+-.IB f " : " n1 " a"
+-Text is to be appended after line number
+-.I n1
+-in file
+-.I f,
+-where
+-.I f
+-= 1, 2, or 3.
+-.TP 16
+-.IB f " : " n1 " , " n2 " c"
+-Text is to be
+-changed in the range line
+-.I n1
+-to line
+-.IR n2 .
+-If 
+-.I n1
+-=
+-.I n2,
+-the range may be abbreviated to
+-.IR n1 .
+-.PP
+-The original contents of the range follows immediately
+-after a
+-.B c
+-indication.
+-When the contents of two
+-files are identical, the contents of the lower-numbered
+-file is suppressed.
+-.PP
+-Under the
+-.B \-e
+-option,
+-.I diff3
+-publishes a script for the editor
+-.I ed
+-that will incorporate into
+-.I file1
+-all changes between
+-.I file2
+-and
+-.I file3,
+-.IR i.e .
+-the changes that normally would be flagged ==== and ====3.
+-Option
+-.B \-x
+-(\fB\-3\fR)
+-produces a script to incorporate
+-only changes flagged ==== (====3).
+-The following command will apply the resulting script to
+-`file1'.
+-.PP
+-.ti 16n
+-(cat script; echo \'1,$p\') \(bv ed \- file1
+-.SH FILES
+-/tmp/d3?????
+-.br
+-/usr/lib/diff3
+-.SH "SEE ALSO"
+-diff(1)
+-.SH BUGS
+-Text lines that consist of a single `.' will
+-defeat
+-.B \-e.
+-.br
+-Files longer than 64K bytes won't work.
+//GO.SYSIN DD diff3.1
+echo du.1
+sed 's/.//' >du.1 <<'//GO.SYSIN DD du.1'
+-.TH DU 1 
+-.SH NAME
+-du  \-  summarize disk usage
+-.SH SYNOPSIS
+-.B du
+-[
+-.B \-s
+-] [
+-.B \-a
+-] [ name ... ]
+-.SH DESCRIPTION
+-.I Du
+-gives the number of blocks contained in all files
+-and (recursively) directories within each specified directory or
+-file
+-.IR name .
+-If
+-.I name
+-is missing,
+-`\fB.\fR'
+-is used.
+-.PP
+-The optional argument
+-.B \-s
+-causes only the grand total to
+-be given.
+-The optional argument
+-.B \-a
+-causes an entry to be generated
+-for each file.
+-Absence of either causes an entry to be generated for
+-each directory only.
+-.PP
+-A file which has two links to it is only counted once.
+-.SH BUGS
+-Non-directories
+-given as arguments (not under
+-.B \-a
+-option) are not listed.
+-.br
+-If there are too many distinct linked files,
+-.I du
+-counts the excess files multiply.
+//GO.SYSIN DD du.1
+echo dump.1m
+sed 's/.//' >dump.1m <<'//GO.SYSIN DD dump.1m'
+-.TH DUMP 1M 
+-.SH NAME
+-dump \- incremental file system dump
+-.SH SYNOPSIS
+-.B dump
+-[ key [ argument ... ] filesystem ]
+-.SH DESCRIPTION
+-.I Dump
+-copies to magnetic tape all files
+-changed after a certain date
+-in the
+-.I filesystem.
+-The
+-.I key
+-specifies the date and other options about the dump.
+-.I Key
+-consists of characters from
+-the set
+-.B 0123456789fusd.
+-.TP 5
+-.B  f
+-Place the dump on the next 
+-.I argument 
+-file
+-instead of the tape.
+-.TP 5
+-.B  u
+-If the dump completes successfully,
+-write the date of the beginning of the dump on
+-file `/etc/ddate'.
+-This file records a separate date for
+-each filesystem and each dump level.
+-.TP 5
+-.B  0\-9
+-This number is the `dump level'.
+-All files modified since the last date stored
+-in the file `/etc/ddate' for
+-the same filesystem at lesser levels
+-will be dumped.
+-If no date is determined by the level,
+-the beginning of time is assumed;
+-thus the option
+-.B 0
+-causes the entire filesystem to be dumped.
+-.TP 5
+-.B  s
+-The size of the dump tape is specified in feet.
+-The number of feet is taken from the next
+-.I argument.
+-When the specified size is reached,
+-the dump will wait for reels to be changed.
+-The default size is 2300 feet.
+-.TP 5
+-.B d
+-The density of the tape, expressed in BPI,
+-is taken from the next
+-.I argument.
+-This is used in calculating the amount of tape
+-used per write. The default is 1600.
+-.PP
+-.DT
+-If no arguments are given,
+-the
+-.I key
+-is assumed to be
+-.B 9u
+-and a default file system is dumped
+-to the default tape.
+-.PP
+-Now a short suggestion on how
+-perform dumps.
+-Start with a full level 0 dump
+-.PP
+-      dump 0u
+-.PP
+-Next,
+-periodic level 9 dumps should be made on an
+-exponential progression of tapes.
+-(Sometimes called Tower of Hanoi \- 1 2 1 3 1 2 1 4 ...
+-tape 1 used every other time,
+-tape 2 used every fourth,
+-tape 3 used every eighth, etc.)
+-.PP
+-      dump 9u
+-.PP
+-When the level 9 incremental approaches a full
+-tape (about 78000 blocks at 1600 BPI blocked 20),
+-a level 1 dump should be made.
+-.PP
+-      dump 1u
+-.PP
+-After this,
+-the exponential series should progress as uninterrupted.
+-These level 9 dumps are based on the level 1 dump which
+-is based on the level 0 full dump.
+-This progression of levels of dump can be carried
+-as far as desired.
+-.SH FILES
+-default filesystem and tape vary with installation.
+-.br
+-/etc/ddate: record dump dates of filesystem/level.
+-.SH "SEE ALSO"
+-restor(1), dump(5), dumpdir(1)
+-.SH DIAGNOSTICS
+-If the dump requires more than one tape,
+-it will ask you to change tapes.
+-Reply with a new-line when this has been done.
+-.SH BUGS
+-Sizes are based on 1600 BPI blocked tape.
+-The raw magtape device has to be used to
+-approach these densities.
+-Read errors on the filesystem are ignored.
+-Write errors on the magtape are usually fatal.
+//GO.SYSIN DD dump.1m
+echo dumpdir.1m
+sed 's/.//' >dumpdir.1m <<'//GO.SYSIN DD dumpdir.1m'
+-.TH DUMPDIR 1M 
+-.SH NAME
+-dumpdir \- print the names of files on a dump tape
+-.SH SYNOPSIS
+-.I dumpdir
+-[
+-.B f
+-filename ]
+-.SH DESCRIPTION
+-.I Dumpdir
+-is used to read magtapes dumped with the
+-.I dump
+-command and list the names and inode numbers
+-of all the files and directories on the tape.
+-.PP
+-The
+-.B f
+-option causes
+-.I filename
+-as the name of the tape instead
+-of the default.
+-.SH FILES
+-default tape unit varies with installation
+-.br
+-rst*
+-.SH "SEE ALSO"
+-dump(1), restor(1)
+-.SH DIAGNOSTICS
+-If the dump extends over more than one tape,
+-it may ask you to change tapes.
+-Reply with a new-line when the next tape has been mounted.
+-.SH BUGS
+-There is redundant information on the tape
+-that could be used in case of tape reading problems.
+-Unfortunately,
+-.I dumpdir
+-doesn't use it.
+//GO.SYSIN DD dumpdir.1m
+echo echo.1
+sed 's/.//' >echo.1 <<'//GO.SYSIN DD echo.1'
+-.TH ECHO 1 
+-.SH NAME
+-echo \- echo arguments 
+-.SH SYNOPSIS
+-.B echo
+-[
+-.B \-n
+-]
+-[ arg ] ...
+-.SH DESCRIPTION
+-.I Echo
+-writes its arguments separated by blanks and terminated by
+-a newline on the standard output.
+-If the flag
+-.B \-n
+-is used,
+-no newline is added to the output.
+-.PP
+-.I Echo
+-is useful for producing diagnostics in
+-shell programs and for writing constant data on pipes.
+-To send diagnostics to the standard error file, do
+-`echo ... 1>&2'.
+//GO.SYSIN DD echo.1
+echo ed.1
+sed 's/.//' >ed.1 <<'//GO.SYSIN DD ed.1'
+-.TH ED 1 
+-.if t .ds q \(aa
+-.if n .ds q '
+-.SH NAME
+-ed \- text editor
+-.SH SYNOPSIS
+-.B ed
+-[
+-.B \-
+-] [
+-.B \-x
+-] [ name ]
+-.SH DESCRIPTION
+-.I Ed
+-is the standard text editor.
+-.PP
+-If a
+-.I name
+-argument is given,
+-.I ed
+-simulates an
+-.I e
+-command (see below)\| on the named file; that is to say,
+-the file is read into
+-.I ed's
+-buffer so that it can be edited.
+-If 
+-.B \-x
+-is present, an
+-.I x
+-command is simulated first to handle an encrypted file.
+-The optional
+-.B \-
+-suppresses the printing
+-of character counts by
+-.I e,
+-.I r,
+-and
+-.I w
+-commands.
+-.PP
+-.I Ed
+-operates on a copy of any file it is editing; changes made
+-in the copy have no effect on the file until a
+-.IR w ""
+-(write)\|
+-command is given.
+-The copy of the text being edited resides
+-in a temporary file called the 
+-.IR buffer .
+-.PP
+-Commands to
+-.I ed
+-have a simple and regular structure: zero or
+-more
+-.I addresses
+-followed by a single character
+-.I command,
+-possibly
+-followed by parameters to the command.
+-These addresses specify one or more lines in the buffer.
+-Missing addresses are supplied by default.
+-.PP
+-In general, only one command may appear on a line.
+-Certain commands allow the 
+-addition of text to the buffer.
+-While
+-.I ed
+-is accepting text, it is said
+-to be in
+-.I  "input mode."
+-In this mode, no commands are recognized;
+-all input is merely collected.
+-Input mode is left by typing a period `\fB.\fR' alone at the
+-beginning of a line.
+-.PP
+-.I Ed
+-supports a limited form of
+-.I "regular expression"
+-notation.
+-A regular expression specifies
+-a set of strings of characters.
+-A member of this set of strings is said to be
+-.I matched
+-by the regular expression.
+-In the following specification for regular expressions
+-the word `character' means any character but newline.
+-.IP 1.
+-Any character except a special character
+-matches itself.
+-Special characters are
+-the regular expression delimiter plus
+-.RB \e\|[\| .
+-and sometimes ^\|*\|$.
+-.IP 2.
+-A
+-.B .
+-matches any character.
+-.IP 3.
+-A \e followed by any character except a digit or (\|) matches that character.
+-.IP 4.
+-A nonempty string
+-.I s
+-bracketed
+-.RI [ \|s\| ]
+-(or
+-.RI [^ s\| ])
+-matches any character in (or not in)
+-.I s.
+-In 
+-.I s,
+-\e has no special meaning, and ] may only appear as
+-the first letter.
+-A substring 
+-.I a\-b,
+-with
+-.I a
+-and
+-.I b
+-in ascending ASCII order, stands for the inclusive
+-range of ASCII characters.
+-.IP 5.
+-A regular expression of form 1-4 followed by * matches a sequence of
+-0 or more matches of the regular expression.
+-.IP 6.
+-A regular expression,
+-.I x,
+-of form 1-8, bracketed
+-.RI \e( \|x\| \e)
+-matches what
+-.I x
+-matches.
+-.IP 7.
+-A \e followed by a digit 
+-.I n
+-matches a copy of the string that the
+-bracketed regular expression beginning with the
+-.IR n th
+-\e( matched.
+-.IP 8.
+-A regular expression of form 1-8,
+-.I x,
+-followed by a regular expression of form 1-7,
+-.I y
+-matches a match for
+-.I x
+-followed by a match for
+-.I y,
+-with the
+-.I x
+-match being as long as possible while still permitting a
+-.I y
+-match.
+-.IP 9.
+-A regular expression of form 1-8 preceded by ^
+-(or followed by $), is constrained to matches that
+-begin at the left (or end at the right) end of a line.
+-.IP 10.
+-A regular expression of form 1-9 picks out the
+-longest among the leftmost matches in a line.
+-.IP 11.
+-An empty regular expression stands for a copy of the
+-last regular expression encountered.
+-.PP
+-Regular expressions are used in addresses to specify
+-lines and in one command
+-(see
+-.I s
+-below)\|
+-to specify a portion of a line which is to be replaced.
+-If it is desired to use one of
+-the regular expression metacharacters as an ordinary
+-character, that character may be preceded by `\e'.
+-This also applies to the character bounding the regular
+-expression (often `/')\| and to `\e' itself.
+-.PP
+-To understand addressing in
+-.I ed
+-it is necessary to know that at any time there is a
+-.I  "current line."
+-Generally speaking, the current line is
+-the last line affected by a command; however,
+-the exact effect on the current line
+-is discussed under the description of
+-the command.
+-Addresses are constructed as follows.
+-.TP
+-1.
+-The character `\fB.\fR' addresses the current line.
+-.TP
+-2.
+-The character `$' addresses the last line of the buffer.
+-.TP
+-3.
+-A decimal number
+-.I n
+-addresses the
+-.IR n -th
+-line of the buffer.
+-.TP
+-4.
+-`\(fm\fIx\fR' addresses the line marked with the name
+-.IR x ,
+-which must be a lower-case letter.
+-Lines are marked with the
+-.I k
+-command described below.
+-.TP
+-5.
+-A regular expression enclosed in slashes `/' addresses
+-the line found by searching forward from the current line
+-and stopping at the first line containing a
+-string that matches the regular expression.
+-If necessary the search wraps around to the beginning of the
+-buffer.
+-.TP
+-6.
+-A regular expression enclosed in queries `?' addresses
+-the line found by searching backward from the current line
+-and stopping at the first line containing
+-a string that matches the regular expression.
+-If necessary
+-the search wraps around to the end of the buffer.
+-.TP
+-7.
+-An address followed by a plus sign `+'
+-or a minus sign `\-' followed by a decimal number specifies that address plus
+-(resp. minus)\| the indicated number of lines.
+-The plus sign may be omitted.
+-.TP
+-8.
+-If an address begins with `+' or `\-'
+-the addition or subtraction is taken with respect to the current line;
+-e.g. `\-5' is understood to mean `\fB.\fR\-5'.
+-.TP
+-9.
+-If an address ends with `+' or `\-',
+-then 1 is added (resp. subtracted).
+-As a consequence of this rule and rule 8,
+-the address `\-' refers to the line before the current line.
+-Moreover,
+-trailing
+-`+' and `\-' characters
+-have cumulative effect, so `\-\-' refers to the current
+-line less 2.
+-.TP
+-10.
+-To maintain compatibility with earlier versions of the editor,
+-the character `^' in addresses is 
+-equivalent to `\-'.
+-.PP
+-Commands may require zero, one, or two addresses.
+-Commands which require no addresses regard the presence
+-of an address as an error.
+-Commands which accept one or two addresses
+-assume default addresses when insufficient are given.
+-If more addresses are given than such a command requires,
+-the last one or two (depending on what is accepted)\| are used.
+-.PP
+-Addresses are separated from each other typically by a comma
+-`\fB,\fR'.
+-They may also be separated by a semicolon
+-`\fB;\fR'.
+-In this case the current line `\fB.\fR' is set to
+-the previous address before the next address is interpreted.
+-This feature can be used to determine the starting
+-line for forward and backward searches (`/', `?')\|.
+-The second address of any two-address sequence
+-must correspond to a line following the line corresponding to the first address.
+-.PP
+-In the following list of
+-.I ed
+-commands, the default addresses
+-are shown in parentheses.
+-The parentheses are not part of
+-the address, but are used to show that the given addresses are
+-the default.
+-.PP
+-As mentioned, it is generally illegal for more than one
+-command to appear on a line.
+-However, most commands may be suffixed by `p'
+-or by `l', in which case
+-the current line is either
+-printed or listed respectively
+-in the way discussed below.
+-.TP 5
+-.RB (\| .\| )\|a
+-.br
+-.ns
+-.TP 5
+-<text>
+-.br
+-.ns
+-.TP 5
+-.B .
+-.br
+-The append command reads the given text
+-and appends it after the addressed line.
+-`\fB.\fR' is left
+-on the last line input, if there
+-were any, otherwise at the addressed line.
+-Address `0' is legal for this command; text is placed
+-at the beginning of the buffer.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|c
+-.br
+-.ns
+-.TP 5
+-<text>
+-.br
+-.ns
+-.TP 5
+-.B .
+-.br
+-The change
+-command deletes the addressed lines, then accepts input
+-text which replaces these lines.
+-`\fB.\fR' is left at the last line input; if there were none,
+-it is left at the line preceding the deleted lines.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|d
+-The delete command deletes the addressed lines from the buffer.
+-The line originally after the last line deleted becomes the current line;
+-if the lines deleted were originally at the end,
+-the new last line becomes the current line.
+-.TP 5
+-e filename
+-The edit
+-command causes the entire contents of the buffer to be deleted,
+-and then the named file to be read in.
+-`\fB.\fR' is set to the last line of the buffer.
+-The number of characters read is typed.
+-`filename' is remembered for possible use as a default file name
+-in a subsequent
+-.I r
+-or
+-.I w
+-command.
+-If `filename' is missing, the remembered name is used.
+-.TP 5
+-E filename
+-This command is the same as
+-.I e,
+-except that no diagnostic results when no
+-.I w
+-has been given since the last buffer alteration.
+-.TP 5
+-f filename
+-The filename command prints the currently remembered file name.
+-If `filename' is given,
+-the currently remembered file name is changed to `filename'.
+-.TP 5
+-(1,$)\|g/regular expression/command list
+-In the global
+-command, the first step is to mark every line which matches
+-the given regular expression.
+-Then for every such line, the
+-given command list is executed with `\fB.\fR' initially set to that line.
+-A single command or the first of multiple commands
+-appears on the same line with the global command.
+-All lines of a multi-line list except the last line must be ended with `\e'.
+-.I A,
+-.I i,
+-and
+-.I c
+-commands and associated input are permitted;
+-the `\fB.\fR' terminating input mode may be omitted if it would be on the
+-last line of the command list.
+-The commands
+-.I g
+-and
+-.I v
+-are not permitted in the command list.
+-.TP 5
+-.RB (\| .\| )\|i
+-.ns
+-.TP 5
+-<text>
+-.br
+-.ns
+-.TP 5
+-.B .
+-.br
+-This command inserts the given text before the addressed line.
+-`\fB.\fR' is left at the last line input, or, if there were none,
+-at the line before the addressed line.
+-This command differs from the
+-.I a
+-command only in the placement of the
+-text.
+-.TP 5
+-.RB (\| .\| ,\  . +1)\|j
+-This command joins the addressed lines into a single line;
+-intermediate newlines simply disappear.
+-`\fB.\fR' is left at the resulting line.
+-.TP 5
+-( \fB. \fR)\|k\fIx\fR
+-The mark command marks the addressed line with
+-name
+-.I x,
+-which must be a lower-case letter.
+-The address form `\(fm\fIx\fR' then addresses this line.
+-.ne 2.5
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|l
+-The list command
+-prints the addressed lines in an unambiguous way:
+-non-graphic characters are
+-printed in two-digit octal,
+-and long lines are folded.
+-The
+-.I l
+-command may be placed on the same line after any non-i/o
+-command.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|m\fIa
+-The move command repositions the addressed lines after the line
+-addressed by
+-.IR a .
+-The last of the moved lines becomes the current line.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|p
+-The print command prints the addressed lines.
+-`\fB.\fR'
+-is left at the last line printed.
+-The
+-.I p
+-command
+-may
+-be placed on the same line after any non-i/o command.
+-.TP
+-.RB (\| .\| ,\  .\| )\|P
+-This command is a synonym for
+-.I p.
+-.TP 5
+-q
+-The quit command causes
+-.I ed
+-to exit.
+-No automatic write
+-of a file is done.
+-.TP 5
+-Q
+-This command is the same as
+-.I q,
+-except that no diagnostic results when no
+-.I w
+-has been given since the last buffer alteration.
+-.TP 5
+-($)\|r filename
+-The read command
+-reads in the given file after the addressed line.
+-If no file name is given,
+-the remembered file name, if any, is used
+-(see
+-.I e
+-and
+-.I f
+-commands)\|.
+-The file name is remembered if there was no
+-remembered file name already.
+-Address `0' is legal for
+-.I r
+-and causes the
+-file to be read at the beginning of the buffer.
+-If the read is successful, the number of characters
+-read is typed.
+-`\fB.\fR' is left at the last line read in from the file.
+-.TP 5
+-(\| \fB.\fR\|, \fB.\fR\|)\|s/regular expression/replacement/       or,
+-.br
+-.ns
+-.TP 5
+-(\| \fB.\fR\|, \fB.\fR\|)\|s/regular expression/replacement/g
+-The substitute command searches each addressed
+-line for an occurrence of the specified regular expression.
+-On each line in which a match is found,
+-all matched strings are replaced by the replacement specified,
+-if the global replacement indicator `g' appears after the command.
+-If the global indicator does not appear, only the first occurrence
+-of the matched string is replaced.
+-It is an error for the substitution to fail on all addressed lines.
+-Any character other than space or new-line
+-may be used instead of `/' to delimit the regular expression
+-and the replacement.
+-`\fB.\fR' is left at the last line substituted.
+-.IP
+-An ampersand `&' appearing in the replacement
+-is replaced by the string matching the regular expression.
+-The special meaning of `&' in this context may be
+-suppressed by preceding it by `\e'.
+-The characters
+-.I `\|\en'
+-where
+-.I n
+-is a digit,
+-are replaced by the text matched by the
+-.IR n -th
+-regular subexpression
+-enclosed between `\e(' and `\e)'.
+-When
+-nested, parenthesized subexpressions
+-are present,
+-.I n
+-is determined by counting occurrences of `\e(' starting from the left.
+-.IP
+-Lines may be split by substituting new-line characters into them.
+-The new-line in the
+-replacement string
+-must be escaped by preceding it by `\e'.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|t\|\fIa
+-This command acts just like the
+-.I m
+-command, except that a copy of the addressed lines is placed
+-after address
+-.I a
+-(which may be 0).
+-`\fB.\fR' is left on the last line of the copy.
+-.TP 5
+-.RB (\| .\| ,\  .\| )\|u
+-The undo command restores the preceding contents
+-of the current line, which must be the last line
+-in which a substitution was made.
+-.TP 5
+-(1, $)\|v/regular expression/command list
+-This command is the same as the global command
+-.I g
+-except that the command list is executed
+-.I g
+-with `\fB.\fR' initially set to every line
+-.I except
+-those
+-matching the regular expression.
+-.TP 5
+-(1, $)\|w filename
+-.br
+-The write command writes the addressed lines onto
+-the given file.
+-If the file does not exist,
+-it is created mode 666 (readable and writable by everyone)\|.
+-The file name is remembered if there was no 
+-remembered file name already.
+-If no file name is given,
+-the remembered file name, if any, is used
+-(see
+-.I e
+-and
+-.I f
+-commands)\|.
+-`\fB.\fR' is unchanged.
+-If the command is successful, the number of characters written is
+-printed.
+-.TP
+-(1,$)W filename
+-This command is the same as
+-.I w,
+-except that the addressed lines are appended to the file.
+-.TP 5
+-x
+-A key string is demanded from the standard input.
+-Later
+-.I r, e
+-and
+-.I w
+-commands will encrypt and decrypt the text 
+-with this key by the algorithm of 
+-.IR crypt (1).
+-An explicitly empty key turns off encryption.
+-.TP 5
+-($)\|=
+-The line number of the addressed line is typed.
+-`\fB.\fR' is unchanged by this command.
+-.TP 5
+-!<shell command>
+-The remainder of the line after the `!' is sent
+-to
+-.IR sh (1)
+-to be interpreted as a command.
+-.RB ` . '
+-is unchanged.
+-.TP 5
+-.RB (\| . +1)\|<newline>
+-An address alone on a line causes the addressed line to be printed.
+-A blank line alone is equivalent to `.+1p'; it is useful
+-for stepping through text.
+-.PP
+-If an interrupt signal (ASCII DEL)\| is sent,
+-.I ed
+-prints a `?' and returns to its command level.
+-.PP
+-Some size limitations:
+-512 characters per line,
+-256 characters per global command list,
+-64 characters per file name,
+-and 128K characters in the temporary file.
+-The limit on the number of lines depends on the amount of core:
+-each line takes 1 word.
+-.PP
+-When reading a file,
+-.I ed
+-discards ASCII NUL characters
+-and all characters after the last newline.
+-It refuses to read files containing non-ASCII characters.
+-.SH FILES
+-/tmp/e*
+-.br
+-ed.hup: work is saved here if terminal hangs up
+-.SH "SEE ALSO"
+-B. W. Kernighan,
+-.I
+-A Tutorial Introduction to the ED Text Editor
+-.br
+-B. W. Kernighan,
+-.I Advanced editing on UNIX
+-.br
+-sed(1), crypt(1)
+-.SH DIAGNOSTICS
+-`?name' for inaccessible file;
+-`?' for
+-errors in commands;
+-`?TMP' for temporary file overflow.
+-.PP
+-To protect against throwing away valuable work,
+-a
+-.I q
+-or
+-.I e
+-command is considered to be in error, unless a
+-.I w
+-has occurred since the last buffer change.
+-A second
+-.I q
+-or
+-.I e
+-will be obeyed regardless.
+-.SH BUGS
+-The 
+-.I l
+-command mishandles DEL.
+-.br
+-A
+-.I !
+-command cannot be subject to a
+-.I g
+-command.
+-.br
+-Because 0 is an illegal address for a
+-.I w
+-command, it is not possible to
+-create an empty file with
+-.I ed.
+//GO.SYSIN DD ed.1
+echo eqn.1
+sed 's/.//' >eqn.1 <<'//GO.SYSIN DD eqn.1'
+-.EQ
+-delim $$
+-.EN
+-.TH EQN 1 2/22/74
+-.SH NAME
+-eqn, neqn, checkeq  \-  typeset mathematics
+-.SH SYNOPSIS
+-.B eqn
+-[
+-.BR \-d xy
+-] [
+-.BR \-p n
+-] [
+-.BR \-s n
+-] [
+-.BR \-f n
+-] 
+-[ file ] ...
+-.br
+-.B checkeq
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Eqn
+-is a
+-troff(1)
+-preprocessor
+-for typesetting mathematics
+-on a Graphic Systems phototypesetter,
+-.I neqn
+-on terminals.
+-Usage is almost always
+-.PP
+-      eqn file ... | troff
+-.br
+-      neqn file ... | nroff
+-.PP
+-If no files are specified, 
+-these programs
+-reads from the standard input.
+-A line beginning with `.EQ' marks the start of an equation;
+-the end of an equation
+-is marked by a line beginning with `.EN'.
+-Neither of these lines is altered,
+-so they may be defined in macro packages
+-to get
+-centering, numbering, etc.
+-It is also possible to set two characters as `delimiters';
+-subsequent text between delimiters is also treated as
+-.ul
+-eqn
+-input.
+-Delimiters may be set to characters
+-.I x
+-and
+-.I y
+-with the command-line argument
+-.BI \-d xy
+-or (more commonly) with
+-`delim
+-.IR xy '
+-between .EQ and .EN.
+-The left and right delimiters may be identical.
+-Delimiters are turned off by `delim off'.
+-All text that is neither between delimiters nor between .EQ and .EN
+-is passed through untouched.
+-.PP
+-The program
+-.I checkeq
+-reports missing or unbalanced delimiters and .EQ/.EN pairs.
+-.PP
+-Tokens within
+-.I eqn
+-are separated by
+-spaces, tabs, newlines, braces, double quotes,
+-tildes or circumflexes.
+-Braces {} are used for grouping;
+-generally speaking,
+-anywhere a single character like
+-.I x
+-could appear, a complicated construction
+-enclosed in braces may be used instead.
+-Tilde ~ represents a full space in the output,
+-circumflex ^ half as much.
+-.PP
+-.vs 13p
+-Subscripts and superscripts are produced with the keywords
+-.B sub
+-and
+-.B sup.
+-Thus
+-.I "x sub i" 
+-makes
+-$x sub i$, 
+-.I "a sub i sup 2"
+-produces
+-$a sub i sup 2$,
+-and
+-.I "e sup {x sup 2 + y sup 2}"
+-gives
+-$e sup {x sup 2 + y sup 2}$.
+-.PP
+-Fractions are made with
+-.BR over :
+-.I "a over b"
+-yields $a over b$.
+-.PP
+-.B sqrt
+-makes square roots:
+-.I "1 over sqrt {ax sup 2 +bx+c}"
+-results in
+-$1 over sqrt {ax sup 2 +bx+c}$ .
+-.PP
+-The keywords
+-.B from
+-and
+-.B to
+-introduce lower and upper
+-limits on arbitrary things:
+-$lim from {n-> inf} sum from 0 to n x sub i$
+-is made with
+-.I "lim from {n\-> inf } sum from 0 to n x sub i."
+-.PP
+-Left and right brackets, braces, etc., of the right height are made with
+-.B left
+-and
+-.B right:
+-.I "left [ x sup 2 + y sup 2 over alpha right ] ~=~1"
+-produces
+-$left [ x sup 2 + y sup 2 over alpha right ] ~=~1$.
+-The
+-.B right
+-clause is optional.
+-Legal characters after 
+-.B left
+-and
+-.B right
+-are braces, brackets, bars,
+-.B c
+-and
+-.B f
+-for ceiling and floor,
+-and "" for nothing at all (useful for a right-side-only bracket).
+-.PP
+-Vertical piles of things are made with 
+-.BR pile ,
+-.BR lpile ,
+-.BR cpile ,
+-and
+-.BR rpile :
+-.I "pile {a above b above c}"
+-produces
+-$pile {a above b above c}$.
+-There can be an arbitrary number of elements in a pile.
+-.B lpile
+-left-justifies,
+-.B pile
+-and
+-.B cpile
+-center, with different vertical spacing,
+-and 
+-.B rpile
+-right justifies.
+-.PP
+-Matrices are made with
+-.BR matrix :
+-.I "matrix { lcol { x sub i above y sub 2 } ccol { 1 above 2 } }"
+-produces
+-$matrix { lcol { x sub i above y sub 2 } ccol { 1 above 2 } }$.
+-In addition, there is
+-.B rcol
+-for a right-justified column.
+-.PP
+-.vs 12p
+-Diacritical marks are made with
+-.BR dot ,
+-.BR dotdot ,
+-.BR hat ,
+-.BR tilde ,
+-.BR bar ,
+-.BR vec ,
+-.BR dyad ,
+-and
+-.BR under :
+-.I "x dot = f(t) bar"
+-is
+-$x dot = f(t) bar$,
+-.I "y dotdot bar ~=~ n under"
+-is
+-$y dotdot bar ~=~ n under$,
+-and
+-.I "x vec ~=~ y dyad"
+-is
+-$x vec ~=~ y dyad$.
+-.PP
+-Sizes and font can be changed with
+-.B size
+-.I n
+-or
+-.B size
+-.BI \(+- n,
+-.BR roman ,
+-.BR italic ,
+-.BR bold ,
+-and
+-.BR font
+-.I n.
+-Size and fonts can be changed globally in a document by
+-.B gsize
+-.I n
+-and
+-.B gfont
+-.IR n ,
+-or by the command-line arguments
+-.BI \-s n
+-and
+-.BI \-f n.
+-.PP
+-Normally subscripts and superscripts are reduced by
+-3 point sizes from the previous size;
+-this may be changed by the command-line argument
+-.BI \-p n.
+-.PP
+-Successive display arguments can be lined up.
+-Place
+-.B mark
+-before the desired lineup point in the first equation;
+-place
+-.B lineup
+-at the place that is to line up vertically in subsequent equations.
+-.PP
+-Shorthands may be defined
+-or existing keywords redefined with
+-.BI define :
+-.I "define thing % replacement %"
+-defines a new token called
+-.I thing
+-which will be replaced by
+-.I replacement
+-whenever it appears thereafter.
+-The 
+-.I %
+-may be any character that does not occur in
+-.I replacement.
+-.PP
+-Keywords like 
+-.I sum
+-.EQ
+-( sum )
+-.EN
+-.I int
+-.EQ
+-( int )
+-.EN
+-.I inf
+-.EQ
+-( inf )
+-.EN
+-and shorthands like
+->=
+-.EQ
+-(>=)
+-.EN
+-\->
+-.EQ
+-(->),
+-.EN
+-and
+-!=
+-.EQ
+-( != )
+-.EN
+-are recognized.
+-Greek letters are spelled out in the desired case, as in
+-.I alpha
+-or
+-.I GAMMA.
+-Mathematical words like sin, cos, log are made Roman automatically.
+-.IR Troff (1)
+-four-character escapes like \e(bs (\(bs)
+-can be used anywhere.
+-Strings enclosed in double quotes "..."
+-are passed through untouched;
+-this permits keywords to be entered as text,
+-and can be used to communicate
+-with 
+-.I troff
+-when all else fails.
+-.SH "SEE ALSO"
+-.PP
+-troff(1), tbl(1), ms(7), eqnchar(7)
+-.br
+-B. W. Kernighan and L. L. Cherry,
+-.ul
+-Typesetting Mathematics\(emUser's Guide
+-.br
+-J. F. Ossanna,
+-.ul
+-NROFF/TROFF User's Manual
+-.SH BUGS
+-.PP
+-To embolden digits, parens, etc.,
+-it is necessary to quote them,
+-as in `bold "12.3"'.
+//GO.SYSIN DD eqn.1
+echo expr.1
+sed 's/.//' >expr.1 <<'//GO.SYSIN DD expr.1'
+-.TH EXPR 1 
+-.SH NAME
+-expr \- evaluate arguments as an expression
+-.SH SYNOPSIS
+-.B expr
+-arg
+-.B .\|.\|.
+-.SH DESCRIPTION
+-The arguments are taken as an expression.
+-After evaluation, the result is written on the standard output.
+-Each token of the expression is a separate argument.
+-.PP
+-The operators and keywords are listed below.
+-The list is in order of increasing precedence,
+-with equal precedence operators grouped.
+-.TP
+-.I expr | expr
+-yields the first
+-.I expr
+-if it is neither null nor `0', otherwise
+-yields the second
+-.I expr.
+-.TP
+-.I expr & expr
+-yields the first
+-.I expr
+-if neither
+-.I expr
+-is null or `0', otherwise yields `0'.
+-.TP
+-.I expr relop expr
+-where
+-.I relop is one of
+-< <= = != >= >,
+-yields `1' if the indicated comparison is true, `0' if false.
+-The comparison is numeric if both
+-.I expr
+-are integers, otherwise lexicographic.
+-.TP
+-.IR expr " + " expr
+-.br
+-.IR expr " - " expr
+-.br
+-addition or subtraction of the arguments.
+-.TP
+-.IR expr " * " expr
+-.br
+-.IR expr " / " expr
+-.br
+-.IR expr " % " expr
+-.br
+-multiplication, division, or remainder of the arguments.
+-.TP
+-.IR expr " : " expr
+-The matching operator compares the string first argument
+-with the regular expression second argument;
+-regular expression syntax is the same as that of
+-.IR ed (1).
+-The
+-\fB\\(\|.\|.\|.\|\\)\fP
+-pattern symbols can be used to select a portion of the
+-first argument.
+-Otherwise,
+-the matching operator yields the number of characters matched
+-(`0' on failure).
+-.TP
+-.RI ( " expr " )
+-parentheses for grouping.
+-.PP
+-Examples:
+-.PP
+-To add 1 to the Shell variable
+-.IR a :
+-.IP
+-a=\`expr $a + 1\`
+-.PP
+-To find the filename part (least significant part)
+-of the pathname stored in variable
+-.I a,
+-which may or may not contain `/':
+-.IP
+-expr $a : \'.*/\e(\^.*\e)\' \'\^|\' $a
+-.LP
+-Note the quoted Shell metacharacters.
+-.SH "SEE ALSO"
+-ed(1), sh(1), test(1)
+-.SH DIAGNOSTICS
+-.I Expr
+-returns the following exit codes:
+-.PP
+-      0       if the expression is neither null nor `0',
+-.br
+-      1       if the expression
+-is null or `0',
+-.br
+-      2       for invalid expressions.
+//GO.SYSIN DD expr.1
+echo f77.1
+sed 's/.//' >f77.1 <<'//GO.SYSIN DD f77.1'
+-.TH F77 1
+-.SH NAME
+-f77 \- Fortran 77 compiler
+-.SH SYNOPSIS
+-.B f77
+-[ option ] ... file ...
+-.SH DESCRIPTION
+-.I F77
+-is the UNIX Fortran 77 compiler.
+-It accepts several types of arguments:
+-.PP
+-Arguments whose names end with `.f' are taken to be
+-Fortran 77 source programs;
+-they are compiled, and
+-each object program is left on the file in the current directory
+-whose name is that of the source with `.o' substituted
+-for '.f'.
+-.PP
+-Arguments whose names end with `.r' or `.e' are taken to be Ratfor or EFL
+-source programs, respectively; these are first transformed by the
+-appropriate preprocessor, then compiled by f77.
+-.PP
+-In the same way,
+-arguments whose names end with `.c' or `.s' are taken to be C or assembly source programs
+-and are compiled or assembled, producing a `.o' file.
+-.PP
+-The following options have the same meaning as in
+-.IR cc (1).
+-See
+-.IR ld (1)
+-for load-time options.
+-.TP
+-.B \-c
+-Suppress loading and produce `.o' files for each source 
+-file.
+-.TP
+-.B \-p
+-Prepare object files for profiling, see
+-.IR  prof (1).
+-.TP
+-.SM
+-.B \-O
+-Invoke an
+-object-code optimizer.
+-.TP
+-.SM
+-.B \-S
+-Compile the named programs, and leave the
+-assembler-language output on corresponding files suffixed `.s'.
+-(No `.o' is created.).
+-.TP
+-.B \-f
+-Use a floating point interpreter (for PDP11's that lack
+-11/70-style floating point).
+-.TP
+-.BR \-o " output"
+-Name the final output file
+-.I output
+-instead of `a.out'.
+-.PP
+-The following options are peculiar to
+-.IR f77 .
+-.TP
+-.SM
+-.BR \-onetrip
+-Compile DO loops that are performed at least once if reached.
+-(Fortran 77 DO loops are not performed at all if the upper limit is smaller than the lower limit.)
+-.TP
+-.BR \-u
+-Make the default type of a variable `undefined' rather than using the default Fortran rules.
+-.TP
+-.BR \-C
+-Compile code to check that subscripts are within declared array bounds.
+-.TP
+-.BR \-w
+-Suppress all warning messages.
+-If the option is `\-w66', only Fortran 66 compatibility warnings are suppressed.
+-.TP
+-.BR \-F
+-Apply EFL and Ratfor preprocessor to relevant files, put the result in the file
+-with the suffix changed to `.f', but do not compile.
+-.TP
+-.BR \-m
+-Apply the M4 preprocessor to each `.r' or `.e' file before transforming
+-it with the Ratfor or EFL preprocessor.
+-.TP
+-.TP
+-.BI \-E x
+-Use the string
+-.I x
+-as an EFL option in processing `.e' files.
+-.TP
+-.BI \-R x
+-Use the string 
+-.I x
+-as a Ratfor option in processing `.r' files.
+-.PP
+-Other arguments
+-are taken
+-to be either loader option arguments, or F77-compatible
+-object programs, typically produced by an earlier
+-run,
+-or perhaps libraries of F77-compatible routines.
+-These programs, together with the results of any
+-compilations specified, are loaded (in the order
+-given) to produce an executable program with name
+-`a.out'.
+-.SH FILES
+-.nf
+-.ta \w'/usr/lib/f77rt0.o 'u
+-file.[fresc]  input file
+-file.o        object file
+-a.out loaded output
+-./fort[pid].? temporary
+-/usr/lib/f77pass1     compiler
+-/lib/c1       pass 2
+-/lib/c2       optional optimizer
+-/usr/lib/libF77.a     intrinsic function library
+-/usr/lib/libI77.a     Fortran I/O library
+-/lib/libc.a   C library, see section 3
+-.fi
+-.SH "SEE ALSO"
+-S. I. Feldman,
+-P. J. Weinberger,
+-.I
+-A Portable Fortran 77 Compiler
+-.br
+-prof(1), cc(1), ld(1)
+-.SH DIAGNOSTICS
+-The diagnostics produced by
+-.I f77
+-itself are intended to be
+-self-explanatory.
+-Occasional messages may be produced by the loader.
+-.SH BUGS
+-The Fortran 66 subset of the language has been
+-exercised extensively;
+-the newer features have not.
+//GO.SYSIN DD f77.1
+echo factor.1
+sed 's/.//' >factor.1 <<'//GO.SYSIN DD factor.1'
+-.TH FACTOR 1 
+-.SH NAME
+-factor, primes \- factor a number, generate large primes
+-.SH SYNOPSIS
+-.B factor
+-[ number ]
+-.PP
+-.B primes
+-.SH DESCRIPTION
+-When
+-.I factor
+-is invoked without an argument, it waits for a number to be typed in.
+-If you type in a positive
+-number less than 2\u\s756\s0\d (about
+-.if n 7.2e16)
+-.if t 7.2\(mu10\u\s716\s0\d\|)
+-it will factor the number and print its prime factors; each one is printed
+-the proper number of times.
+-Then it waits for another number.
+-It exits if it encounters a zero or any non-numeric character.
+-.PP
+-If
+-.I factor
+-is invoked with an argument, it factors the number
+-as above and then exits.
+-.PP
+-Maximum time to factor is proportional to
+-.if n sqrt(n)
+-.if t \(sr\o'\fIn\fR\(rn'
+-and occurs when
+-.I n
+-is prime
+-or the square of a prime.
+-It takes 1 minute to factor a prime
+-near
+-10\u\s714\s0\d
+-on a PDP11.
+-.PP
+-When
+-.I primes
+-is invoked, it waits for a number to be typed in.
+-If you type in a positive
+-number less than 2\u\s756\s0\d
+-it will print all primes greater than or
+-equal to this number.
+-.SH DIAGNOSTICS
+-`Ouch.' for input out of range or for garbage input.
+//GO.SYSIN DD factor.1
+echo file.1
+sed 's/.//' >file.1 <<'//GO.SYSIN DD file.1'
+-.TH FILE 1 
+-.SH NAME
+-file \- determine file type
+-.SH SYNOPSIS
+-.B file
+-file ...
+-.SH DESCRIPTION
+-.I File
+-performs a series of tests on each argument
+-in an attempt to classify it.
+-If an argument appears to be ascii,
+-.I file
+-examines the first 512 bytes
+-and tries to guess its language.
+-.SH BUGS
+-It often makes mistakes.
+-In particular it often suggests that
+-command files are C programs.
+//GO.SYSIN DD file.1
+echo find.1
+sed 's/.//' >find.1 <<'//GO.SYSIN DD find.1'
+-.TH FIND 1 
+-.SH NAME
+-find \- find files
+-.SH SYNOPSIS
+-.B find
+-pathname-list  expression
+-.SH DESCRIPTION
+-.I Find
+-recursively descends
+-the directory hierarchy for
+-each pathname in the
+-.I pathname-list
+-(i.e., one or more pathnames)
+-seeking files that match a boolean
+-.I expression
+-written in the primaries given below.
+-In the descriptions, the argument
+-.I n
+-is used as a decimal integer
+-where
+-.I +n
+-means more than
+-.I n,
+-.I \-n
+-means less than
+-.I n
+-and
+-.I n
+-means exactly
+-.IR n .
+-.TP 10n
+-.BR \-name " filename"
+-True if the
+-.I filename
+-argument matches the current file name.
+-Normal
+-Shell
+-argument syntax may be used if escaped (watch out for
+-`[', `?' and `*').
+-.TP
+-.BR \-perm " onum"
+-True if the file permission flags
+-exactly
+-match the
+-octal number
+-.I onum
+-(see
+-.IR  chmod (1)).
+-If
+-.I onum
+-is prefixed by a minus sign,
+-more flag bits (017777, see
+-.IR   stat (2))
+-become significant and
+-the flags are compared:
+-.IR (flags&onum)==onum .
+-.TP
+-.BR \-type " c"
+-True if the type of the file
+-is
+-.I c,
+-where
+-.I c
+-is
+-.B "b, c, d"
+-or
+-.B f
+-for
+-block special file, character special file,
+-directory or plain file.
+-.TP
+-.BR \-links " n"
+-True if the file has
+-.I n
+-links.
+-.TP
+-.BR \-user " uname"
+-True if the file belongs to the user
+-.I uname
+-(login name or numeric user ID).
+-.TP
+-.BR \-group " gname"
+-True if the file belongs to group
+-.I gname
+-(group name or numeric group ID).
+-.TP
+-.BR \-size " n"
+-True if the file is
+-.I n
+-blocks long (512 bytes per block).
+-.TP
+-.BR \-inum " n"
+-True if the file has inode number
+-.I n.
+-.TP
+-.BR \-atime " n"
+-True if the file has been accessed in
+-.I n
+-days.
+-.TP
+-.BR \-mtime " n"
+-True if the file has been modified in
+-.I n
+-days.
+-.TP
+-.BR \-exec " command"
+-True if the executed command returns
+-a zero value as exit status.
+-The end of the command must be punctuated by an escaped
+-semicolon.
+-A command argument `{}' is replaced by the
+-current pathname.
+-.TP
+-.BR \-ok " command"
+-Like
+-.B \-exec
+-except that the generated command is written on
+-the standard output, then the standard input is read
+-and the command executed only upon response
+-.BR y .
+-.TP
+-.B  \-print
+-Always true;
+-causes the current pathname to be printed.
+-.TP
+-.BR \-newer " file"
+-True if
+-the current file has been modified more recently than the argument
+-.I file.
+-.PP
+-The primaries may be combined using the following operators
+-(in order of decreasing precedence):
+-.TP 4
+-1)
+-A parenthesized group of primaries and operators
+-(parentheses are special to the Shell and must be escaped).
+-.TP 4
+-2)
+-The negation of a primary
+-(`!' is the unary
+-.I not
+-operator).
+-.TP 4
+-3)
+-Concatenation of primaries
+-(the
+-.I and
+-operation
+-is implied by the juxtaposition of two primaries).
+-.TP 4
+-4)
+-Alternation of primaries
+-.RB "(`" \-o "' is the"
+-.I or
+-operator).
+-.SH EXAMPLE
+-To remove all files named
+-`a.out' or `*.o' that have not been accessed for a week:
+-.IP "" .2i
+-find / \\( \-name a.out \-o \-name '*.o' \\)
+-\-atime +7 \-exec rm {} \\;
+-.SH FILES
+-/etc/passwd
+-.br
+-/etc/group
+-.SH "SEE ALSO"
+-sh(1), test(1), filsys(5)
+-.SH BUGS
+-The syntax is painful.
+//GO.SYSIN DD find.1
+echo graph.1g
+sed 's/.//' >graph.1g <<'//GO.SYSIN DD graph.1g'
+-.TH GRAPH 1G 
+-.SH NAME
+-graph \- draw a graph
+-.SH SYNOPSIS
+-.B graph
+-[ option ] ...
+-.SH DESCRIPTION
+-.I Graph
+-with no options takes pairs of numbers from the
+-standard input as abscissas and
+-ordinates of a graph.
+-Successive points are connected by straight lines.
+-The graph is encoded on the standard output
+-for display by the
+-.IR  plot (1)
+-filters.
+-.PP
+-If the coordinates of a point are followed by
+-a nonnumeric string, that string is printed as a
+-label beginning on the point.
+-Labels may be surrounded with quotes "...", in
+-which case they may be empty or contain blanks
+-and numbers;
+-labels never contain newlines.
+-.PP
+-The following options are recognized,
+-each as a separate argument.
+-.TP
+-.B  \-a
+-Supply abscissas automatically (they are missing from
+-the input); spacing is given by the next
+-argument (default 1).
+-A second optional argument is the starting point for
+-automatic abscissas (default 0 or lower limit given by
+-.BR \-x ).
+-.TP
+-.B  \-b
+-Break (disconnect) the graph after each label in the input.
+-.TP
+-.B  \-c
+-Character string given by next argument
+-is default label for each point.
+-.TP
+-.B  \-g
+-Next argument is grid style,
+-0 no grid, 1 frame with ticks, 2 full grid (default).
+-.TP
+-.B  \-l
+-Next argument is label for graph.
+-.TP
+-.B  \-m
+-Next argument is mode (style)
+-of connecting lines:
+-0 disconnected, 1 connected (default).
+-Some devices give distinguishable line styles
+-for other small integers.
+-.TP
+-.B  \-s
+-Save screen, don't erase before plotting.
+-.TP
+-\fB\-x\fR [ \fBl\fR ]
+-If
+-.B l
+-is present, x axis is logarithmic.
+-Next 1 (or 2) arguments are lower (and upper)
+-.IR x ""
+-limits.
+-Third argument, if present, is grid spacing on 
+-.I x
+-axis.
+-Normally these quantities are determined automatically.
+-.TP
+-\fB\-y\fR [ \fBl\fR ]
+-Similarly for
+-.IR y .
+-.TP
+-.B  \-h
+-Next argument is fraction of space for height.
+-.TP
+-.B  \-w
+-Similarly for width.
+-.TP
+-.B  \-r
+-Next argument is fraction of space to move right before plotting.
+-.TP
+-.B  \-u
+-Similarly to move up before plotting.
+-.TP
+-.B  \-t
+-Transpose horizontal and vertical axes.
+-(Option
+-.B \-x
+-now applies to the vertical axis.)
+-.PP
+-A legend indicating grid range is produced
+-with a grid unless the
+-.B \-s
+-option is present.
+-.PP
+-If a specified lower limit exceeds the upper limit,
+-the axis
+-is reversed.
+-.SH "SEE ALSO"
+-spline(1), plot(1)
+-.SH BUGS
+-.I Graph
+-stores all points internally and drops those for which
+-there isn't room.
+-.br
+-Segments that run out of bounds are dropped, not windowed.
+-.br
+-Logarithmic axes may not be reversed.
+//GO.SYSIN DD graph.1g
+echo grep.1
+sed 's/.//' >grep.1 <<'//GO.SYSIN DD grep.1'
+-.TH GREP 1 
+-.SH NAME
+-grep, egrep, fgrep \- search a file for a pattern
+-.SH SYNOPSIS
+-.B grep
+-[ option ] ...
+-expression [ file ] ...
+-.LP
+-.B egrep 
+-[ option ] ...
+-[ expression ]
+-[ file ] ...
+-.PP
+-.B fgrep
+-[ option ] ...
+-[ strings ]
+-[ file ]
+-.SH DESCRIPTION
+-Commands of the
+-.I grep
+-family search the input
+-.I files
+-(standard input default)
+-for lines matching
+-a pattern.
+-Normally, each line found
+-is copied to the standard output;
+-unless the
+-.B \-h
+-flag is used,
+-the file name is shown if there is more than one input file.
+-.PP
+-.I Grep
+-patterns are limited regular expressions in the style of
+-.IR ed (1);
+-it uses a compact nondeterministic algorithm.
+-.I Egrep
+-patterns are full regular expressions;
+-it uses a fast deterministic algorithm that
+-sometimes needs exponential space.
+-.I Fgrep
+-patterns are fixed strings; it is fast and compact.
+-.PP
+-The following options are recognized.
+-.TP
+-.B \-v
+-All lines but those matching
+-are printed.
+-.TP
+-.B \-c
+-Only a count of matching lines is printed.
+-.TP
+-.B \-l
+-The names of files with matching lines are listed (once)
+-separated by newlines.
+-.TP
+-.B \-n
+-Each line is preceded by
+-its line number in the file.
+-.TP
+-.B \-b
+-Each line is preceded by the block number
+-on which it was found.
+-This is sometimes useful in locating
+-disk block numbers by context.
+-.TP
+-.B \-s
+-No output is produced, only status.
+-.TP
+-.B \-h
+-Do not print filename headers with output lines.
+-.TP
+-.B \-y
+-Lower case letters in the pattern will also match
+-upper case letters in the input
+-.RI ( grep
+-only).
+-.TP
+-.BI \-e " expression"
+-Same as a simple
+-.I expression 
+-argument,
+-but useful when the
+-.I expression
+-begins with a \-.
+-.TP
+-.BI \-f " file"
+-The regular expression
+-.RI ( egrep )
+-or string list
+-.RI ( fgrep ) 
+-is taken from the
+-.I file.
+-.TP
+-.B \-x
+-(Exact) only lines matched in their entirety are printed
+-.RI ( fgrep
+-only).
+-.PP
+-Care should be taken when
+-using the characters
+-$ * [ ^ | ? \' " ( ) and \e in the
+-.I expression
+-as they are
+-also meaningful to the Shell.
+-It is safest to enclose the
+-entire
+-.I expression
+-argument in single quotes \' \'.
+-.PP
+-.I Fgrep
+-searches for lines that contain one of the (newline-separated)
+-.I strings.
+-.PP
+-.I Egrep
+-accepts extended regular expressions.
+-In the following description `character' excludes
+-newline:
+-.IP
+-A \e followed by a single character
+-matches that character.
+-.IP
+-The character ^
+-($) matches the beginning (end) of a line.
+-.IP
+-A 
+-.B .
+-matches any character.
+-.IP
+-A single character not otherwise endowed with special
+-meaning matches that character.
+-.IP
+-A string enclosed in brackets [\|]
+-matches any single character from the string.
+-Ranges of ASCII character codes may be abbreviated
+-as in `a\-z0\-9'.
+-A ]
+-may occur only as the first character of the string.
+-A literal \- must be placed where it can't be
+-mistaken as a range indicator.
+-.IP
+-A regular expression followed by * (+, ?) matches a sequence
+-of 0 or more (1 or more, 0 or 1)
+-matches of the regular expression.
+-.IP
+-Two regular expressions concatenated
+-match a match of the first followed by a match of 
+-the second.
+-.IP
+-Two regular expressions separated by | or newline
+-match either a match for the first or a match for the
+-second.
+-.IP
+-A regular expression enclosed in parentheses
+-matches a match for the regular expression.
+-.LP
+-The order of precedence of operators
+-at the same parenthesis level
+-is [\|] then
+-*+? then concatenation then | and newline.
+-.SH "SEE ALSO"
+-ed(1),
+-sed(1),
+-sh(1)
+-.SH DIAGNOSTICS
+-Exit status is 0 if any matches are found,
+-1 if none, 2 for syntax errors or inaccessible files.
+-.SH BUGS
+-Ideally there should be only one
+-.I grep,
+-but we don't know a single algorithm that spans a wide enough
+-range of space-time tradeoffs.
+-.PP
+-Lines
+-are limited to 256 characters;
+-longer lines are truncated.
+//GO.SYSIN DD grep.1
+echo icheck.1m
+sed 's/.//' >icheck.1m <<'//GO.SYSIN DD icheck.1m'
+-.TH ICHECK 1M 
+-.SH NAME
+-icheck \- file system storage consistency check
+-.SH SYNOPSIS
+-.B icheck
+-[
+-.B \-s
+-]  [
+-.B \-b
+-numbers ]
+-[ filesystem ]
+-.SH DESCRIPTION
+-.I Icheck
+-examines a file system,
+-builds a bit map of used blocks,
+-and compares this bit map against
+-the free list maintained on the file system.
+-If the file system is not specified,
+-a set of default file systems
+-is checked.
+-The normal output of
+-.I icheck
+-includes a report of
+-.IP ""
+-The total number of files and the numbers of
+-regular, directory, block special and character special files.
+-.IP ""
+-The total number of blocks in use and the numbers of 
+-single-, double-, and triple-indirect blocks and directory blocks.
+-.IP ""
+-The number of free blocks.
+-.IP ""
+-The number of blocks missing; i.e. not in any file
+-nor in the free list.
+-.PP
+-The
+-.B \-s
+-option causes
+-.I icheck
+-to ignore the actual free list and reconstruct a new one
+-by rewriting the super-block of the file system.
+-The file system should be dismounted while this is done;
+-if this is not possible (for example if
+-the root file system has to be salvaged)
+-care should be taken that the system is quiescent and that
+-it is rebooted immediately afterwards so that the old, bad in-core
+-copy of the super-block will not continue to be used.
+-Notice also that
+-the words in the super-block
+-which indicate the size of the free list and of the
+-i-list are believed.
+-If the super-block has been curdled
+-these words will have to be patched.
+-The
+-.B \-s
+-option
+-causes the normal output reports to be suppressed.
+-.PP
+-Following the
+-.B \-b
+-option is a list of block numbers;
+-whenever any of the named blocks turns up in a file,
+-a diagnostic is produced.
+-.PP
+-.I Icheck
+-is faster if the raw version of the special file is used,
+-since it reads the i-list many blocks at a time.
+-.SH FILES
+-Default file systems vary with installation.
+-.SH "SEE ALSO"
+-dcheck(1), ncheck(1),
+-filsys(5), clri(1)
+-.SH DIAGNOSTICS
+-For duplicate blocks
+-and bad blocks (which lie outside the file system)
+-.I icheck
+-announces the difficulty, the i-number, and the kind of block involved.
+-If a read error is encountered,
+-the block number of the bad block is printed and
+-.I icheck
+-considers it to contain 0.
+-`Bad freeblock' means that
+-a block number outside the available space was encountered in the free list.
+-`\fIn\fR dups in free'
+-means that
+-.IR n ""
+-blocks were found in the free list which
+-duplicate blocks either in some file or in the earlier part of the free list.
+-.SH BUGS
+-Since
+-.I icheck
+-is inherently two-pass in nature, extraneous diagnostics
+-may be produced if applied to active file systems.
+-.br
+-It believes even preposterous super-blocks and
+-consequently can get core images.
+//GO.SYSIN DD icheck.1m
+echo intro.1
+sed 's/.//' >intro.1 <<'//GO.SYSIN DD intro.1'
+-.TH INTRO 1 
+-.SH NAME
+-intro \- introduction to commands
+-.SH DESCRIPTION
+-This section describes publicly accessible commands
+-in alphabetic order.
+-Certain distinctions of purpose are made in the headings:
+-.TP
+-(1)
+-Commands of general utility.
+-.TP
+-(1C)
+-Commands for communication with other systems.
+-.TP
+-(1G)
+-Commands used primarily for graphics and computer-aided design.
+-.TP
+-(1M)
+-Commands used primarily for system maintenance.
+-.PP
+-The word `local' at the foot of a page means that the
+-command is not intended for general distribution.
+-.SH SEE ALSO
+-.SH DIAGNOSTICS
+-Section (6) for computer games.
+-.PP
+-.I How to get started,
+-in the Introduction.
+-.SH DIAGNOSTICS
+-Upon termination each command returns two bytes of status,
+-one supplied by the system giving the cause for
+-termination, and (in the case of `normal' termination)
+-one supplied by the program,
+-see
+-.I wait
+-and
+-.IR exit (2).
+-The former byte is 0 for normal termination, the latter
+-is customarily 0 for successful execution, nonzero
+-to indicate troubles such as erroneous parameters, bad or inaccessible data,
+-or other inability to cope with the task at hand.
+-It is called variously `exit code', `exit status' or
+-`return code', and is described only where special
+-conventions are involved.
+//GO.SYSIN DD intro.1
+echo iostat.1m
+sed 's/.//' >iostat.1m <<'//GO.SYSIN DD iostat.1m'
+-.TH IOSTAT 1M 
+-.SH NAME
+-iostat \- report I/O statistics
+-.SH SYNOPSIS
+-.B iostat
+-[ option ] ...
+-[ interval [ count ] ]
+-.SH DESCRIPTION
+-.I Iostat
+-delves into the system and reports certain statistics kept about
+-input-output activity.
+-Information is kept about up to three different disks
+-(RF, RK, RP) and about typewriters.
+-For each disk, IO completions and number of words transferred
+-are counted; for typewriters collectively, the number
+-of input and output characters are counted.
+-Also, each sixtieth of a second,
+-the state of each disk is examined
+-and a tally is made if the disk is active.
+-The tally goes into
+-one of four categories, depending on whether the system is
+-executing in user mode, in `nice' (background)
+-user mode, in system mode, or idle.
+-From all these numbers and from the known transfer rates
+-of the devices it is possible to determine
+-information such as the degree of IO overlap
+-and average seek times for each device.
+-.PP
+-The optional
+-.I interval
+-argument causes
+-.I iostat
+-to report once each
+-.I interval
+-seconds.
+-The first report is for  all time since a reboot and each
+-subsequent report is for the last interval only.
+-.PP
+-The optional
+-.I count
+-argument restricts the number of reports.
+-.PP
+-With no option argument
+-.I iostat
+-reports for each disk the number of transfers per minute,
+-the milliseconds
+-per average seek,
+-and the milliseconds per data transfer exclusive of seek time.
+-It also gives the percentage of time the system has
+-spend in each of the four categories mentioned above.
+-.PP
+-The following options are available:
+-.TP
+-.B \-t
+-Report the number of characters of terminal IO per second as well.
+-.TP
+-.B \-i
+-Report the percentage of time spend in each
+-of the four categories mentioned above,
+-the percentage of time each disk was active (seeking or transferring),
+-the percentage of time any disk was active,
+-and the percentage of time spent in `IO wait:'
+-idle, but with a disk active.
+-.TP
+-.B \-s
+-Report the raw timing information: 32 numbers indicating
+-the percentage of time spent in each of the possible
+-configurations of 4 system states and 8 IO states
+-(3 disks each active or not).
+-.TP
+-.B \-b
+-Report on the usage of IO buffers.
+-.SH FILES
+-/dev/mem, /unix
+//GO.SYSIN DD iostat.1m
+echo join.1
+sed 's/.//' >join.1 <<'//GO.SYSIN DD join.1'
+-.TH JOIN 1 
+-.SH NAME
+-join \- relational database operator
+-.SH SYNOPSIS
+-.B join
+-[
+-options
+-]
+-file1 file2
+-.SH DESCRIPTION
+-.I Join
+-forms, on the standard output,
+-a join
+-of the two relations specified by the lines of
+-.I file1
+-and
+-.IR file2 .
+-If
+-.I file1
+-is `\-', the standard input is used.
+-.PP
+-.I File1
+-and 
+-.I file2
+-must be sorted in increasing ASCII collating
+-sequence on the fields
+-on which they are to be joined,
+-normally the first in each line.
+-.PP
+-There is one line in the output 
+-for each pair of lines in 
+-.I file1 
+-and 
+-.I file2
+-that have identical join fields.
+-The output line normally consists of the common field,
+-then the rest of the line from 
+-.IR file1 ,
+-then the rest of the line from
+-.IR file2 .
+-.PP
+-Fields are normally separated by blank, tab or newline.
+-In this case, multiple separators count as one, and
+-leading separators are discarded.
+-.PP
+-These options are recognized:
+-.TP
+-.BI \-a n
+-In addition to the normal output,
+-produce a line for each unpairable line in file
+-.IR n ,
+-where
+-.I n
+-is 1 or 2.
+-.TP
+-.BI \-e \ s
+-Replace empty output fields by string
+-.IR s .
+-.TP
+-.BI \-j n\ m
+-Join on the
+-.IR m th
+-field of file
+-.IR n .
+-If
+-.I n
+-is missing, use the
+-.IR m th
+-field in each file.
+-.TP
+-.BI \-o \ list
+-Each output line comprises the fields specifed in
+-.IR list ,
+-each element of which has the form
+-.IR n . m ,
+-where
+-.I n
+-is a file number and
+-.I m
+-is a field number.
+-.PP
+-.TP
+-.BI \-t c
+-Use character
+-.I c
+-as a separator (tab character).
+-Every appearance of
+-.I c
+-in a line is significant.
+-.SH "SEE ALSO"
+-sort(1), comm(1), awk(1)
+-.SH BUGS
+-With default field separation,
+-the collating sequence is that of
+-.IR sort\ \-b ;
+-with
+-.BR \-t ,
+-the sequence is that of a plain sort.
+-.PP
+-The conventions of
+-.I join, sort, comm, uniq, look
+-and
+-.IR awk (1)
+-are wildly incongruous.
+//GO.SYSIN DD join.1
+echo kill.1
+sed 's/.//' >kill.1 <<'//GO.SYSIN DD kill.1'
+-.TH KILL 1 
+-.SH NAME
+-kill \- terminate a process with extreme prejudice
+-.SH SYNOPSIS
+-.B kill
+-[
+-.BR \- signo
+-]
+-processid ...
+-.SH DESCRIPTION
+-.I Kill
+-sends signal 15 (terminate) to the specified processes.
+-If a signal number preceded by `\-' is given
+-as first argument, that signal is sent instead of
+-terminate
+-(see
+-.IR  signal (2)).
+-This will kill processes that do not catch the signal;
+-in particular `kill \-9 ...' is a sure kill.
+-.PP
+-By convention, if process number 0 is specified, all members
+-in the process group (i.e. processes resulting from 
+-the current login) are signaled.
+-.PP
+-The killed processes must belong
+-to the current user unless
+-he is the super-user.
+-To shut the system down and bring it up single user
+-the super-user may
+-use `kill \-1 1'; see
+-.IR init (8).
+-.PP
+-The process number of an asynchronous process
+-started with `&' is reported by the shell.
+-Process numbers can also be found by using
+-.IR ps (1).
+-.SH "SEE ALSO"
+-ps(1), kill(2), signal(2)
+//GO.SYSIN DD kill.1
+echo ld.1
+sed 's/.//' >ld.1 <<'//GO.SYSIN DD ld.1'
+-.TH LD 1 
+-.SH NAME
+-ld \- loader
+-.SH SYNOPSIS
+-.B ld
+-[ option ] file ...
+-.SH DESCRIPTION
+-.I Ld
+-combines several
+-object programs into one, resolves external
+-references, and searches libraries.
+-In the simplest case several object
+-.I files
+-are given, and
+-.I ld
+-combines them, producing
+-an object module which can be either executed or
+-become the input for a further
+-.I ld
+-run.
+-(In the latter case, the
+-.B \-r
+-option must be given
+-to preserve the relocation bits.)
+-The output of
+-.I ld
+-is left on
+-.BR a.out .
+-This file is made executable
+-only if no errors occurred during the load.
+-.PP
+-The argument routines are concatenated in the order
+-specified.  The entry point of the output is the
+-beginning of the first routine.
+-.PP
+-If any argument is a library, it is searched exactly once
+-at the point it is encountered in the argument list.
+-Only those routines defining an unresolved external
+-reference are loaded.
+-If a routine from a library
+-references another routine in the library,
+-and the library has not been processed by
+-.IR ranlib (1),
+-the referenced routine must appear after the
+-referencing routine in the library.
+-Thus the order of programs within libraries
+-may be important.
+-If the first member of a library is named
+-`__.SYMDEF',
+-then it is understood to be a dictionary for the
+-library
+-such
+-as produced by
+-.IR ranlib ;
+-the dictionary is searched
+-iteratively to satisfy as many references as possible.
+-.PP
+-The symbols `\_etext', `\_edata' and `\_end'
+-(`etext', `edata' and `end' in C)
+-are reserved, and if referred to,
+-are set to the first location above the program,
+-the first location above initialized data,
+-and the first location above all data respectively.
+-It is erroneous to define these symbols.
+-.PP
+-.I Ld
+-understands several options.
+-Except for
+-.BR \-l ,
+-they should appear before the file names.
+-.TP 
+-.B  \-s
+-`Strip' the output, that is, remove the symbol table
+-and relocation bits to save space (but impair the
+-usefulness of the debugger).
+-This information can also be removed by
+-.IR  strip (1).
+-.TP 
+-.B  \-u
+-Take the following argument as a symbol and enter
+-it as undefined in the symbol table.  This is useful
+-for loading wholly from a library, since initially the symbol
+-table is empty and an unresolved reference is needed
+-to force the loading of the first routine.
+-.TP 
+-.BI \-l x
+-This
+-option is an abbreviation for the library name
+-.RI `/lib/lib x .a',
+-where
+-.I x
+-is a string.
+-If that does not exist,
+-.I ld
+-tries
+-.RI `/usr/lib/lib x .a'.
+-A library is searched when its name is encountered,
+-so the placement of a
+-.B  \-l
+-is significant.
+-.TP 
+-.B  \-x
+-Do not preserve local
+-(non-.globl) symbols in the output symbol table; only enter
+-external symbols.
+-This option saves some space in the output file.
+-.TP 
+-.B  \-X
+-Save local symbols
+-except for those whose names begin with `L'.
+-This option is used by
+-.IR cc (1)
+-to discard internally generated labels while
+-retaining symbols local to routines.
+-.TP 
+-.B  \-r
+-Generate relocation bits in the output file
+-so that it can be the subject of another
+-.I ld
+-run.
+-This flag also prevents final definitions from being
+-given to common symbols,
+-and suppresses the `undefined symbol' diagnostics.
+-.TP 
+-.B  \-d
+-Force definition of common storage
+-even if the
+-.B \-r
+-flag is present.
+-.TP 
+-.B  \-n
+-Arrange that
+-when the output file is executed,
+-the text portion will be read-only and shared
+-among all users executing the file.
+-This involves moving the data areas up to the first
+-possible 4K word boundary following the
+-end of the text.
+-.TP 
+-.B  \-i
+-When the output file is executed, the program
+-text and data areas will live in separate address spaces.
+-The only difference between this option
+-and
+-.B \-n
+-is that here the data starts at location 0.
+-.TP 
+-.B  \-o
+-The
+-.I name
+-argument after
+-.B \-o
+-is used as the name of the
+-.I ld
+-output file, instead of
+-.BR a.out .
+-.TP
+-.B \-e
+-The following argument is taken to be the
+-name of the entry point of the loaded
+-program; location 0 is the default.
+-.TP
+-.B \-O
+-This is an overlay file, only the text segment
+-will be replaced by
+-.IR exec (2).
+-Shared data must have the same layout as in
+-the program overlaid.
+-.TP
+-.B \-D
+-The next argument is a decimal number that sets
+-the size of the data segment.
+-.SH FILES
+-.ta \w'/usr/lib/lib*.a\ \ 'u
+-/lib/lib*.a   libraries
+-.br
+-/usr/lib/lib*.a       more libraries
+-.br
+-a.out output file
+-.SH "SEE ALSO"
+-as(1), ar(1), cc(1), ranlib(1)
+-.SH BUGS
+//GO.SYSIN DD ld.1
+echo lex.1
+sed 's/.//' >lex.1 <<'//GO.SYSIN DD lex.1'
+-.TH LEX 1 
+-.SH NAME
+-lex \- generator of lexical analysis programs
+-.SH SYNOPSIS
+-.B lex
+-[
+-.B \-tvfn
+-] [ file ] ...
+-.SH DESCRIPTION
+-.I Lex
+-generates programs to be used in simple lexical analyis of text.
+-The input
+-.I files
+-(standard input default)
+-contain regular expressions
+-to be searched for, and actions written in C to be executed when
+-expressions are found.
+-.PP
+-A C source program, `lex.yy.c' is generated, to be compiled thus:
+-.IP
+-cc lex.yy.c \-ll
+-.LP
+-This program, when run, copies unrecognized portions of
+-the input to the output,
+-and executes the associated
+-C action for each regular expression that is recognized.
+-.PP
+-The following 
+-.I lex
+-program converts upper case to lower,
+-removes blanks at the end of lines,
+-and replaces multiple blanks by single blanks.
+-.IP ""
+-.nf
+-.ta \w'[A\-Z] 'u
+-%%
+-[A\-Z]        putchar(yytext[0]+\'a\'\-\'A\');
+-[ ]+$
+-[ ]+  putchar(\' \');
+-.fi
+-.PP
+-The options have the following meanings.
+-.TP
+-.B \-t
+-Place the result on the standard output instead of in file
+-`lex.yy.c'.
+-.TP
+-.B \-v
+-Print a one-line summary of statistics of the generated analyzer.
+-.TP
+-.B \-n
+-Opposite of
+-.BR \-v ;
+-.B \-n
+-is default.
+-.TP
+-.B \-f
+-`Faster' compilation: don't bother to pack
+-the resulting tables; limited to small programs.
+-.SH "SEE ALSO"
+-yacc(1)
+-.br
+-M. E. Lesk and E. Schmidt,
+-.I LEX \- Lexical Analyzer Generator
+//GO.SYSIN DD lex.1
+echo lint.1
+sed 's/.//' >lint.1 <<'//GO.SYSIN DD lint.1'
+-.TH LINT 1 
+-.SH NAME
+-lint \- a C program verifier
+-.SH SYNOPSIS
+-.B lint
+-[
+-.B \-abchnpuvx
+-]
+-file ...
+-.SH DESCRIPTION
+-.I Lint
+-attempts to detect features of the C program
+-.I files
+-which are
+-likely to be bugs, or non-portable, or wasteful.
+-It also checks the type usage of the program more strictly
+-than the compilers.
+-Among the things which are currently found are
+-unreachable statements,
+-loops not entered at the top,
+-automatic variables declared and not used,
+-and logical expressions whose value is constant.
+-Moreover, the usage of functions is checked to find
+-functions which return values in some places and not in others,
+-functions called with varying numbers of arguments,
+-and functions whose values are not used.
+-.PP
+-By default, it is assumed that all the
+-.I files
+-are to be loaded together; they are checked for
+-mutual compatibility.
+-Function definitions for certain libraries are available to
+-.IR lint ;
+-these libraries are referred to by a
+-conventional name,
+-such as `-lm', in the style of
+-.IR ld (1).
+-.PP
+-Any number of the options in the following list
+-may be used.
+-The
+-.SM
+-.BR \-D "\*S,"
+-.SM
+-.BR \-U "\*S,"
+-and
+-.SM
+-.B \-I
+-options of
+-.IR cc (1)
+-are also recognized as separate arguments.
+-.TP
+-.B p
+-Attempt to check portability to the
+-.I IBM
+-and
+-.I GCOS
+-dialects of C.
+-.TP
+-.B h
+-Apply a number of heuristic tests to attempt to
+-intuit bugs, improve style, and reduce waste.
+-.TP
+-.B b
+-Report
+-.I break
+-statements that cannot be reached.
+-(This is not the default because, unfortunately,
+-most
+-.I lex
+-and many
+-.I yacc
+-outputs produce dozens of such comments.)
+-.TP
+-.B v
+-Suppress complaints about unused arguments in functions.
+-.TP
+-.B x
+-Report variables referred to by extern declarations,
+-but never used.
+-.TP
+-.B a
+-Report assignments of long values to int variables.
+-.TP
+-.B c
+-Complain about casts which have questionable portability.
+-.TP
+-.B u
+-Do not complain about functions and variables used and not
+-defined, or defined and not used (this is suitable for running
+-.I lint
+-on a subset of files out of a larger program).
+-.TP
+-.B n
+-Do not check compatibility against the standard library.
+-.PP
+-.IR Exit (2)
+-and other functions which do not return
+-are not understood; this causes various lies.
+-.PP
+-Certain conventional comments in the C source
+-will change the behavior of
+-.IR lint :
+-.TP
+-/*NOTREACHED*/
+-at appropriate points
+-stops comments about unreachable code.
+-.TP
+-.RI /*VARARGS n */
+-suppresses
+-the usual checking for variable numbers of arguments
+-in the following function declaration.
+-The data types of the first
+-.I n
+-arguments are checked;
+-a missing
+-.I n
+-is taken to be 0.
+-.TP
+-/*NOSTRICT*/
+-shuts off strict type checking in the next expression.
+-.TP
+-/*ARGSUSED*/
+-turns on the
+-.B \-v
+-option for the next function.
+-.TP
+-/*LINTLIBRARY*/
+-at the beginning of a file shuts off complaints about
+-unused functions in this file.
+-.SH FILES
+-/usr/lib/lint[12] programs
+-.br
+-/usr/lib/llib-lc declarations for standard functions
+-.br
+-/usr/lib/llib-port declarations for portable functions
+-.SH SEE ALSO
+-cc(1)
+-.br
+-S. C. Johnson,
+-.I Lint, a C Program Checker
+//GO.SYSIN DD lint.1
+echo ln.1
+sed 's/.//' >ln.1 <<'//GO.SYSIN DD ln.1'
+-.TH LN 1 
+-.SH NAME
+-ln  \-  make a link
+-.SH SYNOPSIS
+-.B ln
+-name1 [ name2 ]
+-.SH DESCRIPTION
+-A link is a directory entry referring
+-to a file; the same file (together with
+-its size, all its protection
+-information, etc.)
+-may have several links to it.
+-There is no way to distinguish a link to a file
+-from its original directory entry;
+-any changes in the
+-file are effective
+-independently of the name by which the file is known.
+-.PP
+-.I Ln
+-creates a link to an existing file
+-.IR name1 .
+-If
+-.I name2
+-is given, the link has that name;
+-otherwise it is placed in the current directory
+-and its name is the last component
+-of
+-.IR name1 .
+-.PP
+-It is forbidden to link to a directory
+-or to link across file systems.
+-.SH "SEE ALSO"
+-rm(1)
+//GO.SYSIN DD ln.1
+echo login.1
+sed 's/.//' >login.1 <<'//GO.SYSIN DD login.1'
+-.TH LOGIN 1 
+-.SH NAME
+-login  \-  sign on
+-.SH SYNOPSIS
+-.B login
+-[ username ]
+-.SH DESCRIPTION
+-The
+-.I login
+-command
+-is used when a user initially
+-signs on, or it may be used at any time to change
+-from one user to another.
+-The latter case is the one summarized above and
+-described here.
+-See `How to Get Started' for how to dial up initially.
+-.PP
+-If
+-.I login
+-is invoked without an argument,
+-it asks for a user name, and, if
+-appropriate, a password.
+-Echoing is turned off (if possible) during the typing of the password,
+-so it will not appear on the written record of the
+-session.
+-.PP
+-After a successful login,
+-accounting files are updated and
+-the user is informed of the
+-existence of
+-.I .mail
+-and message-of-the-day files.
+-.I Login
+-initializes the user and group IDs and the working directory,
+-then executes a command interpreter (usually
+-.IR  sh (1))
+-according to specifications found in a password file.
+-Argument 0 of the command interpreter is `\-sh.
+-.PP
+-Login is recognized by
+-.IR sh (1)
+-and executed directly (without forking).
+-.SH FILES
+-.ta \w'/usr/adm/wtmp\ \ 'u
+-/etc/utmp     accounting
+-.br
+-/usr/adm/wtmp accounting
+-.br
+-/usr/mail/*   mail
+-.br
+-/etc/motd     message-of-the-day
+-.br
+-/etc/passwd   password file
+-.SH "SEE ALSO"
+-init(8), newgrp(1), getty(8), mail(1), passwd(1), passwd(5)
+-.SH DIAGNOSTICS
+-`Login incorrect,'
+-if the name or the password is bad.
+-.br
+-`No Shell', `cannot open password file', `no directory':
+-consult a programming counselor.
+//GO.SYSIN DD login.1
+echo look.1
+sed 's/.//' >look.1 <<'//GO.SYSIN DD look.1'
+-.TH LOOK 1 
+-.SH NAME
+-look \- find lines in a sorted list
+-.SH SYNOPSIS
+-.B look
+-[
+-.B \-df
+-]
+-string
+-[ file ]
+-.SH DESCRIPTION
+-.I Look
+-consults a sorted
+-.I file
+-and prints all lines that begin with
+-.IR string .
+-It uses binary search.
+-.PP
+-The options 
+-.B d
+-and
+-.B f
+-affect comparisons as in
+-.IR  sort (1):
+-.TP 4
+-.B  d
+-`Dictionary' order:
+-only letters, digits,
+-tabs and blanks participate in comparisons.
+-.TP 4
+-.B  f
+-Fold.
+-Upper case letters compare equal to lower case.
+-.PP
+-If no
+-.I file
+-is specified,
+-.I /usr/dict/words
+-is assumed with collating sequence
+-.B \-df.
+-.SH FILES
+-/usr/dict/words
+-.SH "SEE ALSO"
+-sort(1), grep(1)
+//GO.SYSIN DD look.1
+echo lookall.1
+sed 's/.//' >lookall.1 <<'//GO.SYSIN DD lookall.1'
+-.TH LOOKALL 1
+-.SH NAME
+-lookall \- look through all text files on UNIX
+-.SH SYNOPSIS
+-.B lookall
+-[
+-.BI \-C n
+-]
+-.SH DESCRIPTION
+-.I Lookall
+-accepts keywords from the standard input, performs
+-a search similar to that of
+-.IR  refer (1),
+-and writes the result on the standard output.
+-.I Lookall
+-consults, however, an index to all the text files on
+-the system rather than just bibliographies.
+-Only the first 50
+-words of each file (roughly) were used to
+-make the indexes.
+-Blank lines are taken as delimiters between queries.
+-.PP
+-The
+-.BI -C n
+-option
+-specifies a coordination level search: up to
+-.IR n
+-keywords may be missing
+-from the answers, and the answers are listed
+-with those containing the most keywords first.
+-.PP
+-The command sequence in
+-.I /usr/dict/lookall/makindex
+-regenerates the index.
+-.SH FILES
+-The directory
+-.I /usr/dict/lookall
+-contains the index files.
+-.SH DIAGNOSTICS
+-`Warning: index precedes file ...'
+-means that a file has been changed since the index was made
+-and it may be retrieved (or not retrieved) erroneously.
+-.SH BUGS
+-Coordination level searching doesn't work as described: only
+-those acceptable items with the smallest number of
+-missing keywords are retreived.
+//GO.SYSIN DD lookall.1
+echo lorder.1
+sed 's/.//' >lorder.1 <<'//GO.SYSIN DD lorder.1'
+-.TH LORDER 1 
+-.SH NAME
+-lorder \- find ordering relation for an object library
+-.SH SYNOPSIS
+-.B lorder
+-file ...
+-.SH DESCRIPTION
+-The input
+-is one or more object or library archive (see
+-.IR ar (1))
+-.I files.
+-The standard output
+-is a list of pairs of object file names,
+-meaning that the first file of the pair refers to
+-external identifiers defined in the second.
+-The output may be processed by
+-.IR  tsort (1)
+-to find an ordering of
+-a library suitable for one-pass access by
+-.IR  ld (1).
+-.PP
+-This brash one-liner intends to build a new library
+-from existing `.o' files.
+-.IP
+-ar cr library \`\|lorder *.o | tsort\`
+-.SH FILES
+-*symref, *symdef
+-.br
+-nm(1), sed(1), sort(1), join(1)
+-.SH "SEE ALSO"
+-tsort(1),
+-ld(1),
+-ar(1)
+-.SH BUGS
+-The names of object files, in and out of libraries, must end with `.o';
+-nonsense results otherwise.
+//GO.SYSIN DD lorder.1
+echo ls.1
+sed 's/.//' >ls.1 <<'//GO.SYSIN DD ls.1'
+-.TH LS 1 
+-.SH NAME
+-ls  \-  list contents of directory
+-.SH SYNOPSIS
+-.B ls
+-[
+-.B \-ltasdrucifg
+-] name ...
+-.SH DESCRIPTION
+-For each directory argument,
+-.I ls
+-lists the contents of the directory;
+-for each file argument,
+-.I ls
+-repeats its name and any other information requested.
+-The output is sorted alphabetically by default.
+-When no argument is given, the current directory is listed.
+-When several arguments are given,
+-the arguments are first sorted appropriately,
+-but file arguments appear
+-before directories and their contents.
+-There are several options:
+-.TP
+-.B  \-l
+-List in long format, giving mode, number of links, owner,
+-size in bytes, and time of last modification
+-for each file.
+-(See below.)
+-If the file is a special file the size field will instead contain
+-the major and minor device numbers.
+-.TP
+-.B  \-t
+-Sort by time modified (latest first) instead of
+-by name, as is normal.
+-.TP
+-.B  \-a
+-List all entries; usually
+-.RB ` . '
+-and
+-.RB ` .. '
+-are suppressed.
+-.TP
+-.B  \-s
+-Give size in blocks,
+-including indirect blocks, for each entry.
+-.TP
+-.B  \-d
+-If argument is a directory, list only its name, not
+-its contents (mostly used with
+-.B \-l
+-to get status
+-on directory).
+-.TP
+-.B  \-r
+-Reverse the order of sort to get reverse alphabetic
+-or oldest first as appropriate.
+-.TP
+-.B  \-u
+-Use time of last access instead of last
+-modification for sorting
+-.RB ( \-t )
+-or printing
+-.RB ( \-l ).
+-.TP
+-.B \-c
+-Use time of last modification to inode (mode, etc.)
+-instead of last modification to file for sorting
+-.RB ( \-t )
+-or printing
+-.RB ( \-l ).
+-.TP
+-.B  \-i
+-Print i-number in first column
+-of the report for each file listed.
+-.TP
+-.B  \-f
+-Force each argument to be interpreted as a directory
+-and list the name found in each slot.
+-This option turns off
+-.B "\-l, \-t, \-s,"
+-and
+-.B \-r,
+-and
+-turns on
+-.B \-a;
+-the order is the order in which entries
+-appear in the directory.
+-.TP
+-.B  \-g
+-Give group ID instead of owner ID in long listing.
+-.PP
+-The mode printed under the
+-.B \-l
+-option contains 11 characters
+-which are interpreted
+-as follows:
+-the first character is
+-.TP 3
+-.B  d
+-if the entry is a directory;
+-.br
+-.ns
+-.TP 3
+-.B  b
+-if the entry is a block-type special file;
+-.br
+-.ns
+-.TP 3
+-.B  c
+-if the entry is a character-type special file;
+-.br
+-.ns
+-.TP 3
+-.B  \-
+-if the entry is a plain file.
+-.PP
+-The next 9 characters are interpreted
+-as three sets of three bits each.
+-The first set refers to owner permissions;
+-the next to permissions to others in the same user-group;
+-and the last to all others.
+-Within each set the three characters indicate
+-permission respectively to read, to write, or to
+-execute the file as a program.
+-For a directory, `execute' permission is interpreted
+-to mean permission to search the directory
+-for a specified file.
+-The permissions are indicated as follows:
+-.TP 3
+-.B  r
+-if the file is readable;
+-.br
+-.ns
+-.TP 3
+-.B  w
+-if the file is writable;
+-.br
+-.ns
+-.TP 3
+-.B  x
+-if the file is executable;
+-.br
+-.ns
+-.TP 3
+-.B  \-
+-if the indicated permission is not granted.
+-.PP
+-The group-execute permission character is given
+-as
+-.B s
+-if the file has set-group-ID mode;
+-likewise the user-execute permission character is given
+-as
+-.B s
+-if the file has set-user-ID mode.
+-.PP
+-The last character of the mode (normally `x' or `\-') is 
+-.B t
+-if the 1000 bit of the mode is on.
+-See
+-.IR  chmod (1)
+-for the meaning of this mode.
+-.PP
+-When the sizes of the files in a directory
+-are listed, a total count of blocks,
+-including indirect blocks is printed.
+-.SH FILES
+-/etc/passwd to get user ID's for
+-`ls \-l'.
+-.br
+-/etc/group to get group ID's for
+-`ls \-g'.
+//GO.SYSIN DD ls.1
+echo m4.1
+sed 's/.//' >m4.1 <<'//GO.SYSIN DD m4.1'
+-.TH M4 1 
+-.SH NAME
+-m4 \- macro processor
+-.SH SYNOPSIS
+-.B m4
+-[ files ]
+-.SH DESCRIPTION
+-.I M4
+-is a macro processor
+-intended as a front end for Ratfor, C, and other languages.
+-Each of the argument files is processed in order;
+-if there are no arguments, or if an argument is `\-',
+-the standard input is read.
+-The processed text is written on the standard output.
+-.PP
+-Macro calls
+-have the form
+-.PP
+-      name(arg1,arg2, . . . , argn)
+-.br
+-.PP
+-The `(' must immediately follow the name of the macro.
+-If a defined macro name is not followed by a `(',
+-it is deemed to have no arguments.
+-Leading unquoted blanks, tabs, and newlines are ignored while collecting arguments.
+-Potential macro names consist of alphabetic letters,
+-digits, and underscore `\_', where the first character is not a digit.
+-.PP
+-Left and right single quotes (\`\|\') are used to quote strings.
+-The value of a quoted string is the string stripped of the quotes.
+-.PP
+-When a macro name is recognized,
+-its arguments are collected by searching for a matching right
+-parenthesis.
+-Macro evaluation proceeds normally during the collection of the arguments,
+-and any commas or right parentheses
+-which happen to turn up within the value of a nested
+-call are as effective as those in the original input text.
+-After argument collection,
+-the value of the macro is pushed back onto the input stream
+-and rescanned.
+-.PP
+-.I M4
+-makes available the following built-in macros.
+-They may be redefined, but once this is done the original meaning is lost.
+-Their values are null unless otherwise stated.
+-.TP 10
+-define
+-The second argument is installed as the value of the macro
+-whose name is the first argument.
+-Each occurrence of $\fIn\fR in the replacement text,
+-where
+-.I n
+-is a digit,
+-is replaced by the
+-.IR n -th
+-argument.
+-Argument 0 is the name of the macro;
+-missing arguments are replaced by the null string.
+-.TP
+-undefine
+-removes the definition of the macro named in its argument.
+-.TP
+-ifdef
+-If the first argument is defined, the value is the second argument, otherwise the third.
+-If there is no third argument, the value is null.
+-The word
+-.I unix
+-is predefined on UNIX versions of
+-.IR m4 .
+-.TP
+-changequote
+-Change quote characters to the first and second arguments.
+-.I Changequote
+-without arguments restores the original values
+-(i.e., \`\|\').
+-.TP
+-divert
+-.I M4
+-maintains 10 output streams,
+-numbered 0-9.
+-The final output is the concatenation of the streams
+-in numerical order;
+-initially stream 0 is the current stream.
+-The
+-.I divert
+-macro changes the current output stream to its (digit-string)
+-argument.
+-Output diverted to a stream other than 0 through 9
+-is discarded.
+-.TP
+-undivert
+-causes immediate output of text from diversions named as
+-arguments, or all diversions if no argument.
+-Text may be undiverted into another diversion.
+-Undiverting discards the diverted text.
+-.TP
+-divnum
+-returns the value of the current output stream.
+-.TP
+-dnl
+-reads and discards characters up to and including the next newline.
+-.TP
+-ifelse
+-has three or more arguments.
+-If the first argument is the same string as the second,
+-then the value is the third argument.
+-If not, and if there are more than four arguments, the process is repeated with arguments 4, 5, 6 and 7.
+-Otherwise, the value is either the fourth string, or, if it is not present,
+-null.
+-.TP
+-incr
+-returns the value of its argument incremented by 1.
+-The value of the argument is calculated
+-by interpreting an initial digit-string as a decimal number.
+-.TP
+-eval
+-evaluates its argument as an arithmetic expression, using 32-bit arithmetic.
+-Operators include +, \-, \(**, /, %, ^ (exponentiation); relationals; parentheses.
+-.TP
+-len
+-returns the number of characters in its argument.
+-.TP
+-index
+-returns the position in its first argument where the second argument begins (zero origin),
+-or \-1 if the second argument does not occur.
+-.TP
+-substr
+-returns a substring of its first argument.
+-The second argument is a zero origin
+-number selecting the first character;
+-the third argument indicates the length of the substring.
+-A missing third argument is taken to be large enough to extend to
+-the end of the first string.
+-.TP
+-translit
+-transliterates the characters in its first argument
+-from the set given by the second argument to the set given by the third.
+-No abbreviations are permitted.
+-.TP
+-include
+-returns the contents of the file named in the argument.
+-.TP
+-sinclude
+-is identical to
+-.I include,
+-except that it
+-says nothing if the file is inaccessible.
+-.TP
+-syscmd
+-executes the UNIX command given in the first argument.
+-No value is returned.
+-.TP
+-maketemp
+-fills in a string of XXXXX in its argument with the current process id.
+-.TP
+-errprint
+-prints its argument
+-on the diagnostic output file.
+-.TP
+-dumpdef
+-prints current names and definitions,
+-for the named items, or for all if no arguments are given.
+-.dt
+-.SH "SEE ALSO"
+-B. W. Kernighan and D. M. Ritchie,
+-.I The M4 Macro Processor
+//GO.SYSIN DD m4.1
+echo mail.1
+sed 's/.//' >mail.1 <<'//GO.SYSIN DD mail.1'
+-.TH MAIL 1 
+-.SH NAME
+-mail  \-  send or receive mail among users
+-.SH SYNOPSIS
+-.B mail
+-person ...
+-.br
+-.B mail
+-[
+-.B \-r
+-] [
+-.B \-q
+-] [
+-.B \-p
+-] [
+-.B \-f
+-file
+-]
+-.LP
+-.SH DESCRIPTION
+-.I Mail
+-with no argument
+-prints
+-a user's mail,
+-message-by-message,
+-in last-in, first-out order;
+-the optional argument
+-.B \-r
+-causes first-in, first-out order.
+-If the
+-.B \-p
+-flag is given, the mail is printed with no questions asked;
+-otherwise,
+-for each message,
+-.I mail
+-reads a line from the standard input
+-to direct disposition of the message.
+-.TP
+-newline
+-Go on to next message.
+-.TP
+-d
+-Delete message and go on to the next.
+-.TP
+-p
+-Print message again.
+-.TP
+-\-
+-Go back to previous message.
+-.TP
+-.RI "s [" " file " "] ..."
+-Save the message in the named
+-.I files
+-(`mbox' default).
+-.TP
+-.RI "w [" " file " "] ..."
+-Save the message, without a header, in the named
+-.I files
+-(`mbox' default).
+-.TP
+-.RI "m [" " person " "] ..."
+-Mail the message to the named
+-.I persons
+-(yourself is default).
+-.TP
+-EOT (control-D)
+-Put unexamined mail back in the mailbox and stop.
+-.TP
+-q
+-Same as EOT.
+-.TP
+-x
+-Exit, without changing the mailbox file.
+-.TP
+-!command
+-Escape to the Shell to do command.
+-.TP
+-?
+-Print a command summary.
+-.PP
+-An interrupt stops the printing of the current letter.
+-The optional argument
+-.B \(miq
+-causes
+-.I mail
+-to exit after interrupts
+-without changing the mailbox.
+-.PP
+-When
+-.I persons
+-are named,
+-.I mail
+-takes the standard input up to an end-of-file
+-(or a line with just `.')
+-and adds it to each
+-.I person's
+-`mail' file.
+-The message is preceded by the sender's name and a postmark.
+-Lines that look like postmarks are
+-prepended with `>'.
+-A
+-.I person
+-is usually a user name recognized by
+-.IR  login (1).
+-To denote a recipient on a remote system, prefix 
+-.I person
+-by the system name and exclamation mark (see
+-.IR uucp (1)).
+-.PP
+-The
+-.B \-f
+-option causes the named file, e.g. `mbox',
+-to be printed as if it were the mail file.
+-.PP
+-Each user owns his own mailbox, which is by default generally
+-readable but not writable.
+-The command does not delete an empty mailbox nor change its mode,
+-so a user may make it unreadable if desired.
+-.PP
+-When a user logs in he is informed of the presence
+-of mail.
+-.SH FILES
+-/usr/spool/mail/*     mailboxes
+-.br
+-/etc/passwd   to identify sender and locate persons
+-.br
+-mbox          saved mail
+-.br
+-/tmp/ma*      temp file
+-.br
+-dead.letter   unmailable text
+-.br
+-uux(1)
+-.SH "SEE ALSO"
+-xsend(1), write(1), uucp(1)
+-.SH BUGS
+-There is a locking mechanism intended to prevent
+-two senders from accessing the same mailbox, but it
+-is not perfect and races
+-are possible.
+//GO.SYSIN DD mail.1
+echo make.1
+sed 's/.//' >make.1 <<'//GO.SYSIN DD make.1'
+-.TH MAKE 1 
+-.SH NAME
+-make \- maintain program groups
+-.SH SYNOPSIS
+-.B make
+-[
+-.B \-f
+-makefile ] [ option ] ...
+-file ...
+-.SH DESCRIPTION
+-.I Make
+-executes commands in
+-.I makefile
+-to update
+-one or more target
+-.IR names .
+-.I Name
+-is typically a program.
+-If no
+-.B \-f
+-option is present, `makefile' and `Makefile' are
+-tried in order.
+-If
+-.I makefile
+-is `\-', the standard input is taken.
+-More than one
+-.B \-f
+-option may appear
+-.PP
+-.I Make
+-updates a target if it depends on prerequisite files
+-that have been modified since the target was last modified,
+-or if the target does not exist.
+-.PP
+-.I Makefile
+-contains a sequence of entries that specify dependencies.
+-The first line of an entry is a
+-blank-separated list of targets, then a colon,
+-then a list of prerequisite files.
+-Text following a semicolon, and all following lines
+-that begin with a tab, are shell commands
+-to be executed to update the target.
+-.PP
+-Sharp and newline surround comments.
+-.PP
+-The following makefile says that `pgm' depends on two
+-files `a.o' and `b.o', and that they in turn depend on
+-`.c' files and a common file `incl'.
+-.RS 
+-.HP
+-.PD 0
+-.nf
+-pgm: a.o b.o
+-cc a.o b.o \-lm \-o pgm
+-.HP
+-a.o: incl a.c
+-cc \-c a.c
+-.HP
+-b.o: incl b.c
+-cc \-c b.c
+-.fi
+-.RE
+-.PD
+-.PP
+-.I Makefile
+-entries of the form
+-.PP
+-.IP
+-string1 = string2
+-.PP
+-are macro definitions.
+-Subsequent appearances of 
+-.I $(string1)
+-are replaced by
+-.IR string2 .
+-If
+-.I string1
+-is a single character, the parentheses are optional.
+-.PP
+-.I Make 
+-infers prerequisites for files for which
+-.I makefile
+-gives no construction commands.
+-For example, a
+-`.c' file may be inferred as prerequisite for a `.o' file
+-and be compiled to produce the `.o' file.
+-Thus the preceding example can be done more briefly:
+-.RS
+-.HP
+-.PD 0
+-.nf
+-pgm: a.o b.o
+-cc a.o b.o \-lm \-o pgm
+-.HP
+-a.o b.o: incl
+-.fi
+-.RE
+-.PD
+-.PP
+-Prerequisites are inferred according to selected suffixes
+-listed as the `prerequisites' for the special name `.SUFFIXES';
+-multiple lists accumulate;
+-an empty list clears what came before.
+-Order is significant; the first possible name for which both
+-a file and a rule as described in the next paragraph exist
+-is inferred.
+-The default list is
+-.IP
+-\&.SUFFIXES: .out .o .c .e .r .f .y .l .s
+-.PP
+-The rule to create a file with suffix
+-.I s2
+-that depends on a similarly named file with suffix
+-.I s1
+-is specified as an entry
+-for the `target'
+-.IR s1s2 .
+-In such an entry, the special macro $* stands for
+-the target name with suffix deleted, $@ for the full target name,
+-$< for the complete list of prerequisites,
+-and
+-$? for the list of prerequisites that are out of date.
+-For example, a rule for making
+-optimized `.o' files from `.c' files is
+-.IP
+-\&.c.o: ; cc \-c \-O \-o $@ $*.c
+-.PP
+-Certain macros are used by the default inference rules
+-to communicate optional arguments to
+-any resulting compilations.
+-In particular, `CFLAGS' is used for
+-.I cc
+-and 
+-.IR f77 (1)
+-options, `LFLAGS' and `YFLAGS' for 
+-.I lex
+-and
+-.IR yacc (1)
+-options.
+-.PP
+-Command lines are executed one at a time, each by its
+-own shell.
+-A line is printed when it is executed unless
+-the special target `.SILENT'
+-is in 
+-.I makefile,
+-or the first character of the command is `@'.
+-.PP
+-Commands returning nonzero status (see
+-.IR intro (1))
+-cause
+-.I make
+-to terminate unless
+-the special target `.IGNORE' is in
+-.I makefile
+-or the command begins with
+-<tab><hyphen>.
+-.PP
+-Interrupt and quit cause the target to be deleted
+-unless the target depends on the special name `.PRECIOUS'.
+-.PP
+-Other options:
+-.TP
+-.B \-i
+-Equivalent to the special entry `.IGNORE:'.
+-.TP
+-.B \-k
+-When a command returns nonzero status,
+-abandon work on the current entry, but
+-continue on branches that do not depend on the current entry.
+-.TP
+-.B \-n
+-Trace and print, but do not execute the commands
+-needed to update the targets.
+-.TP
+-.B \-t
+-Touch, i.e. update the modified date of targets, without
+-executing any commands.
+-.TP
+-.B \-r
+-Equivalent to an initial special entry `.SUFFIXES:'
+-with no list.
+-.TP 
+-.B \-s
+-Equivalent to the special entry
+-`.SILENT:'.
+-.SH FILES
+-makefile, Makefile
+-.br
+-.SH "SEE ALSO"
+-sh(1), touch(1)
+-.br
+-S. I. Feldman
+-.I
+-Make \- A Program for Maintaining Computer Programs
+-.SH BUGS
+-Some commands return nonzero status inappropriately.
+-Use
+-.B \-i
+-to overcome the difficulty.
+-.br
+-Commands that are directly executed by the shell,
+-notably
+-.IR  cd (1),
+-are ineffectual across newlines in
+-.I make.
+//GO.SYSIN DD make.1
+echo man.1
+sed 's/.//' >man.1 <<'//GO.SYSIN DD man.1'
+-.TH MAN 1
+-.SH NAME
+-man \- print sections of this manual
+-.SH SYNOPSIS
+-.B man
+-[ option ... ] [ chapter ] title ...
+-.SH DESCRIPTION
+-.I Man
+-locates and prints the section of this manual named
+-.I title
+-in the specified
+-.IR chapter .
+-(In this context, the word `page' is often used as a synonym for `section'.)\ 
+-The
+-.I title
+-is entered in lower case.
+-The
+-.I chapter
+-number does not need a letter suffix.
+-If no
+-.I chapter
+-is specified, the whole manual is searched for
+-.I title
+-and all occurrences of it are printed.
+-.PP
+-.I Options
+-and their meanings are:
+-.TP 
+-.B \-t
+-Phototypeset the section using
+-.IR troff (1).
+-.TP
+-.B \-n
+-Print the section on the standard output using
+-.IR nroff (1).
+-.TP
+-.B \-k
+-Display the output on a Tektronix 4014 terminal using
+-.IR troff (1)
+-and
+-.IR tc (1).
+-.TP
+-.B \-e
+-Appended or prefixed to any of the above
+-causes the manual section to be preprocessed by
+-.I neqn
+-or
+-.IR eqn (1);
+-.B \-e
+-alone means
+-.BR \-te .
+-.TP
+-.B \-w
+-Print the path names of the manual sections,
+-but do not print the sections themselves.
+-.TP
+-(default)
+-Copy an already formatted manual section to the terminal,
+-or, if none is available, act as
+-.BR \-n .
+-It may be necessary to use a filter to adapt the output to
+-the
+-particular terminal's characteristics.
+-.PP
+-Further
+-.I options,
+-e.g. to specify the kind of terminal you have,
+-are passed on to
+-.IR troff (1)
+-or
+-.IR nroff .
+-.I Options
+-and
+-.I chapter
+-may be changed before each
+-.IR title .
+-.PP
+-For example:
+-.IP
+-man man
+-.PP
+-would reproduce this section,
+-as well as any other sections named
+-.I man
+-that may exist in other chapters of the manual, e.g. 
+-.IR man (7).
+-.SH FILES
+-/usr/man/man?/\(**
+-.br
+-/usr/man/cat?/\(**
+-.SH "SEE ALSO"
+-nroff(1),
+-eqn(1),
+-tc(1),
+-man(7)
+-.SH BUGS
+-The manual is supposed to be reproducible either on
+-a phototypesetter or on a terminal.
+-However, on a terminal some information is necessarily lost.
+//GO.SYSIN DD man.1
+echo mesg.1
+sed 's/.//' >mesg.1 <<'//GO.SYSIN DD mesg.1'
+-.TH MESG 1 
+-.SH NAME
+-mesg  \-  permit or deny messages
+-.SH SYNOPSIS
+-.B mesg
+-[
+-.B n
+-] [
+-.B y
+-]
+-.SH DESCRIPTION
+-.I Mesg
+-with argument
+-.B n
+-forbids messages via
+-.IR  write (1)
+-by revoking non-user
+-write permission on the user's terminal.
+-.I Mesg
+-with argument
+-.B y
+-reinstates permission.
+-All by itself,
+-.I mesg
+-reports the current state without changing it.
+-.SH FILES
+-/dev/tty*
+-.br
+-/dev
+-.SH "SEE ALSO"
+-write(1)
+-.SH DIAGNOSTICS
+-Exit status is 0 if messages are receivable,
+-1 if not, 2 on error.
+//GO.SYSIN DD mesg.1
+echo mkconf.1m
+sed 's/.//' >mkconf.1m <<'//GO.SYSIN DD mkconf.1m'
+-.TH MKCONF 1M
+-.SH NAME
+-mkconf \- generate configuration tables
+-.SH SYNOPSIS
+-mkconf
+-.SH DESCRIPTION
+-.I Mkconf
+-examines a machine configuration table on its
+-standard input.
+-Its output is a pair of files
+-.I l.s
+-and
+-.I c.c.
+-The first is an assembler program that represents the interrupt vectors
+-located in low memory addresses;
+-the second contains initialized
+-block and character device switch tables.
+-.PP
+-Input to
+-.I mkconf
+-is a sequence of lines.
+-The following describe devices on the machine:
+-.PP
+-.RS 5
+-.nf
+-.DS
+-pc    (PC11)
+-lp    (LP11)
+-rf    (RS11)
+-hs    (RS03/RS04)
+-tc    (TU56)
+-rk    (RK03/RK05)
+-tm    (TU10)
+-rp    (RP03)
+-hp    (RP04/5/6)
+-ht    (TU16)
+-dc*   (DC11)
+-kl*   (KL11/DL11-ABC)
+-dl*   (DL11-E)
+-dp*   (DP11)
+-dn*   (DN11)
+-dh*   (DH11)
+-dhdm* (DM11-BB)
+-du*   (DU11)
+-.RE
+-.fi
+-.PP
+-The devices marked with * may be preceded by a number telling
+-how many are to be included.
+-The console typewrite is automatically included;
+-don't count it as part of the KL or DL specification.
+-Count DN's in units of 4 (1 system unit).
+-.PP
+-The following lines are also accepted.
+-.TP 5
+-.BI "root " "dev minor"
+-The specified block device (e.g.
+-.BR hp )
+-is used for the root.
+-.I minor
+-is a decimal number giving the minor device.
+-This line must appear exactly once.
+-.TP 5
+-.BI "swap " "dev minor"
+-The specified block device is used for swapping.
+-If not given the root is used.
+-.TP 5
+-.BI "pipe " "dev minor"
+-The specified block device
+-is used to store pipes.
+-If not given the root is used.
+-.TP 5
+-.BI "swplo " number
+-.TP 5
+-.BI "nswap " number
+-Sets the origin (block number) and size of the area used for
+-swapping.
+-By default, the not very useful numbers
+-4000 and 872.
+-.TP 5
+-.B pack
+-Include the packet driver.
+-By default it is left out.
+-.TP 5
+-.B mpx
+-Include the multiplexor driver.
+-By default it is left out.
+-.SH FILES
+-l.s, c.c      output files
+-.SH SEE ALSO
+-`Setting up Unix', in Volume 2.
+-.SH BUGS
+-The set of devices it knows about, the set of drivers included,
+-and the set of devices on the machine
+-are mutually incomparable.
+-Some handwork is certain to be necessary.
+-Because of floating vectors that may have been missed,
+-It is mandatory to check the
+-.I l.s
+-file to make sure it corresponds with reality.
+//GO.SYSIN DD mkconf.1m
+echo mkdir.1
+sed 's/.//' >mkdir.1 <<'//GO.SYSIN DD mkdir.1'
+-.TH MKDIR 1 
+-.SH NAME
+-mkdir  \-  make a directory
+-.SH SYNOPSIS
+-.B mkdir
+-dirname ...
+-.SH DESCRIPTION
+-.I Mkdir
+-creates specified directories
+-in mode 777.
+-Standard entries,
+-.RB ` . ',
+-for the directory itself,
+-and 
+-.BR ` .. '
+-for its parent, are made automatically.
+-.PP
+-.I Mkdir
+-requires write permission in the parent directory.
+-.SH "SEE ALSO"
+-rm(1)
+-.SH DIAGNOSTICS
+-.I Mkdir
+-returns exit code 0 if all directories were successfully made.
+-Otherwise it prints a diagnostic and returns nonzero.
+//GO.SYSIN DD mkdir.1
+echo mkfs.1m
+sed 's/.//' >mkfs.1m <<'//GO.SYSIN DD mkfs.1m'
+-.TH MKFS 1M 
+-.SH NAME
+-mkfs \- construct a file system
+-.SH SYNOPSIS
+-.B /etc/mkfs
+-special
+-proto
+-.SH DESCRIPTION
+-.I Mkfs
+-constructs a file system
+-by writing on the special file
+-.I special
+-according to the directions
+-found in
+-the prototype file
+-.I proto.
+-The prototype file
+-contains tokens separated by spaces or
+-new lines.
+-The first token is the name of a file
+-to be copied onto block zero as
+-the bootstrap program,
+-see
+-.IR bproc (8).
+-The second token is a number specifying the
+-size of the created file system.
+-Typically it will be the number of blocks on the device,
+-perhaps diminished
+-by space for swapping.
+-The next token is the number of i-nodes
+-in the i-list.
+-The next set of tokens comprise the specification
+-for the root file.
+-File specifications consist of tokens
+-giving the mode,
+-the user-id,
+-the group id,
+-and the initial contents of the file.
+-The syntax of the contents field
+-depends on the mode.
+-.PP
+-The mode token for a file is a 6 character string.
+-The first character
+-specifies the type of the file.
+-(The characters
+-.B \-bcd
+-specify regular, block special,
+-character special and directory files
+-respectively.)
+-The second character of the type
+-is either
+-.B u
+-or
+-.B \-
+-to specify set-user-id mode or not.
+-The third is
+-.B g
+-or
+-.B \-
+-for the set-group-id mode.
+-The rest of the mode
+-is a three digit octal number giving the
+-owner, group, and other read, write, execute
+-permissions, see
+-.IR chmod (1).
+-.PP
+-Two decimal number
+-tokens come after the mode; they specify the
+-user and group ID's of the owner of the file.
+-.PP
+-If the file is a regular file,
+-the next token is a pathname
+-whence the contents and size are copied.
+-.PP
+-If the file is a block or character special file,
+-two decimal number tokens
+-follow which give the major and minor device numbers.
+-.PP
+-If the file is a directory,
+-.I mkfs
+-makes the entries
+-.BR . ""
+-and
+-.B  ..
+-and then
+-reads a list of names and
+-(recursively)
+-file specifications for the entries
+-in the directory.
+-The scan is terminated with the
+-token
+-.BR $ .
+-.PP
+-If the prototype file cannot be opened and
+-its name consists of a string of digits,
+-.I mkfs
+-builds a file system with a single
+-empty directory on it.
+-The size of the file system is the value
+-of
+-.I proto
+-interpreted as a decimal number.
+-The number of i-nodes is calculated
+-as a function of the filsystem size.
+-The boot program is left uninitialized.
+-.PP
+-A sample prototype specification follows:
+-.PP
+-.nf
+-.in +5
+-/usr/mdec/uboot
+-4872 55
+-d\-\-777 3 1
+-usr   d\-\-777 3 1
+-      sh      \-\-\-755 3 1 /bin/sh
+-      ken     d\-\-755 6 1
+-              $
+-      b0      b\-\-644 3 1 0 0
+-      c0      c\-\-644 3 1 0 0
+-      $
+-$
+-.in -5
+-.fi
+-.SH "SEE ALSO"
+-filsys(5),
+-dir(5),
+-bproc(8)
+-.SH BUGS
+-There should be some way to specify links.
+//GO.SYSIN DD mkfs.1m
+echo mknod.1m
+sed 's/.//' >mknod.1m <<'//GO.SYSIN DD mknod.1m'
+-.TH MKNOD 1M 
+-.SH NAME
+-mknod \- build special file
+-.SH SYNOPSIS
+-.B /etc/mknod
+-name
+-[
+-.B c
+-] [
+-.B b
+-]
+-major
+-minor
+-.SH DESCRIPTION
+-.I Mknod
+-makes a special file.
+-The first argument is the
+-.I name
+-of the entry.
+-The second is
+-.B b
+-if the special file is block-type (disks, tape) or
+-.B c
+-if it is character-type (other devices).
+-The last two arguments are
+-numbers specifying the
+-.I major
+-device type
+-and the
+-.I minor
+-device (e.g. unit, drive, or line number).
+-.PP
+-The assignment of major device numbers is specific to each system.
+-They have to be dug out of the
+-system source file
+-.I conf.c.
+-.SH "SEE ALSO"
+-mknod(2)
+//GO.SYSIN DD mknod.1m
+echo mount.1m
+sed 's/.//' >mount.1m <<'//GO.SYSIN DD mount.1m'
+-.TH MOUNT 1M 
+-.SH NAME
+-mount, umount \- mount and dismount file system
+-.SH SYNOPSIS
+-.B /etc/mount
+-[ special name [
+-.B \-r
+-] ]
+-.PP
+-.B /etc/umount
+-special
+-.SH DESCRIPTION
+-.I Mount
+-announces to the system that a removable file system
+-is present on the device
+-.I special.
+-The file
+-.I name
+-must exist already; it
+-must be a directory (unless the root of the
+-mounted file system is not a directory).
+-It becomes the name of the newly mounted root.
+-The optional last argument indicates that the file system
+-is to be mounted read-only.
+-.PP
+-.I Umount
+-announces to the system that the removable file system previously
+-mounted on device
+-.I special
+-is to be removed.
+-.PP
+-These commands
+-maintain a table of mounted devices.
+-If invoked without an argument,
+-.I mount
+-prints the table.
+-.PP
+-Physically write-protected and magnetic tape file
+-systems must be mounted read-only
+-or errors will occur when access times are updated,
+-whether or not any explicit write is attempted.
+-.SH FILES
+-/etc/mtab: mount table
+-.SH "SEE ALSO"
+-mount(2),
+-mtab(5)
+-.SH BUGS
+-Mounting file systems full of garbage will crash the system.
+-.br
+-Mounting a root directory on a non-directory
+-makes some apparently good pathnames invalid.
+//GO.SYSIN DD mount.1m
+echo mv.1
+sed 's/.//' >mv.1 <<'//GO.SYSIN DD mv.1'
+-.TH MV 1 
+-.SH NAME
+-mv  \-  move or rename files and directories
+-.SH SYNOPSIS
+-.B mv
+-file1 file2
+-.PP
+-.B mv
+-file ... directory
+-.SH DESCRIPTION
+-.I Mv
+-moves (changes the name of)
+-.I file1
+-to
+-.IR file2 .
+-.PP
+-If
+-.I file2
+-already exists,
+-it is removed before
+-.I file1
+-is moved.
+-If
+-.I file2
+-has a mode which forbids writing,
+-.I mv
+-prints the mode (see
+-.IR chmod (2))
+-and
+-reads the standard input to obtain a line;
+-if the line begins with
+-.B y,
+-the move takes place;
+-if not,
+-.I mv
+-exits.
+-.PP
+-In the second form,
+-one or more
+-.I files
+-are moved to the
+-.I directory
+-with their original
+-file-names.
+-.PP
+-.I Mv
+-refuses to move a file onto itself.
+-.SH "SEE ALSO"
+-cp(1), chmod(2)
+-.SH BUGS
+-If
+-.I file1
+-and
+-.I file2
+-lie on different file systems,
+-.I mv
+-must copy the file and delete the original.
+-In this case the owner name becomes
+-that of the copying process and any
+-linking relationship with other files
+-is lost.
+-.PP
+-.I Mv
+-should take
+-.B \-f
+-flag, like
+-.I rm,
+-to suppress the question
+-if the target exists and is not writable.
+//GO.SYSIN DD mv.1
+echo ncheck.1m
+sed 's/.//' >ncheck.1m <<'//GO.SYSIN DD ncheck.1m'
+-.TH NCHECK 1M 
+-.SH NAME
+-ncheck  \-  generate names from i-numbers
+-.SH SYNOPSIS
+-.B ncheck
+-[
+-.B \-i
+-numbers ]  [
+-.B \-a
+-] [
+-.B \-s
+-]  [ filesystem ]
+-.SH DESCRIPTION
+-.I Ncheck
+-with no argument
+-generates a pathname vs. i-number
+-list of all files
+-on a set of default file systems.
+-Names of directory files are followed by `/\fB.\fR'.
+-The
+-.B \-i
+-option reduces the report to only those files whose i-numbers follow.
+-The
+-.B \-a
+-option
+-allows printing of the names
+-.RB ` . '
+-and
+-.RB ` .. ',
+-which are ordinarily suppressed.
+-suppressed.
+-The
+-.B \-s
+-option reduces the report to special files
+-and files with set-user-ID mode;
+-it is intended to discover concealed violations
+-of security policy.
+-.PP
+-A file system may be specified.
+-.PP
+-The report is in no useful
+-order, and probably should be sorted.
+-.SH "SEE ALSO"
+-dcheck(1), icheck(1), sort(1)
+-.SH DIAGNOSTICS
+-When the filesystem structure is improper,
+-`??' denotes the `parent' of
+-a parentless file and
+-a pathname beginning with `...' denotes a loop.
+//GO.SYSIN DD ncheck.1m
+echo newgrp.1
+sed 's/.//' >newgrp.1 <<'//GO.SYSIN DD newgrp.1'
+-.TH NEWGRP 1 
+-.SH NAME
+-newgrp \- log in to a new group
+-.SH SYNOPSIS
+-.B newgrp
+-group
+-.SH DESCRIPTION
+-.I Newgrp
+-changes the group identification of its caller,
+-analogously to
+-.IR  login (1).
+-The same person remains logged in,
+-and the current directory is unchanged,
+-but calculations of access permissions to files are
+-performed with respect to the
+-new group ID.
+-.PP
+-A password is demanded if the group has
+-a password and the user himself does not.
+-.PP
+-When most users log in, they
+-are members of the group named `other.'
+-.I Newgrp
+-is known to the shell, which executes it directly without a fork.
+-.SH FILES
+-/etc/group, /etc/passwd
+-.SH "SEE ALSO"
+-login(1), group(5)
+//GO.SYSIN DD newgrp.1
+echo nice.1
+sed 's/.//' >nice.1 <<'//GO.SYSIN DD nice.1'
+-.TH NICE 1 
+-.SH NAME
+-nice, nohup \- run a command at low priority
+-.SH SYNOPSIS
+-.B nice
+-[
+-.BI \- number
+-]
+-command [ arguments ]
+-.PP
+-.B nohup
+-command [ arguments ]
+-.SH DESCRIPTION
+-.I Nice
+-executes
+-.I command
+-with low scheduling priority.
+-If the
+-.I number
+-argument is present, the priority is incremented (higher
+-numbers mean lower priorities) by that amount up to a limit of 20.
+-The default
+-.I number
+-is 10.
+-.PP
+-The super-user may run commands with
+-priority higher than normal
+-by using a negative priority,
+-e.g. `\-\-10'.
+-.PP
+-.I Nohup
+-executes
+-.I command
+-immune to hangup and terminate signals from the controlling terminal.
+-The priority is incremented by 5.
+-.I Nohup
+-should be invoked from the shell with `&' in order to 
+-prevent it from responding to interrupts by or
+-stealing the input from
+-the next person who logs in on the same terminal.
+-.SH FILES
+-nohup.out standard output and standard error file under
+-.I nohup
+-.SH "SEE ALSO"
+-nice(2)
+-.SH DIAGNOSTICS
+-.I Nice
+-returns the exit status of the subject command.
+//GO.SYSIN DD nice.1
+echo nm.1
+sed 's/.//' >nm.1 <<'//GO.SYSIN DD nm.1'
+-.TH NM 1 
+-.SH NAME
+-nm  \-  print name list
+-.SH SYNOPSIS
+-.B nm
+-[
+-.B \-gnopru
+-]
+-[ file ... ]
+-.SH DESCRIPTION
+-.I Nm
+-prints the name list (symbol table) of each object
+-.I file
+-in the argument list.
+-If an argument
+-is an archive, a listing for each object
+-file in the archive will be produced.
+-If no
+-.I file
+-is given, the symbols in
+-`a.out'
+-are listed.
+-.PP
+-Each symbol name is preceded by its value (blanks if undefined)
+-and one of the letters
+-.SM
+-.B U
+-(undefined),
+-.SM
+-.B A
+-(absolute),
+-.SM
+-.B  T
+-(text segment symbol),
+-.SM
+-.B D
+-(data segment symbol),
+-.SM
+-.B B
+-(bss segment symbol),
+-or
+-.SM
+-.B C
+-(common symbol).
+-If the symbol is local (non-external) the type letter is in
+-lower case.
+-The output is sorted alphabetically.
+-.PP
+-Options are:
+-.TP
+-.B  \-g
+-Print only global (external) symbols.
+-.TP
+-.B \-n
+-Sort numerically rather than alphabetically.
+-.TP
+-.B  \-o
+-Prepend file or archive element name to each
+-output line rather than only once.
+-.TP
+-.B  \-p
+-Don't sort; print in symbol-table order.
+-.TP
+-.B  \-r
+-Sort in reverse order.
+-.TP
+-.B  \-u
+-Print only undefined symbols.
+-.sh FILES
+-.SH SEE ALSO
+-ar(1), ar(5), a.out(5)
+//GO.SYSIN DD nm.1
+echo od.1
+sed 's/.//' >od.1 <<'//GO.SYSIN DD od.1'
+-.TH OD 1 
+-.SH NAME
+-od  \-  octal dump
+-.SH SYNOPSIS
+-.B od
+-[
+-.B \-bcdox
+-] [ file ] [ [
+-.B +
+-]offset[
+-.BR ". " "]["
+-\fBb\fR ] ]
+-.SH DESCRIPTION
+-.I Od
+-dumps
+-.I file
+-in
+-one or more formats
+-as
+-selected by the first argument.
+-If the first argument is missing,
+-.B \-o
+-is default.
+-The meanings of the format argument characters
+-are:
+-.TP 3
+-.B  b
+-Interpret bytes in octal.
+-.TP 3
+-.B  c
+-Interpret bytes in ASCII.
+-Certain non-graphic characters appear as C escapes:
+-null=\e0,
+-backspace=\eb,
+-formfeed=\ef,
+-newline=\en,
+-return=\er,
+-tab=\et;
+-others appear as 3-digit octal numbers.
+-.TP 3
+-.B  d
+-Interpret words in decimal.
+-.TP 3
+-.B  o
+-Interpret words in octal.
+-.TP 3
+-.B  x
+-Interpret words in hex.
+-.PP
+-The
+-.I file
+-argument specifies which file is to be dumped.
+-If no file argument is specified,
+-the standard input is used.
+-.PP
+-The offset argument specifies the offset
+-in the file where dumping is to commence.
+-This argument is normally interpreted
+-as octal bytes.
+-If `\fB.\fR' is appended, the offset is interpreted in
+-decimal.
+-If `\fBb\fR' is appended, the offset is interpreted in
+-blocks of 512 bytes.
+-If the file argument is omitted,
+-the offset argument must be preceded 
+-.RB ` + '.
+-.PP
+-Dumping continues until end-of-file.
+-.SH "SEE ALSO"
+-adb(1)
+//GO.SYSIN DD od.1
+echo passwd.1
+sed 's/.//' >passwd.1 <<'//GO.SYSIN DD passwd.1'
+-.TH PASSWD 1 
+-.SH NAME
+-passwd \- change login password
+-.SH SYNOPSIS
+-.B passwd
+-[ name ]
+-.SH DESCRIPTION
+-This command changes (or installs) a password
+-associated with the user
+-.IR name
+-(your own name by default).
+-.PP
+-The program prompts for the old password and then for the new one.
+-The caller must supply both.
+-The new password must be typed twice, to forestall mistakes.
+-.PP
+-New passwords must be at least four characters long if they use
+-a sufficiently rich alphabet and at least six characters long
+-if monocase.
+-These rules are relaxed if you are insistent enough.
+-.PP
+-Only the owner of the name or the super-user may change a password;
+-the owner must prove he knows the old password.
+-.SH FILES
+-/etc/passwd
+-.SH "SEE ALSO"
+-login(1), passwd(5), crypt(3)
+-.br
+-Robert Morris and Ken Thompson,
+-.I Password Security: A Case History
+//GO.SYSIN DD passwd.1
+echo plot.1g
+sed 's/.//' >plot.1g <<'//GO.SYSIN DD plot.1g'
+-.TH PLOT 1G 
+-.SH NAME
+-plot \- graphics filters
+-.SH SYNOPSIS
+-.B plot
+-[
+-.BR \-T terminal
+-[ raster ] ]
+-.SH DESCRIPTION
+-These commands read plotting instructions (see
+-.IR  plot (5))
+-from the standard input,
+-and in general
+-produce plotting instructions suitable for
+-a particular
+-.I terminal
+-on the standard output.
+-.PP
+-If no
+-.I terminal
+-type is specified, the environment parameter $TERM
+-(see
+-.IR environ (5))
+-is used.
+-Known
+-.I terminals
+-are:
+-.TP
+-4014
+-Tektronix 4014 storage scope.
+-.TP
+-450
+-DASI Hyterm 450 terminal (Diablo mechanism).
+-.TP
+-300
+-DASI 300 or GSI terminal (Diablo mechanism).
+-.TP
+-300S
+-DASI 300S terminal (Diablo mechanism).
+-.TP
+-ver
+-Versatec D1200A printer-plotter.
+-This version of
+-.I plot
+-places a scan-converted
+-image in `/usr/tmp/raster' and sends the
+-result directly to the plotter device rather than to
+-the standard output.
+-The optional argument causes a previously
+-scan-converted file
+-.I raster
+-to be sent to the plotter.
+-.SH FILES
+-/usr/bin/tek
+-.br
+-/usr/bin/t450
+-.br
+-/usr/bin/t300
+-.br
+-/usr/bin/t300s
+-.br
+-/usr/bin/vplot
+-.br
+-/usr/tmp/raster 
+-.SH "SEE ALSO"
+-plot(3), plot(5)
+-.SH BUGS
+-There is no lockout protection
+-for /usr/tmp/raster.
+//GO.SYSIN DD plot.1g
+echo pr.1
+sed 's/.//' >pr.1 <<'//GO.SYSIN DD pr.1'
+-.TH PR 1 
+-.SH NAME
+-pr  \-  print file
+-.SH SYNOPSIS
+-.B pr
+-[ option ] ...
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Pr
+-produces a printed listing of one or more
+-.I files.
+-The output is separated into pages headed by a date,
+-the name of the file or a specified header, and the page number.
+-If there are no file arguments,
+-.I pr
+-prints its standard input.
+-.PP
+-Options apply to all following files but may be reset
+-between files:
+-.TP
+-.BI \- n
+-Produce
+-.IR n -column
+-output.
+-.TP
+-.BI + n
+-Begin printing with page
+-.I  n.
+-.TP
+-.B  \-h
+-Take the next argument as a page header.
+-.TP
+-.BI \-w n
+-For purposes of multi-column output,
+-take the width of the page to be
+-.I n
+-characters instead of the default 72.
+-.TP
+-.BI \-l n
+-Take the length of the page to be
+-.I n
+-lines instead of the default 66.
+-.TP
+-.B  \-t
+-Do not print the 5-line header or the
+-5-line trailer normally supplied for each page.
+-.TP
+-.BI \-s c
+-Separate columns by the single character
+-.I c
+-instead of by the appropriate amount of white space.
+-A missing
+-.I c
+-is taken to be a tab.
+-.TP
+-.B  \-m
+-Print all
+-.I files
+-simultaneously,
+-each in one column,
+-.PP
+-Inter-terminal messages via
+-.IR write (1)
+-are
+-forbidden during a
+-.IR pr .
+-.SH FILES
+-/dev/tty?
+-to suspend messages.
+-.SH "SEE ALSO"
+-cat(1)
+-.SH DIAGNOSTICS
+-There are no diagnostics when
+-.I pr
+-is printing on a terminal.
+//GO.SYSIN DD pr.1
+echo prep.1
+sed 's/.//' >prep.1 <<'//GO.SYSIN DD prep.1'
+-.TH PREP 1 
+-.SH NAME
+-prep \- prepare text for statistical processing
+-.SH SYNOPSIS
+-.B prep
+-[
+-.B \-dio
+-]
+-file ...
+-.SH DESCRIPTION
+-.I Prep
+-reads each
+-.I file
+-in sequence
+-and writes it on the standard output,
+-one `word' to a line.
+-A word is a string of alphabetic characters
+-and imbedded apostrophes,
+-delimited by space or punctuation.
+-Hyphented words are broken apart;
+-hyphens at the end of lines are removed and the
+-hyphenated parts are joined.
+-Strings of digits are discarded.
+-.PP
+-The following option letters may appear in any order:
+-.TP
+-.B \-d
+-Print the word number (in the input
+-stream) with each word.
+-.TP
+-.B \-i
+-Take the next
+-.I file
+-as an `ignore' file.
+-These words will not appear in the output.
+-(They will be counted, for purposes of the
+-.B \-d
+-count.)
+-.TP
+-.B \-o
+-Take the next 
+-.I file
+-as an `only' file.
+-Only these words will appear in the output.
+-(All other words will also be counted for
+-the 
+-.B \-d
+-count.)
+-.TP
+-.B \-p
+-Include punctuation marks (single nonalphanumeric characters)
+-as separate output lines.
+-The punctuation marks are not counted for the
+-.B \-d
+-count.
+-.PP
+-Ignore and only files contain words, one per line.
+-.SH SEE ALSO
+-deroff(1)
+//GO.SYSIN DD prep.1
+echo prof.1
+sed 's/.//' >prof.1 <<'//GO.SYSIN DD prof.1'
+-.TH PROF 1 
+-.SH NAME
+-prof \- display profile data
+-.SH SYNOPSIS
+-.B prof
+-[
+-.B \-v
+-] [
+-.B \-a
+-] [
+-.B \-l
+-] [
+-.BI \- "low\fR [ \fB\-\fIhigh\fR ]"
+-] [ file ]
+-.SH DESCRIPTION
+-.I Prof
+-interprets the file
+-.I mon.out
+-produced by the
+-.I monitor
+-subroutine.
+-Under default modes,
+-the symbol table in the
+-named object file
+-.I (a.out
+-default)
+-is read and correlated with the
+-.I mon.out
+-profile file.
+-For each external symbol, the percentage
+-of time spent executing between that symbol
+-and the next
+-is printed (in decreasing order),
+-together with the number of times that routine was called
+-and the number of milliseconds per call.
+-.PP
+-If the
+-.B \-a
+-option is used,
+-all symbols are reported rather than
+-just external symbols.
+-If the
+-.B \-l
+-option
+-is used,
+-the output is listed by
+-symbol value rather than
+-decreasing percentage.
+-.PP
+-If the
+-.B \-v
+-option is used,
+-all printing is suppressed
+-and a graphic version of the profile
+-is produced
+-on the standard output for display by the
+-.IR  plot (1)
+-filters.
+-The numbers
+-.I low
+-and 
+-.I high,
+-by default 0 and 100, cause a selected
+-percentage of the profile to be plotted
+-with accordingly higher resolution.
+-.PP
+-In order for the number of calls to a routine to be tallied,
+-the
+-.B \-p
+-option of
+-.I cc
+-must have been given when the file containing the
+-routine was compiled.
+-This option also arranges for the
+-.I mon.out
+-file to be produced automatically.
+-.SH FILES
+-.ta \w'mon.out  'u
+-mon.out       for profile
+-.br
+-a.out         for namelist
+-.SH "SEE ALSO"
+-monitor(3), profil(2), cc(1), plot(1)
+-.SH BUGS
+-Beware of quantization errors.
+//GO.SYSIN DD prof.1
+echo ps.1
+sed 's/.//' >ps.1 <<'//GO.SYSIN DD ps.1'
+-.TH PS 1  PDP11
+-.SH NAME
+-ps \- process status
+-.SH SYNOPSIS
+-.B ps
+-[
+-.B aklx
+-]
+-[ namelist ]
+-.SH DESCRIPTION
+-.I Ps
+-prints certain indicia about active
+-processes.
+-The
+-.B a
+-option asks for information about all processes with terminals (ordinarily
+-only one's own processes are displayed);
+-.B x
+-asks even about processes with no terminal;
+-.B l
+-asks for a long listing.
+-The short listing contains the process ID, tty letter,
+-the cumulative execution time of the process and an
+-approximation to the command line.
+-.PP
+-The long listing is columnar and contains
+-.TP
+-F
+-Flags associated with the process.
+-01: in core;
+-02: system process;
+-04: locked in core (e.g. for physical I/O);
+-10: being swapped;
+-20: being traced by another process.
+-.TP
+-S
+-The state of the process.
+-0: nonexistent;
+-S: sleeping;
+-W: waiting;
+-R: running;
+-I: intermediate;
+-Z: terminated;
+-T: stopped.
+-.TP
+-UID
+-The user ID of the process owner.
+-.TP
+-PID
+-The process ID of the process; as in certain cults it is possible to kill a process
+-if you know its true name.
+-.TP
+-PPID
+-The process ID of the parent process.
+-.TP
+-CPU
+-Processor utilization for scheduling.
+-.TP
+-PRI
+-The priority of the
+-process; high numbers mean low priority.
+-.TP
+-NICE
+-Used in priority computation.
+-.TP
+-ADDR
+-The core address of the process if resident,
+-otherwise the disk address.
+-.TP
+-SZ
+-The size in blocks of the core image of the process.
+-.TP
+-WCHAN
+-The event for which the process is waiting or sleeping;
+-if blank, the process is running.
+-.TP
+-TTY
+-The controlling tty for the process.
+-.TP
+-TIME
+-The cumulative execution time for the process.
+-.TP TIME
+-The command and its arguments.
+-.DT
+-.PP
+-A process that has exited and has a parent, but has not
+-yet been waited for by the parent is marked <defunct>.
+-.I Ps
+-makes an educated guess as to the file name
+-and arguments given when the process was created
+-by examining core memory or the swap area.
+-The method is inherently somewhat unreliable and in any event
+-a process is entitled to destroy this information,
+-so the names cannot be counted on too much.
+-.PP
+-If the
+-.B k
+-option is specified,
+-the file
+-.I /usr/sys/core
+-is used in place of
+-.IR /dev/mem .
+-This is used for
+-postmortem system debugging.
+-If a second argument is given,
+-it is taken to be the file containing the system's namelist.
+-.SH FILES
+-.ta \w'/usr/sys/core 'u
+-/unix         system namelist
+-.br
+-/dev/mem      core memory
+-.br
+-/usr/sys/core alternate core file
+-.br
+-/dev          searched to find swap device and tty names
+-.SH "SEE ALSO"
+-kill(1)
+-.SH BUGS
+-Things can change while
+-.I ps
+-is running; the picture it gives is only a close
+-approximation to reality.
+-.br
+-Some data printed for defunct processes is irrelevant
+//GO.SYSIN DD ps.1
+echo pstat.1m
+sed 's/.//' >pstat.1m <<'//GO.SYSIN DD pstat.1m'
+-.TH PSTAT 1M
+-.SH NAME
+-pstat \- print system facts
+-.SH SYNOPSIS
+-.B pstat
+-[
+-.B \-aixptuf
+-] [ suboptions ]
+-[ file ]
+-.SH DESCRIPTION
+-.I Pstat
+-interprets the contents of certain system tables.
+-If
+-.I file
+-is given, the tables are sought there, otherwise
+-in
+-.I /dev/mem.
+-The required namelist is taken from
+-.I /unix.
+-Options are
+-.TP \w'WCHAN\ 'u
+-.B \-a
+-Under
+-.BR \-p ,
+-describe all process slots rather than just active ones.
+-.TP
+-.B \-i
+-Print the inode table with the these headings:
+-.IP LOC
+-The core location of this table entry.
+-.PD 0
+-.IP FLAGS
+-Miscellaneous state variables encoded thus:
+-.RS
+-.IP L
+-locked
+-.IP U
+-update time
+-.IR filsys (5))
+-must be corrected
+-.IP A
+-access time must be corrected
+-.IP M
+-file system is mounted here
+-.IP W
+-wanted by another process (L flag is on)
+-.IP T
+-contains a text file
+-.IP C
+-changed time must be corrected
+-.RE
+-.IP CNT
+-Number of open file table entries for this inode.
+-.IP DEV
+-Major and minor device number of file system in which
+-this inode resides.
+-.IP INO
+-I-number within the device.
+-.IP MODE
+-Mode bits, see
+-.IR chmod (2).
+-.IP NLK
+-Number of links to this inode.
+-.IP UID
+-User ID of owner.
+-.IP SIZ/DEV
+-Number of bytes in an ordinary file, or
+-major and minor device of special file.
+-.PD
+-.TP
+-.B \-x
+-Print the text table with these headings:
+-.IP LOC
+-The core location of this table entry.
+-.PD 0
+-.IP FLAGS
+-Miscellaneous state variables encoded thus:
+-.RS
+-.IP T
+-.IR ptrace (2)
+-in effect
+-.IP W
+-text not yet written on swap device
+-.IP L
+-loading in progress
+-.IP K
+-locked
+-.IP w
+-wanted (L flag is on)
+-.RE
+-.PD
+-.IP DADDR
+-Disk address in swap, measured in multiples of 512 bytes.
+-.IP CADDR
+-Core address, measured in multiples of 64 bytes.
+-.IP SIZE
+-Size of text segment, measured in multiples of 64 bytes.
+-.IP IPTR
+-Core location of corresponding inode.
+-.IP CNT
+-Number of processes using this text segment.
+-.IP CCNT
+-Number of processes in core using this text segment.
+-.PD
+-.TP
+-.B \-p
+-Print process table for active processes with these headings:
+-.IP LOC
+-The core location of this table entry.
+-.PD 0
+-.IP S
+-Run state encoded thus:
+-.RS
+-.IP 0
+-no process
+-.IP 1
+-waiting for some event
+-.IP 3
+-runnable
+-.IP 4
+-being created
+-.IP 5
+-being terminated
+-.IP 6
+-stopped under trace
+-.RE
+-.IP F
+-Miscellaneous state variables, or-ed together:
+-.RS
+-.IP 01
+-loaded
+-.IP 02
+-the scheduler process
+-.IP 04
+-locked
+-.IP 010
+-swapped out
+-.IP 020
+-traced
+-.IP 040
+-used in tracing
+-.IP 0100
+-locked in by
+-.IR lock (2).
+-.RE
+-.IP PRI
+-Scheduling priority, see
+-.IR nice (2).
+-.IP SIGNAL
+-Signals received (signals 1-16 coded in bits 0-15),
+-.IP UID
+-Real user ID.
+-.IP TIM
+-Time resident in seconds; times over 127 coded as 127.
+-.IP CPU
+-Weighted integral of CPU time, for scheduler.
+-.IP NI
+-Nice level,
+-see
+-.IR nice (2).
+-.IP PGRP
+-Process number of root of process group
+-(the opener of the controlling terminal).
+-.IP PID
+-The process ID number.
+-.IP PPID
+-The process ID of parent process.
+-.IP ADDR
+-If in core, the physical address of the `u-area' of
+-the process measured in multiples of 64 bytes.
+-If swapped out, the position in the swap area
+-measured in multiples of 512 bytes.
+-.IP SIZE
+-Size of process image in multiples of 64 bytes.
+-.IP WCHAN
+-Wait channel number of a waiting process.
+-.IP LINK
+-Link pointer in list of runnable processes.
+-.IP TEXTP
+-If text is pure, pointer to location of text table entry.
+-.IP CLKT
+-Countdown for
+-.IR alarm (2)
+-measured in seconds.
+-.PD
+-.TP
+-.B \-t
+-Print table for terminals (only DH11 and DL11 handled)
+-with these headings:
+-.IP RAW
+-Number of characters in raw input queue.
+-.PD 0
+-.IP CAN
+-Number of characters in canonicalized input queue.
+-.IP OUT
+-Number of characters in putput queue.
+-.IP MODE
+-See
+-.IR tty (4).
+-.IP ADDR
+-Physical device address.
+-.IP DEL
+-Number of delimiters (newlines) in canonicalized input queue.
+-.IP COL
+-Calculated column position of terminal.
+-.IP STATE
+-Miscellaneous state variables encoded thus:
+-.RS
+-.IP W
+-waiting for open to complete
+-.IP O
+-open
+-.IP S
+-has special (output) start routine
+-.IP C
+-carrier is on
+-.IP B
+-busy doing output
+-.IP A
+-process is awaiting output
+-.IP X
+-open for exclusive use
+-.IP H
+-hangup on close
+-.RE
+-.IP PGRP
+-Process group for which this is controlling terminal.
+-.PD
+-.TP
+-.B \-u
+-print information about a user process;
+-the next argument is its address as given
+-by
+-.IR ps (1).
+-The process must be in main memory, or the file used can
+-be a core image and the address 0.
+-.TP
+-.B \-f
+-Print the open file table with these headings:
+-.IP LOC
+-The core location of this table entry.
+-.PD 0
+-.IP FLG
+-Miscellaneous state variables encoded thus:
+-.RS
+-.IP R
+-open for reading
+-.IP W
+-open for writing
+-.IP P
+-pipe
+-.RE
+-.IP CNT
+-Number of processes that know this open file.
+-.IP INO
+-The location of the inode table entry for this file.
+-.IP OFFS
+-The file offset, see
+-.IR lseek (2).
+-.PD
+-.PP
+-.SH FILES
+-.ta \w'/dev/mem  'u
+-/unix namelist
+-.br
+-/dev/mem      default source of tables
+-.SH SEE ALSO
+-ps(1), stat(2), filsys(5)
+-.br
+-K. Thompson,
+-.I UNIX Implementation
+//GO.SYSIN DD pstat.1m
+echo ptx.1
+sed 's/.//' >ptx.1 <<'//GO.SYSIN DD ptx.1'
+-.TH PTX 1
+-.SH NAME
+-ptx \- permuted index
+-.SH SYNOPSIS
+-.B ptx
+-[ option ] ...
+-[ input [ output ] ]
+-.SH DESCRIPTION
+-.I Ptx
+-generates a permuted index to file
+-.I input
+-on file
+-.I output
+-(standard input and output default).
+-It has three phases: the first does the permutation, generating
+-one line for each keyword in an input line.
+-The keyword is rotated to the front.
+-The permuted file is then
+-sorted.
+-Finally, the sorted lines are rotated so the keyword
+-comes at the middle of the page.
+-.I Ptx
+-produces output in the form:
+-.br
+-.IP
+-\&.xx "tail" "before keyword" "keyword and after" "head"
+-.LP
+-where .xx may be an
+-.I nroff
+-or
+-.IR troff (1)
+-macro
+-for user-defined formatting.
+-The
+-.I before keyword
+-and
+-.I keyword and after
+-fields incorporate as much of the line as will fit
+-around the keyword when it is printed at the middle of the page.
+-.I Tail
+-and
+-.I head,
+-at least one of which is an empty string "",
+-are wrapped-around pieces small enough to fit
+-in the unused space at the opposite end of the line.
+-When original text must be discarded, `/' marks the spot.
+-.PP
+-The following options can be applied:
+-.TP
+-.BR \-f
+-Fold upper and lower case letters for sorting.
+-.TP 
+-.BR \-t
+-Prepare the output for the phototypesetter;
+-the default line length is 100 characters.
+-.TP 
+-.BI \-w " n"
+-Use the next argument,
+-.I n,
+-as the width of the output line.
+-The default line length is 72 characters.
+-.TP
+-.BI \-g " n"
+-Use the next argument,
+-.I n,
+-as the number of characters to allow for each gap
+-among the four parts of the line as finally printed.
+-The default gap is 3 characters.
+-.TP 
+-.BR \-o " only"
+-Use as keywords only the words given in the \fIonly\fR file.
+-.TP 
+-.BR \-i " ignore"
+-Do not use as keywords any words given in the
+-.I
+-ignore
+-file.
+-If the \fB-\fIi\fR and \fB-\fIo\fR options are missing, use /usr/lib/eign
+-as the 
+-.I
+-ignore
+-file.
+-.TP 
+-.BR \-b " break"
+-Use the characters in the 
+-.I
+-break
+-file to separate words.
+-In any case, tab, newline, and space characters are always used as break characters.
+-.TP
+-.BR \-r
+-Take any leading nonblank characters of each input line to
+-be a reference identifier (as to a page or chapter)
+-separate from the text of the line.
+-Attach that identifier as a 5th field on each output line.
+-.PP
+-The index for this manual was generated using
+-.I ptx.
+-.SH FILES
+-/bin/sort
+-.br
+-/usr/lib/eign
+-.SH BUGS
+-Line length counts do not account for overstriking or
+-proportional spacing.
+-.br
+//GO.SYSIN DD ptx.1
+echo pubindex.1
+sed 's/.//' >pubindex.1 <<'//GO.SYSIN DD pubindex.1'
+-.TH PUBINDEX 1 local
+-.SH NAME
+-pubindex \- make inverted bibliographic index
+-.SH SYNOPSIS
+-.B pubindex
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Pubindex
+-makes a hashed inverted index to
+-the named
+-.I files
+-for use by
+-.IR refer (1).
+-The
+-.I files
+-contain bibliographic references separated by blank lines.
+-A bibliographic reference is a set of lines
+-that contain bibliographic information fields.
+-Each field starts on a line beginning with a `%', followed
+-by a key-letter, followed by a blank, and followed by the
+-contents of the field, which continues until the next line
+-starting with `%'.
+-The most common key-letters and the corresponding fields are:
+-.IP
+-.nf
+-A     Author name
+-B     Title of book containing article referenced
+-C     City
+-D     Date
+-d     Alternate date
+-E     Editor of book containing article referenced
+-G     Government (CFSTI) order number
+-I     Issuer (publisher)
+-J     Journal
+-K     Other keywords to use in locating reference
+-M     Technical memorandum number
+-N     Issue number within volume
+-O     Other commentary to be printed at end of reference
+-P     Page numbers
+-R     Report number
+-r     Alternate report number
+-T     Title of article, book, etc.
+-V     Volume number
+-X     Commentary unused by \fIpubindex\fR
+-.fi
+-.PP
+-Except for `A', each field should only be given once.
+-Only relevant fields should be supplied.
+-An example is:
+-.IP
+-.nf
+-%T 5-by-5 Palindromic Word Squares
+-%A M. D. McIlroy
+-%J Word Ways
+-%V 9
+-%P 199-202
+-%D 1976
+-.fi
+-.SH FILES
+-.I "x.ia, x.ib, x.ic"
+-where 
+-.I x
+-is the first argument.
+-.SH SEE ALSO
+-refer(1)
+//GO.SYSIN DD pubindex.1
+echo pwd.1
+sed 's/.//' >pwd.1 <<'//GO.SYSIN DD pwd.1'
+-.TH PWD 1 
+-.SH NAME
+-pwd \- working directory name
+-.SH SYNOPSIS
+-.B pwd
+-.SH DESCRIPTION
+-.I Pwd
+-prints the pathname of the working (current) directory.
+-.SH "SEE ALSO"
+-cd(1)
+//GO.SYSIN DD pwd.1
+echo quot.1m
+sed 's/.//' >quot.1m <<'//GO.SYSIN DD quot.1m'
+-.TH QUOT 1M 
+-.SH NAME
+-quot \- summarize file system ownership
+-.SH SYNOPSIS
+-.B quot
+-[ option ] ...
+-[ filesystem ]
+-.SH DESCRIPTION
+-.I Quot
+-prints the number of blocks in the named
+-.I filesystem
+-currently owned by each user.
+-If no 
+-.I filesystem
+-is named, a default name is assumed.
+-The following options are available:
+-.TP
+-.B \-n
+-Cause the pipeline
+-.B "ncheck filesystem | sort +0n | quot \-n filesystem
+-to produce a list of all files and their owners.
+-.TP
+-.B \-c
+-Print three columns giving file size in blocks, number of
+-files of that size, and cumulative total of blocks
+-in that size or smaller file.
+-.TP
+-.B \-f
+-Print count of number of files as well as space owned by each user.
+-.SH FILES
+-Default file system varies with system.
+-.br
+-/etc/passwd to get user names
+-.SH "SEE ALSO"
+-ls(1), du(1)
+-.SH BUGS
+-Holes in files are counted as if they actually occupied space.
+//GO.SYSIN DD quot.1m
+echo ranlib.1
+sed 's/.//' >ranlib.1 <<'//GO.SYSIN DD ranlib.1'
+-.TH RANLIB 1
+-.SH NAME
+-ranlib \- convert archives to random libraries
+-.SH SYNOPSIS
+-.B ranlib
+-archive ...
+-.SH DESCRIPTION
+-.I Ranlib
+-converts each
+-.I archive
+-to a form which can be loaded
+-more rapidly by the loader,
+-by adding a table of contents named
+-.B __.SYMDEF
+-to the beginning of the archive.
+-It uses
+-.IR ar (1)
+-to reconstruct the archive,
+-so that sufficient temporary file space must
+-be available in the file system containing the
+-current directory.
+-.SH SEE ALSO
+-ld(1), ar(1)
+-.SH BUGS
+-Because generation of a library by
+-.I ar
+-and randomization by
+-.I ranlib
+-are separate,
+-phase errors are possible.
+-The loader
+-.I ld
+-warns when the modification date of
+-a library is more recent than
+-the creation of its dictionary;
+-but this means you get the warning even if you
+-only copy the library.
+//GO.SYSIN DD ranlib.1
+echo ratfor.1
+sed 's/.//' >ratfor.1 <<'//GO.SYSIN DD ratfor.1'
+-.TH RATFOR 1
+-.SH NAME
+-ratfor \- rational Fortran dialect
+-.SH SYNOPSIS
+-.B ratfor
+-[ option ... ]
+-[ filename ... ]
+-.SH DESCRIPTION
+-.I Ratfor
+-converts a rational dialect of Fortran into ordinary irrational Fortran.
+-.I Ratfor
+-provides control flow constructs essentially identical to those in C:
+-.TP
+-statement grouping:
+-.nf
+-{ statement; statement; statement }
+-.TP
+-decision-making:
+-if (condition) statement [ else statement ]
+-.br
+-switch (integer value) {
+-      case integer:   statement
+-      ...
+-      [ default: ]    statement
+-}
+-.TP
+-loops:
+-while (condition) statement
+-for (expression; condition; expression) statement
+-do limits statement
+-repeat statement [ until (condition) ]
+-break [n]
+-next [n]
+-.LP
+-and some syntactic sugar to make programs easier to read and write:
+-.TP
+-free form input:
+-multiple statements/line; automatic continuation
+-.TP
+-comments:
+-# this is a comment
+-.TP
+-translation of relationals:
+->, >=, etc., become .GT., .GE., etc.
+-.TP
+-return (expression)
+-returns expression to caller from function
+-.TP
+-define:
+-define name replacement
+-.TP
+-include:
+-include filename
+-.PP
+-.fi
+-The option
+-.B \-h
+-causes quoted strings to be turned into
+-27H constructs.
+-.B \-C
+-copies comments to the output, and attempts
+-to format it neatly.
+-Normally, continuation lines are marked with a &
+-in column 1;
+-the option
+-.B \-6x
+-makes the continuation character
+-.B x
+-and places it in column 6.
+-.PP
+-.I Ratfor
+-is best used with
+-.IR f77 (1).
+-.SH "SEE ALSO"
+-f77(1)
+-.br
+-B. W. Kernighan and P. J. Plauger,
+-.IR "Software Tools" ,
+-Addison-Wesley, 1976.
+//GO.SYSIN DD ratfor.1
+echo refer.1
+sed 's/.//' >refer.1 <<'//GO.SYSIN DD refer.1'
+-.TH REFER 1
+-.SH NAME
+-refer, lookbib \- find and insert literature references in documents
+-.SH SYNOPSIS
+-.B refer
+-[ option ] ...
+-.PP
+-.B lookbib
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Lookbib
+-accepts keywords from the standard input 
+-and searches a bibliographic data base for references
+-that contain those keywords anywhere in title, author,
+-journal name, etc.
+-Matching references are printed on the standard output.
+-Blank lines are taken as delimiters between queries.
+-.PP
+-.I Refer
+-is a preprocessor for
+-.I nroff
+-or
+-.IR troff (1)
+-that finds and formats references.
+-The input files (standard input default) are copied to the standard output,
+-except for lines between .[ and .]
+-command lines, which are assumed to contain keywords as for
+-.I lookbib,
+-and are replaced by information from the bibliographic data base.
+-The user may avoid the search, override fields from it, or
+-add new fields.
+-The reference data, from whatever source, are assigned to a set of
+-.I troff
+-strings.
+-Macro packages such as
+-.IR ms (7)
+-print the finished reference text from these strings.
+-A flag is placed in the text at the point of reference;
+-by default the references are indicated by numbers.
+-.br
+-.sp
+-The following options are available:
+-.TP 6
+-.BI \-a r
+-Reverse the first
+-.I r
+-author names (Jones, J. A. instead of J. A. Jones).
+-If
+-.I r
+-is omitted all author names are reversed.
+-.ns
+-.TP
+-.B \-b
+-Bare mode: do not put any flags in text (neither numbers nor labels).
+-.ns
+-.TP
+-.BI \-c string
+-Capitalize (with C\s-2APS\s0 S\s-2MALL\s+2 C\s-2APS\s0)
+-the fields whose key-letters are in
+-.IR string .
+-.ns
+-.TP
+-.B \-e
+-Instead of leaving the references where encountered,
+-accumulate them
+-until a sequence of the form
+-.nf
+-              .[
+-              $LIST$
+-              .]
+-.fi
+-is encountered, and then write out all references
+-collected so far.  Collapse references to the same source.
+-.ns
+-.TP
+-.BI \-k x
+-Instead of numbering references, use labels as specified in
+-a
+-reference data line
+-beginning
+-.I %x;
+-by default 
+-.I x
+-is
+-.B L.
+-.ns
+-.TP
+-.BI \-l m , n
+-Instead of numbering references, use labels made from
+-the senior author's last name and the year of publication.
+-Only the first
+-.I m
+-letters of the last name
+-and the last
+-.I n
+-digits of the date are used.
+-If either
+-.I m
+-or
+-.BI , n
+-is omitted the entire name or date respectively is used.
+-.ns
+-.TP
+-.B \-p
+-Take the next argument as a file of
+-references to be searched.
+-The default file is searched last.
+-.ns
+-.TP
+-.B \-n
+-Do not search the default file.
+-.ns
+-.TP
+-.BI \-s keys
+-Sort references by fields whose key-letters are in
+-the
+-.I keys
+-string;
+-permute
+-reference numbers in text accordingly.
+-Implies
+-.BR \-e .
+-The key-letters in
+-.I keys
+-may be followed by a number to indicate how many such fields
+-are used, with
+-.B +
+-taken as a very large number.
+-The default is
+-.B AD
+-which sorts on the senior author and then date; to sort, for example,
+-on all authors and then title use
+-.BR -sA+T .
+-.PP
+-To use your own references, put them in the format
+-described in
+-.IR pubindex (1)
+-They can be searched
+-more rapidly by running
+-.IR pubindex (1)
+-on them before using
+-.I refer;
+-failure to index results in a linear search.
+-.PP
+-When
+-.I refer
+-is used with
+-.I eqn,
+-.I neqn
+-or
+-.I tbl,
+-.I refer
+-should be first, to minimize the volume
+-of data passed through
+-pipes.
+-.SH FILES
+-.I /usr/dict/papers
+-directory of default publication lists and indexes
+-.br
+-.I /usr/lib/refer
+-directory of programs
+-.SH SEE ALSO
+-.br
+//GO.SYSIN DD refer.1
+echo restor.1m
+sed 's/.//' >restor.1m <<'//GO.SYSIN DD restor.1m'
+-.TH RESTOR 1M 
+-.SH NAME
+-restor \- incremental file system restore
+-.SH SYNOPSIS
+-.I restor
+-key [ argument ... ]
+-.SH DESCRIPTION
+-.I Restor
+-is used to read magtapes dumped with the
+-.I dump
+-command.
+-The
+-.I key
+-specifies what is to be done.
+-.I Key
+-is one of the characters
+-.B rRxt
+-optionally combined with
+-.BR f .
+-.TP
+-.B  f
+-Use the first
+-.I argument
+-as the name of the tape instead
+-of the default.
+-.TP
+-.B  r or R
+-The tape
+-is read and loaded into the file system
+-specified in
+-.I argument.
+-This should not be done lightly (see below).
+-If the key is
+-.B R
+-.I restor
+-asks which tape of a multi volume set to start on.
+-This allows restor to be interrupted and then
+-restarted (an
+-.I icheck \-s must be done before restart).
+-.TP
+-.B  x
+-Each file on the
+-tape named by an 
+-.I argument
+-is extracted.
+-The file name has all `mount' prefixes removed;
+-for example, /usr/bin/lpr is named /bin/lpr on the tape.
+-The file extracted is placed in a file with a numeric name
+-supplied by
+-.I restor
+-(actually the inode number).
+-In order to keep the amount of tape read to a minimum,
+-the following procedure is recommended:
+-.sp
+-Mount volume 1 of the set of dump tapes.
+-.sp
+-Type the
+-.I restor
+-command.
+-.sp
+-.I Restor
+-will announce whether or not it found the files,
+-give the number it will name the file, and rewind the tape.
+-.sp
+-It then
+-asks you to `mount the desired tape volume'.
+-Type the number of the volume you choose.
+-On a
+-multivolume dump the recommended procedure is to mount the
+-last through the first volume in that order.
+-.I Restor
+-checks to see if any of the files requested are on the
+-mounted tape (or a later tape, thus the reverse order) and doesn't
+-read through the tape if no files are.
+-If you are working with a single volume dump or the number of files
+-being restored is large, respond to the query with `1' and
+-.I restor
+-will read the tapes in sequential order.
+-.sp
+-If you have a hierarchy to restore you can use dumpdir(1)
+-to produce the list of names and a shell script to move
+-the resulting files to their homes.
+-.TP
+-.B t
+-Print the date the tape was written and the date
+-the filesystem was dumped from.
+-.PP
+-The
+-.B r
+-option should only be used to restore
+-a complete dump tape onto a clear file system
+-or to restore an incremental dump tape onto this.
+-Thus
+-.PP
+-      /etc/mkfs /dev/rp0 40600
+-.br
+-      restor r /dev/rp0
+-.PP
+-is a typical sequence to restore a complete dump.
+-Another
+-.I restor
+-can be done to get an incremental dump
+-in on top of this.
+-.PP
+-A
+-.I dump
+-followed by a
+-.I mkfs
+-and a
+-.I restor
+-is used to
+-change the size of a file system.
+-.SH FILES
+-default tape unit varies with installation
+-.br
+-rst*
+-.SH "SEE ALSO"
+-dump(1), mkfs(1), dumpdir(1)
+-.SH DIAGNOSTICS
+-There are various diagnostics
+-involved with reading the tape and writing the disk.
+-There are also diagnostics if the i-list or the free list
+-of the file system is not large enough to hold the dump.
+-.PP
+-If the dump extends over more than one tape,
+-it may ask you to change tapes.
+-Reply with a new-line when the next tape has been mounted.
+-.SH BUGS
+-There is redundant information on the tape
+-that could be used in case of tape reading problems.
+-Unfortunately,
+-.I restor
+-doesn't use it.
+//GO.SYSIN DD restor.1m
+echo rev.1
+sed 's/.//' >rev.1 <<'//GO.SYSIN DD rev.1'
+-.TH REV 1 
+-.SH NAME
+-rev \- reverse lines of a file
+-.SH SYNOPSIS
+-.B rev
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Rev
+-copies the named files to the standard output,
+-reversing the order of characters in every line.
+-If no file is specified, the standard input is copied.
+//GO.SYSIN DD rev.1
+echo rm.1
+sed 's/.//' >rm.1 <<'//GO.SYSIN DD rm.1'
+-.TH RM 1 
+-.SH NAME
+-rm, rmdir  \- remove (unlink) files
+-.SH SYNOPSIS
+-.B rm
+-[
+-.B \-fri
+-] file ...
+-.PP
+-.B rmdir
+-dir ...
+-.PP
+-.SH DESCRIPTION
+-.I Rm
+-removes the entries for one or more
+-files
+-from a directory.
+-If an entry was the last link to the file, the file
+-is destroyed.
+-Removal of a file requires write permission in its directory,
+-but neither read nor write permission on the file itself.
+-.PP
+-If a file has no write permission
+-and the standard input is a terminal,
+-its permissions are printed and a line is read from
+-the standard input.
+-If that line begins with `y' the file is deleted,
+-otherwise the file remains.
+-No questions are asked
+-when the
+-.B \-f
+-(force) option is given.
+-.PP
+-If a designated file is a directory,
+-an error comment is printed unless the optional
+-argument
+-.B \-r
+-has been used.
+-In that case,
+-.I rm
+-recursively deletes the
+-entire contents of the specified directory,
+-and the directory itself.
+-.PP
+-If the
+-.B \-i
+-(interactive) option is in effect,
+-.I rm
+-asks whether to delete each file,
+-and, under
+-.BR \-r ,
+-whether to examine each directory.
+-.PP
+-.I Rmdir
+-removes entries for the named directories,
+-which must be empty.
+-.SH "SEE ALSO"
+-unlink(2)
+-.SH DIAGNOSTICS
+-Generally self-explanatory.
+-It is forbidden to remove the file `..' merely to avoid the
+-antisocial consequences of inadvertently doing something like
+-`rm \-r .*'.
+//GO.SYSIN DD rm.1
+echo roff.1
+sed 's/.//' >roff.1 <<'//GO.SYSIN DD roff.1'
+-.TH ROFF 1 
+-.SH NAME
+-roff  \-  format text
+-.SH SYNOPSIS
+-.B roff
+-[ \fB+\fIn\fR ] [ \fB\-\fIn\fR ] [
+-.B \-s
+-] [
+-.B \-h
+-] file ...
+-.PP
+-.B nroff \-mr
+-[ option ] ... file ...
+-.br
+-.B troff \-mr
+-[ option ] ... file ...
+-.SH DESCRIPTION
+-.I Roff
+-formats text according to control lines embedded
+-in the text in the given files.
+-Encountering a nonexistent file terminates printing.
+-Incoming inter-terminal messages are turned off during printing.
+-The optional flag arguments mean:
+-.br
+-.ns
+-.TP 5
+-.BI + n
+-Start printing at the first page with number
+-.IR n .
+-.br
+-.ns
+-.TP 5
+-.BI \- n
+-Stop printing at the first page numbered higher
+-than
+-.IR n .
+-.br
+-.ns
+-.TP 5
+-.B  \-s
+-Stop before each page (including the first)
+-to allow paper manipulation;
+-resume on receipt of an interrupt signal.
+-.br
+-.ns
+-.TP 5
+-.B  \-h
+-Insert tabs in the output stream to replace
+-spaces whenever appropriate.
+-.PP
+-.DT
+-Input consists of intermixed
+-.I "text lines,"
+-which contain information to be formatted, and
+-.I "request lines,"
+-which contain instructions about how to format
+-it.
+-Request lines begin with a distinguished
+-.I "control character,"
+-normally a period.
+-.PP
+-Output lines may be
+-.I filled
+-as nearly as possible with words without regard to
+-input lineation.
+-Line
+-.I breaks
+-may be caused at specified places by
+-certain commands, or by the appearance of an
+-empty input line or an input line beginning with a space.
+-.PP
+-The capabilities of
+-.I roff
+-are specified in the attached Request Summary.
+-Numerical values are denoted there by n or +n,
+-titles by t, and single characters by c.
+-Numbers denoted +n may be signed + or \-,
+-in which case they signify relative changes to
+-a quantity, otherwise they signify
+-an absolute resetting.
+-Missing n fields are ordinarily taken to be 1,
+-missing t fields to be empty, and c fields to shut off
+-the appropriate special interpretation.
+-.PP
+-Running titles usually appear at top and bottom of every
+-page.
+-They are set by requests like
+-.PP
+-.in +10
+-.if t \&.he \(fmpart1\(fmpart2\(fmpart3\(fm
+-.if n \&.he 'part1'part2'part3'
+-.in -10
+-.PP
+-Part1 is left justified, part2 is centered,
+-and part3 is right justified on the page.
+-Any % sign in a title is replaced by the current
+-page number.
+-Any nonblank may serve as a quote.
+-.PP
+-ASCII tab characters are replaced in the input by a
+-.I "replacement character,"
+-normally a space,
+-according to the
+-column settings given by a .ta command.
+-(See .tr for how to convert this character on output.)
+-.PP
+-Automatic hyphenation of filled output is done
+-under control of .hy.
+-When a word contains a designated
+-.I "hyphenation character,"
+-that character disappears from the output and
+-hyphens can be introduced into
+-the word at the marked places only.
+-.PP
+-The
+-.B \-mr
+-option of
+-.I nroff
+-or 
+-.IR troff (1)
+-simulates
+-.I roff
+-to the greatest extent possible.
+-.SH FILES
+-/usr/lib/suftab       suffix hyphenation tables
+-.br
+-/tmp/rtm?     temporary
+-.br
+-.SH BUGS
+-.I Roff
+-is the simplest of the text formatting
+-programs, and is utterly frozen.
+-.bp
+-.tc |
+-.tr |
+-.in 0
+-.ce
+-REQUEST SUMMARY
+-.PP
+-.ul
+-.ta \w'.tr cdef.. 'u +\w'Break 'u +\w'Initial 'u
+-.di x
+-                      \ka
+-.br
+-.di
+-.in \nau
+-.ti 0
+-Request       Break   Initial Meaning
+-.na
+-.ti 0
+-.li
+-.ad   yes     yes     Begin adjusting right margins.
+-.ti 0
+-.li
+-.ar   no      arabic  Arabic page numbers.
+-.ti 0
+-.li
+-.br   yes     \-      Causes a line break \*- the filling of
+-the current line is stopped.
+-.ti 0
+-.li
+-.bl|n yes     \-      Insert of n blank lines, on new page if necessary.
+-.ti 0
+-.li
+-.bp|+n        yes     n=1     Begin new page and number it n; no n means `+1'.
+-.ti 0
+-.li
+-.cc|c no      c=.     Control character becomes `c'.
+-.ti 0
+-.li
+-.ce|n yes     \-      Center the next n input lines,
+-without filling.
+-.ti 0
+-.li
+-.de|xx        no      \-      Define parameterless macro 
+-to be invoked by request `.xx'
+-(definition ends on line beginning `\fB..\fR').
+-.ti 0
+-.li
+-.ds   yes     no      Double space; same as `.ls 2'.
+-.ti 0
+-.li
+-.ef|t no      t=\*a\*a\*a\*a  Even foot title becomes t.
+-.ti 0
+-.li
+-.eh|t no      t=\*a\*a\*a\*a  Even head title becomes t.
+-.ti 0
+-.li
+-.fi   yes     yes     Begin filling output lines.
+-.ti 0
+-.li
+-.fo   no      t=\*a\*a\*a\*a  All foot titles are t.
+-.ti 0
+-.li
+-.hc|c no      none    Hyphenation character becomes `c'.
+-.ti 0
+-.li
+-.he|t no      t=\*a\*a\*a\*a  All head titles are t.
+-.ti 0
+-.li
+-.hx   no      \-      Title lines are suppressed.
+-.ti 0
+-.li
+-.hy|n no      n=1     Hyphenation is done, if n=1;
+-and is not done, if n=0.
+-.ti 0
+-.li
+-.ig   no      \-      Ignore input lines through
+-a line beginning with `\fB..\fR'.
+-.ti 0
+-.li
+-.in|+n        yes     \-      Indent n spaces from left margin.
+-.ti 0
+-.li
+-.ix +n        no      \-      Same as `.in' but without break.
+-.ti 0
+-.li
+-.li|n no      \-      Literal, treat next n lines as text.
+-.ti 0
+-.li
+-.ll|+n        no      n=65    Line length including indent is n characters.
+-.ti 0
+-.li
+-.ls|+n        yes     n=1     Line spacing set to n lines per output line.
+-.ti 0
+-.li
+-.m1|n no      n=2     Put n blank lines between the top
+-of page and head title.
+-.ti 0
+-.li
+-.m2|n no      n=2     n blank lines put between head title
+-and beginning of text on page.
+-.ti 0
+-.li
+-.m3|n no      n=1     n blank lines put between end of
+-text and foot title.
+-.ti 0
+-.li
+-.m4|n no      n=3     n blank lines put between the foot title
+-and the bottom of page.
+-.ti 0
+-.li
+-.na   yes     no      Stop adjusting the right margin.
+-.ti 0
+-.li
+-.ne|n no      \-      Begin new page, if n output lines
+-cannot fit on present page.
+-.ti 0
+-.li
+-.nn|+n        no      \-      The next n output lines are not numbered.
+-.ti 0
+-.li
+-.n1   no      no      Add 5 to page offset;
+-number lines in margin from 1 on each page.
+-.ti 0
+-.li
+-.n2|n no      no      Add 5 to page offset;
+-number lines from n;
+-stop if n=0.
+-.ti 0
+-.li
+-.ni|+n        no      n=0     Line numbers are indented n.
+-.ti 0
+-.li
+-.nf   yes     no      Stop filling output lines.
+-.ti 0
+-.li
+-.nx|file      \-      Switch input to `file'.
+-.ti 0
+-.li
+-.of|t no      t=\*a\*a\*a\*a  Odd foot title becomes t.
+-.ti 0
+-.li
+-.oh|t no      t=\*a\*a\*a\*a  Odd head title becomes t.
+-.ti 0
+-.li
+-.pa|+n        yes     n=1     Same as `.bp'.
+-.ti 0
+-.li
+-.pl|+n        no      n=66    Total paper length taken to be n lines.
+-.ti 0
+-.li
+-.po|+n        no      n=0     Page offset.
+-All lines are preceded by n spaces.
+-.ti 0
+-.li
+-.ro   no      arabic  Roman page numbers.
+-.ti 0
+-.li
+-.sk|n no      \-      Produce n blank pages starting next page.
+-.ti 0
+-.li
+-.sp|n yes     \-      Insert block of n blank lines,
+-except at top of page.
+-.ti 0
+-.li
+-.ss   yes     yes     Single space output lines,
+-equivalent to `.ls 1'.
+-.ti 0
+-.li
+-.ta|n|n..             \-      Pseudotab settings.
+-Initial tab settings are columns 9 17 25 ...
+-.ti 0
+-.li
+-.tc|c no      space   Tab replacement character becomes `c'.
+-.ti 0
+-.li
+-.ti|+n        yes     \-      Temporarily indent next output
+-line n spaces.
+-.ti0
+-.li
+-.tr|cdef..    no      \-      Translate c into d, e into f, etc.
+-.ti0
+-.li
+-.ul|n no      \-      Underline the letters and numbers
+-in the next n input lines.
+-.br
+-.tr ||
+//GO.SYSIN DD roff.1
+echo sa.1m
+sed 's/.//' >sa.1m <<'//GO.SYSIN DD sa.1m'
+-.TH SA 1M 
+-.SH NAME
+-sa, accton \- system accounting
+-.SH SYNOPSIS
+-.B sa
+-[
+-.B \-abcjlnrstuv
+-] [ file ]
+-.PP
+-.B /etc/accton 
+-[ file ]
+-.SH DESCRIPTION
+-With an argument naming an existing
+-.I file,
+-.I accton
+-causes system accounting information for
+-every process executed to be placed at the end of the file.
+-If no arguemnt is given, accounting is turned off.
+-.PP
+-.I Sa
+-reports on, cleans up, and generally maintains
+-accounting files.
+-.PP
+-.I Sa
+-is able to condense
+-the information in
+-.I /usr/adm/acct
+-into a summary file
+-.I /usr/adm/savacct
+-which contains a count of the
+-number of times each command was called and the time resources
+-consumed.
+-This condensation is desirable because on a large system
+-.I acct
+-can grow by 100 blocks per day.
+-The summary file is read before the accounting file,
+-so the reports include all available information.
+-.PP
+-If a file name is given as the last argument,
+-that file will be treated
+-as the accounting file;
+-.I sha
+-is the default.
+-There are zillions of options:
+-.PP
+-.TP
+-a
+-Place all command names containing unprintable characters
+-and those used only once under the name `***other.'
+-.TP
+-b
+-Sort output by sum of user and system time divided by number of
+-calls.
+-Default sort is by sum of user and system times.
+-.TP
+-c
+-Besides total user, system, and real time for each command print percentage
+-of total time over all commands.
+-.TP
+-j
+-Instead of total minutes time for each category,
+-give seconds per call.
+-.TP
+-l
+-Separate system and user time; normally they are combined.
+-.TP
+-m
+-Print number of processes and number of CPU minutes for each user.
+-.TP
+-n
+-Sort by number of calls.
+-.TP
+-r
+-Reverse order of sort.
+-.TP
+-s
+-Merge accounting file into summary file
+-.I /usr/adm/savacct
+-when done.
+-.TP
+-t
+-For each command report ratio of real time to the sum of user and
+-system times.
+-.TP
+-u
+-Superseding all other flags,
+-print for each command in the accounting file the
+-user ID and command name.
+-.TP
+-v
+-If the next character is a digit
+-.I n,
+-then type the name of
+-each command used
+-.I n
+-times or fewer.
+-Await a reply from the typewriter;
+-if it begins with `y', add the command to
+-the category `**junk**.'
+-This is used to strip out garbage.
+-.dt
+-.SH FILES
+-/usr/adm/acct raw accounting
+-.br
+-/usr/adm/savacct      summary
+-.br
+-/usr/adm/usracct      per-user summary
+-.SH "SEE ALSO"
+-ac(1), acct(2)
+//GO.SYSIN DD sa.1m
+echo sed.1
+sed 's/.//' >sed.1 <<'//GO.SYSIN DD sed.1'
+-.TH SED 1 
+-.SH NAME
+-sed \- stream editor
+-.SH SYNOPSIS
+-.B sed
+-[
+-.B \-n
+-]
+-[
+-.B \-e
+-script ] [
+-.B \-f
+-sfile ] [ file ] ...
+-.SH DESCRIPTION
+-.I Sed
+-copies the named
+-.I files
+-(standard input default) to the standard output,
+-edited according to a script of commands.
+-The
+-.B \-f
+-option causes the script to be taken from file
+-.IR sfile ;
+-these options accumulate.
+-If there is just one
+-.B \-e
+-option and no
+-.BR \-f 's,
+-the flag
+-.B \-e
+-may be omitted.
+-The
+-.B \-n
+-option suppresses the default output.
+-.PP
+-A script consists of editing commands, one per line,
+-of the following form:
+-.IP
+-[address [, address] ] function [arguments]
+-.PP
+-In normal operation
+-.I sed
+-cyclically copies a line of input into a
+-.I pattern space
+-(unless there is something left after
+-a `D' command),
+-applies in sequence
+-all commands whose
+-.I addresses
+-select that pattern space,
+-and at the end of the script copies the pattern space
+-to the standard output (except under
+-.BR \-n )
+-and deletes the pattern space.
+-.PP
+-An
+-.I address
+-is either a decimal number that counts
+-input lines cumulatively across files, a `$' that
+-addresses the last line of input, or a context address,
+-`/regular expression/', in the style of
+-.IR ed (1)
+-modified thus:
+-.IP
+-The escape sequence `\en' matches a
+-newline embedded in the pattern space.
+-.PP
+-A command line with no addresses selects every pattern space.
+-.PP
+-A command line with
+-one address selects each pattern space that matches the address.
+-.PP
+-A command line with
+-two addresses selects the inclusive range from the first
+-pattern space that matches the first address through
+-the next pattern space that matches 
+-the second.
+-(If the second address is a number less than or equal
+-to the line number first selected, only one
+-line is selected.)
+-Thereafter the process is repeated, looking again for the
+-first address.
+-.PP
+-Editing commands can be applied only to non-selected pattern
+-spaces by use of the negation function `!' (below).
+-.PP
+-In the following list of functions the 
+-maximum number of permissible addresses
+-for each function is indicated in parentheses.
+-.PP
+-An argument denoted
+-.I text
+-consists of one or more lines,
+-all but the last of which end with `\e' to hide the
+-newline.
+-Backslashes in text are treated like backslashes
+-in the replacement string of an `s' command,
+-and may be used to protect initial blanks and tabs
+-against the stripping that is done on
+-every script line.
+-.PP
+-An argument denoted
+-.I rfile
+-or
+-.I wfile
+-must terminate the command
+-line and must be preceded by exactly one blank.
+-Each
+-.I wfile
+-is created before processing begins.
+-There can be at most 10 distinct
+-.I wfile
+-arguments.
+-.TP
+-(1)\|a\e
+-.br
+-.ns
+-.TP
+-.I text
+-.br
+-Append.
+-Place
+-.I text
+-on the output before
+-reading the next input line.
+-.TP
+-.RI (2)\|b " label"
+-Branch to the `:' command bearing the
+-.IR label .
+-If
+-.I label
+-is empty, branch to the end of the script.
+-.TP
+-(2)\|c\e
+-.br
+-.ns
+-.TP
+-.I text
+-.br
+-Change.
+-Delete the pattern space.
+-With 0 or 1 address or at the end of a 2-address range, place
+-.I text
+-on the output.
+-Start the next cycle.
+-.TP
+-(2)\|d
+-Delete the pattern space.
+-Start the next cycle.
+-.TP
+-(2)\|D
+-Delete the initial segment of the 
+-pattern space through the first newline.
+-Start the next cycle.
+-.TP
+-(2)\|g
+-Replace the contents of the pattern space
+-by the contents of the hold space.
+-.TP
+-(2)\|G
+-Append the contents of the hold space to the pattern space.
+-.TP
+-(2)\|h
+-Replace the contents of the hold space by the contents of the pattern space.
+-.TP
+-(2)\|H
+-Append the contents of the pattern space to the hold space.
+-.TP
+-(1)\|i\e
+-.br
+-.ns
+-.TP
+-.I text
+-Insert.
+-Place
+-.I text
+-on the standard output.
+-.TP
+-(2)\|l
+-List the pattern space on the standard output in an
+-unambiguous form.
+-Non-printing characters are spelled in two digit ascii,
+-and long lines are folded.
+-.TP
+-(2)\|n
+-Copy the pattern space to the standard output.
+-Replace the pattern space with the next line of input.
+-.TP
+-(2)\|N
+-Append the next line of input to the pattern space
+-with an embedded newline.
+-(The current line number changes.)
+-.TP
+-(2)\|p
+-Print.
+-Copy the pattern space to the standard output.
+-.TP
+-(2)\|P
+-Copy the initial segment of the pattern space through
+-the first newline to the standard output.
+-.TP
+-(1)\|q
+-Quit.
+-Branch to the end of the script.
+-Do not start a new cycle.
+-.TP
+-.RI (2)\|r " rfile"
+-Read the contents of
+-.IR rfile .
+-Place them on the output before reading
+-the next input line.
+-.TP
+-.RI (2)\|s /regular\ expression/replacement/flags
+-Substitute the
+-.I replacement
+-string for instances of the
+-.I regular expression
+-in the pattern space.
+-Any character may be used instead of `/'.
+-For a fuller description see
+-.IR ed (1).
+-.I Flags
+-is zero or more of
+-.RS
+-.TP
+-g
+-Global.
+-Substitute for all nonoverlapping instances of the
+-.I regular expression
+-rather than just the
+-first one.
+-.TP
+-p
+-Print the pattern space if a replacement was made.
+-.TP
+-.RI w " wfile"
+-Write.
+-Append the pattern space to
+-.I wfile
+-if a replacement
+-was made.
+-.RE
+-.TP
+-.RI (2)\|t " label"
+-Test.
+-Branch to the `:' command bearing the
+-.I label
+-if any
+-substitutions have been made since the most recent
+-reading of an input line or execution of a `t'.
+-If 
+-.I label
+-is empty, branch to the end of the script.
+-.TP
+-.RI (2)\|w " wfile"
+-Write.
+-Append the pattern space to
+-.IR wfile .
+-.TP
+-.RI (2)\|x
+-Exchange the contents of the pattern and hold spaces.
+-.TP
+-.RI (2)\|y /string1/string2/
+-Transform.
+-Replace all occurrences of characters in
+-.I string1
+-with the corresponding character in
+-.I string2.
+-The lengths of
+-.I
+-string1
+-and
+-.I string2
+-must be equal.
+-.TP
+-.RI (2)! " function"
+-Don't.
+-Apply the
+-.I function
+-(or group, if
+-.I function
+-is `{') only to lines
+-.I not
+-selected by the address(es).
+-.TP
+-.RI (0)\|: " label"
+-This command does nothing; it bears a
+-.I label
+-for `b' and `t' commands to branch to.
+-.TP
+-(1)\|=
+-Place the current line number on the standard output as a line.
+-.TP
+-(2)\|{
+-Execute the following commands through a matching `}'
+-only when the pattern space is selected.
+-.TP
+-(0)\|
+-An empty command is ignored.
+-.SH SEE ALSO
+-ed(1), grep(1), awk(1)
+//GO.SYSIN DD sed.1
+echo sh.1
+sed 's/.//' >sh.1 <<'//GO.SYSIN DD sh.1'
+-.ds OK [\|
+-.ds CK \|]
+-.ds LT \s-2<\s0
+-.ds GT \s-2>\s0
+-.ds LE \s-2<\s0
+-.ds ST *
+-.TH SH 1
+-.SH NAME
+-sh,
+-for,
+-case,
+-if,
+-while,
+-.BR : ,
+-.BR . ,
+-break,
+-continue,
+-cd,
+-eval,
+-exec,
+-exit,
+-export,
+-login,
+-newgrp,
+-read,
+-readonly,
+-set,
+-shift,
+-times,
+-trap,
+-umask,
+-wait
+-\- command language
+-.SH SYNOPSIS
+-.B sh
+-[
+-.B \-ceiknrstuvx
+-] [ arg ] ...
+-.SH DESCRIPTION
+-.I Sh
+-is a command programming language
+-that executes commands read from a terminal
+-or a file.
+-See
+-.B invocation
+-for the meaning of arguments to the shell.
+-.PP
+-.B Commands.
+-.br
+-A
+-.I simple-command
+-is a sequence of non blank
+-.I words
+-separated by blanks (a blank is a
+-.B tab
+-or a
+-.BR space ).
+-The first word specifies the name of the command to
+-be executed.
+-Except as specified below
+-the remaining words are passed as arguments
+-to the invoked command.
+-The command name is passed as argument 0
+-(see
+-.IR exec (2)).
+-The
+-.I value
+-of a simple-command is its exit status
+-if it terminates normally or 200+\fIstatus\fP if
+-it terminates abnormally (see
+-.IR signal (2)
+-for a list of
+-status values).
+-.LP
+-A
+-.I pipeline
+-is a sequence of one or more
+-.I commands
+-separated by
+-.B \(or.
+-The standard output of each command but the last
+-is connected by a
+-.IR pipe (2)
+-to the standard input of the next command.
+-Each command is run as a separate process;
+-the shell waits for the last command to terminate.
+-.LP
+-A
+-.I list
+-is a sequence of one or more
+-.I pipelines
+-separated by
+-.BR ; ,
+-.BR & ,
+-.B &&
+-or
+-.B \(or\|\(or
+-and optionally terminated by
+-.B ;
+-or
+-.BR & .
+-.B ;
+-and
+-.B &
+-have equal precedence
+-which is lower than that of
+-.B &&
+-and
+-.BR \(or\|\(or ,
+-.B &&
+-and
+-.B \(or\|\(or
+-also have equal precedence.
+-A semicolon causes sequential execution; an ampersand causes
+-the preceding
+-.I pipeline
+-to be executed without waiting for it to finish.
+-The symbol
+-.B &&
+-.RB ( \(or\|\(or )
+-causes the
+-.I list
+-following to be executed only if the preceding
+-.I pipeline
+-returns a zero (non zero) value.
+-Newlines may appear in a
+-.I list,
+-instead of semicolons,
+-to delimit commands.
+-.LP
+-A
+-.I command
+-is either a simple-command
+-or one of the following.
+-The value returned by a command is that of the
+-last simple-command executed in the command.
+-.TP
+-\fBfor \fIname\fR \*(OK\fBin \fIword\fR ...\*(CK \fBdo \fIlist \fBdone\fR
+-Each time a
+-.B for
+-command is executed
+-.I name
+-is set to the next word in the
+-.B for
+-word list
+-If
+-.BI in \ word
+-\&...
+-is omitted then
+-.B
+-in "$@"
+-is assumed.
+-Execution ends when there are no more words in the list.
+-.TP
+-\fBcase \fIword \fBin\fR \*(OK\fIpattern \fR\*(OK \fB\(or \fIpattern \fR\*(CK ... \fB) \fIlist \fB;;\fR\*(CK ... \fBesac\fR
+-A
+-.B case
+-command executes the
+-.I list
+-associated with the first
+-pattern that matches
+-.I word.
+-The form of the patterns is
+-the same as that used for
+-file name generation.
+-.TP
+-\fBif \fIlist \fBthen \fIlist\fR \*(OK\fBelif \fIlist \fBthen \fIlist\fR\*(CK ... \*(OK\fBelse \fIlist\fR\*(CK \fBfi\fR
+-The
+-.I list
+-following
+-.B if
+-is executed and if it returns zero the
+-.I list
+-following
+-.B then
+-is executed.
+-Otherwise, the
+-.I list
+-following
+-.B elif
+-is executed and if its value is zero
+-the
+-.I list
+-following
+-.B then
+-is executed.
+-Failing that the
+-.B else
+-.I list
+-is executed.
+-.TP
+-\fBwhile \fIlist\fR \*(OK\fBdo \fIlist\fR\*(CK \fBdone\fR
+-A
+-.B while
+-command repeatedly executes the
+-.B while
+-.I list
+-and if its value is zero executes the
+-.B do
+-.I list;
+-otherwise the loop terminates.
+-The value returned by a
+-.B while
+-command is that
+-of the last executed command in the
+-.B do
+-.I list.
+-.B until
+-may be used in place of
+-.B while
+-to negate
+-the loop termination test.
+-.TP
+-.BI ( " list " )
+-Execute
+-.I list
+-in a subshell.
+-.TP
+-.BI { " list " }
+-.I list
+-is simply executed.
+-.LP
+-The following words
+-are only recognized as the first word of a command
+-and when not quoted.
+-.IP
+-.B
+-if then else elif fi case in esac for while until do done { }
+-.PP
+-.B Command substitution.
+-.br
+-The standard output from a command enclosed in
+-a pair of grave accents
+-.RB ( \`\|\` )
+-may be used as part or all
+-of a word;
+-trailing newlines are removed.
+-.PP
+-.B Parameter substitution.
+-.br
+-The character
+-.B $
+-is used to introduce substitutable
+-parameters.
+-Positional parameters may be assigned values by
+-.BR set .
+-Variables may be set by writing
+-.IP
+-.IB name = value
+-[
+-.IB name = value
+-] ...
+-.TP
+-$\fB\|{\fIparameter\fB\|}\fR
+-A
+-.I parameter
+-is a sequence of letters, digits or underscores (a
+-.IR name ),
+-a digit,
+-or any of the characters
+-.B
+-* @ # ? \- $ !\|.
+-The value, if any, of the parameter is substituted.
+-The braces are required only when
+-.I parameter
+-is followed by a letter, digit, or underscore
+-that is not to be interpreted as part of its name.
+-If
+-.I parameter
+-is a digit then it is a positional parameter.
+-If
+-.I parameter
+-is
+-.BR * " or" " @"
+-then all the positional
+-parameters, starting with
+-.SM
+-.BR $1 ,
+-are substituted
+-separated by spaces.
+-.SM
+-.B $0
+-is set from argument zero when the shell
+-is invoked.
+-.TP
+-$\fB\|{\fIparameter\|\-word\|\fB}\fR
+-If
+-.I parameter
+-is set then substitute its value;
+-otherwise substitute
+-.I word.
+-.TP
+-$\fB\|{\fIparameter\|\(eq\|word\|\fB}\fR
+-If
+-.I parameter
+-is not set then set it to
+-.I word;
+-the value of the parameter is then substituted.
+-Positional parameters may not be assigned to
+-in this way.
+-.TP
+-$\fB\|{\fIparameter\|?\|word\|\fB}\fR
+-If
+-.I parameter
+-is set then substitute its value;
+-otherwise, print
+-.I word
+-and exit from the shell.
+-If
+-.I word
+-is omitted then a standard message is printed.
+-.TP
+-$\fB\|{\fIparameter\|\(plword\|\fB}\fR
+-If
+-.I parameter
+-is set then substitute
+-.I word;
+-otherwise substitute nothing.
+-.LP
+-In the above
+-.I word
+-is not evaluated unless it is
+-to be used as the substituted string.
+-(So that, for example,
+-echo ${d\-\`pwd\`}
+-will only execute
+-.I pwd
+-if
+-.I d
+-is unset.)
+-.LP
+-The following
+-.I parameters
+-are automatically set by the shell.
+-.RS
+-.TP
+-.B #
+-The number of positional parameters in decimal.
+-.PD 0
+-.TP
+-.B \-
+-Options supplied to the shell on invocation or by
+-.BR set .
+-.TP
+-.B ?
+-The value returned by the last executed command
+-in decimal.
+-.TP
+-.B $
+-The process number of this shell.
+-.TP
+-.B !
+-The process number of the last background command invoked.
+-.PD
+-.RE
+-.LP
+-The following
+-.I parameters
+-are used but not set by the shell.
+-.RS
+-.TP
+-.B
+-.SM HOME
+-The default argument (home directory) for the
+-.B cd
+-command.
+-.PD 0
+-.TP
+-.B
+-.SM PATH
+-The search path for commands (see
+-.BR execution ).
+-.TP
+-.B
+-.SM MAIL
+-If this variable is set to the name of
+-a mail file then the shell informs the user of
+-the arrival of mail in the specified file.
+-.SM
+-.TP
+-.B PS1
+-Primary prompt string, by default `$ '.
+-.TP
+-.SM
+-.B PS2
+-Secondary prompt string, by default `> '.
+-.TP
+-.SM
+-.B IFS
+-Internal field separators,
+-normally
+-.BR space ,
+-.BR tab ,
+-and
+-.BR newline .
+-.PD
+-.RE
+-.PP
+-.B Blank interpretation.
+-.br
+-After parameter and command substitution,
+-any results of substitution are scanned for internal field separator
+-characters (those found in
+-.SM
+-.BR $IFS \*S)
+-and split into distinct arguments where such characters are found.
+-Explicit null arguments ("" or \'\') are retained.
+-Implicit null arguments
+-(those resulting from
+-.I parameters
+-that have no values) are removed.
+-.PP
+-.B File name generation.
+-.br
+-Following substitution, each command word is scanned for
+-the characters
+-.BR * ,
+-.B ?
+-and
+-.B \*(OK.
+-If one of these characters appears
+-then the word is regarded as a pattern.
+-The word is replaced with alphabetically sorted file names that match the pattern.
+-If no file name is found that matches the pattern then
+-the word is left unchanged.
+-The character
+-.B .
+-at the start of a file name
+-or immediately following a
+-.BR / ,
+-and the character
+-.BR / ,
+-must be matched explicitly.
+-.TP 
+-.B \*(ST
+-Matches any string, including the null string.
+-.PD 0
+-.TP 
+-.B ?
+-Matches any single character.
+-.TP 
+-.B \*(OK...\*(CK
+-Matches any one of the characters
+-enclosed.
+-A pair of characters separated by
+-.B \-
+-matches any
+-character lexically between the pair.
+-.PD
+-.PP
+-.B Quoting.
+-.br
+-The following characters have a special meaning to the shell
+-and cause termination of a word unless quoted.
+-.LP
+-      \fB;   &   (   )   \(or   \*(LT   \*(GT   newline   space   tab\fP
+-.LP
+-A character may be
+-.I quoted
+-by preceding
+-it with a
+-.B
+-\\\|.
+-.B \\\\newline
+-is ignored.
+-All characters enclosed between a pair of quote marks (\fB\'\|\'\fP),
+-except a single quote,
+-are quoted.
+-Inside double quotes
+-(\fB"\|"\fP)
+-parameter and command substitution occurs and
+-.B
+-\\
+-quotes the characters
+-.B
+-\\ \` "
+-and
+-.BR $ \|.
+-.LP
+-.B
+-"$*"
+-is equivalent to
+-.SM
+-.B
+-"$1 $2 ..."
+-whereas
+-.br
+-.B
+-"$@"
+-is equivalent to
+-.SM
+-.B
+-"$1" "$2" ... .
+-.PP
+-.B Prompting.
+-.br
+-When used interactively,
+-the shell prompts with the value of
+-.SM
+-PS1
+-before reading a command.
+-If at any time a newline is typed and further input is needed
+-to complete a command then the secondary prompt
+-.RB ( \s-2$PS2\s0 )
+-is issued.
+-.PP
+-.B Input output.
+-.br
+-Before a command is executed its input and output
+-may be redirected using a special notation interpreted by the shell.
+-The following may appear anywhere in a simple-command
+-or may precede or follow a
+-.I command
+-and are not passed on to the invoked command.
+-Substitution occurs before
+-.I word
+-or
+-.I digit
+-is used.
+-.TP
+-\*(LT\fI\|word\fP
+-Use file
+-.I word
+-as standard input (file descriptor 0).
+-.PD
+-.TP
+-\*(GT\fI\|word\fP
+-Use file
+-.I word
+-as standard output (file descriptor 1).
+-If the file does not exist then it is created;
+-otherwise it is truncated to zero length.
+-.TP
+-\*(GT\*(GT\fI\|word\fP
+-Use file
+-.I word
+-as standard output.
+-If the file exists then output is appended (by seeking to the end);
+-otherwise the file is created.
+-.TP
+-\*(LT\*(LT\fI\|word\fP
+-The shell input is read up to a line the same as
+-.IR word ,
+-or end of file.
+-The resulting document becomes
+-the standard input.
+-If any character of
+-.I word
+-is quoted then no interpretation
+-is placed upon the characters of the document;
+-otherwise, parameter and command substitution occurs,
+-.B
+-\\newline
+-is ignored,
+-and
+-.B
+-\\
+-is used to quote the characters
+-.B
+-\\ $ \`
+-and the first character of
+-.I word.
+-.TP
+-\*(LT\|&\|\fIdigit\fP
+-The standard input is duplicated from file descriptor
+-.I digit;
+-see
+-.IR dup (2).
+-Similarly for the standard output using \*(GT\|.
+-.TP
+-\*(LT\|&\|\-
+-The standard input is closed.
+-Similarly for the standard output using \*(GT\|.
+-.PD
+-.LP
+-If one of the above is preceded by a digit
+-then the
+-file descriptor created is that specified
+-by the digit
+-(instead of the default 0 or 1).
+-For example,
+-.LP
+-      \&... 2\*(GT&1
+-.LP
+-creates file descriptor 2 to be a duplicate
+-of file descriptor 1.
+-.LP
+-If a command is followed by
+-.B &
+-then the default standard input
+-for the command
+-is the empty file
+-(/dev/null).
+-Otherwise, the environment for the execution of a command contains the
+-file descriptors of the invoking shell as modified by input
+-output specifications.
+-.PP
+-.B Environment.
+-.br
+-The environment
+-is a list of name-value pairs that is passed to
+-an executed program in the same way as a normal argument list;
+-see
+-.IR exec (2)
+-and
+-.IR environ (5).
+-The shell interacts with the environment in several ways.
+-On invocation, the shell scans the environment
+-and creates a
+-.I parameter
+-for each name found,
+-giving it the corresponding value.
+-Executed commands inherit the same environment.
+-If the user modifies the values of these
+-.I parameters
+-or creates new ones,
+-none of these affects the environment
+-unless the
+-.B export
+-command is used to bind the shell's
+-.I parameter
+-to the environment.
+-The environment seen by any executed command is thus composed
+-of any unmodified name-value pairs originally inherited by the shell,
+-plus any modifications or additions,
+-all of which must be noted in
+-.B export
+-commands.
+-.LP
+-The environment for any
+-.I simple-command
+-may be augmented by prefixing it with one or more assignments to
+-.I parameters.
+-Thus these two lines are equivalent
+-.IP
+-TERM=450 cmd args
+-.br
+-(export TERM; TERM=450; cmd args)
+-.LP
+-If the
+-.B \-k
+-flag is set,
+-.I all
+-keyword arguments are placed in the environment,
+-even if the occur after the command name.
+-The following prints `a=b c' and `c':
+-.nf
+-echo a=b c
+-set \-k
+-echo a=b c
+-.fi
+-.PP
+-.B Signals.
+-.br
+-The INTERRUPT and QUIT signals for an invoked
+-command are ignored if the command is followed by
+-.BR & ;
+-otherwise signals have the values
+-inherited by the shell from its parent.
+-(But see also
+-.BR trap. )
+-.PP
+-.B Execution.
+-.br
+-Each time a command is executed the above substitutions
+-are carried out.
+-Except for the `special commands' listed below a new
+-process is created and
+-an attempt is made to execute the command via an
+-.IR exec (2).
+-.LP
+-The shell parameter
+-.B
+-.SM $PATH
+-defines the search path for
+-the directory containing the command.
+-Each alternative directory name is separated by
+-a colon
+-.RB ( : ).
+-The default path is
+-.BR :/bin:/usr/bin .
+-If the command name contains a / then the search path
+-is not used.
+-Otherwise, each directory in the path is
+-searched for an executable file.
+-If the file has execute permission but is not an
+-.I a.out
+-file,
+-it is assumed to be a file containing shell commands.
+-A subshell (i.e., a separate process) is spawned to read it.
+-A parenthesized command is also executed in
+-a subshell.
+-.PP
+-.B Special commands.
+-.br
+-The following commands are executed in the shell process
+-and except where specified
+-no input output redirection is permitted for such commands.
+-.TP
+-.B :
+-No effect; the command does nothing.
+-.PD 0
+-.TP
+-.BI . \ file
+-Read and execute commands from
+-.I file
+-and return.
+-The search path
+-.B
+-.SM $PATH
+-is used to find the directory containing
+-.IR file .
+-.TP
+-\fBbreak\fR \*(OK\fIn\fR\*(CK
+-Exit from the enclosing
+-.B for
+-or
+-.B while
+-loop, if any.
+-If
+-.I n
+-is specified then break
+-.I n
+-levels.
+-.TP
+-\fBcontinue\fR \*(OK\fIn\fR\*(CK
+-Resume the next iteration of the enclosing
+-.B for
+-or
+-.B while
+-loop.
+-If
+-.I n
+-is specified then resume at the
+-.IR n -th
+-enclosing loop.
+-.TP
+-\fBcd\fR \*(OK\fIarg\fR\*(CK
+-Change the current directory to
+-.I arg.
+-The shell
+-parameter
+-.B
+-.SM $HOME
+-is the default
+-.IR arg .
+-.TP
+-\fBeval\fR \*(OK\fIarg \fR...\*(CK
+-The arguments are read as input
+-to the shell
+-and the resulting command(s) executed.
+-.TP
+-\fBexec\fR \*(OK\fIarg \fR...\*(CK
+-The command specified by
+-the arguments is executed in place of this shell
+-without creating a new process.
+-Input output arguments may appear and if no other
+-arguments are given cause the shell input
+-output to be modified.
+-.TP
+-\fBexit\fR \*(OK\fIn\fR\*(CK
+-Causes a non interactive shell to exit
+-with the exit status specified by
+-.I n.
+-If
+-.I n
+-is omitted then the exit status is that of the last command executed.
+-(An end of file will also exit from the shell.)
+-.TP
+-\fBexport\fR \*(OK\fIname\fR ...\*(CK
+-The given names are marked
+-for automatic export to the
+-.I environment
+-of subsequently-executed commands.
+-If no arguments are given then a list of
+-exportable names is printed.
+-.TP
+-\fBlogin\fR \*(OK\fIarg\fR ...\*(CK
+-Equivalent to `exec login arg ...'.
+-.TP
+-\fBnewgrp\fR \*(OK\fIarg \fR...\*(CK
+-Equivalent to `exec newgrp arg ...'.
+-.TP
+-.BI read \ name\ ...
+-One line is read from the standard input;
+-successive words of the input are assigned to the
+-variables
+-.I name
+-in order,
+-with leftover words to the last variable.
+-The return code is 0 unless the end-of-file is encountered.
+-.TP
+-\fBreadonly\fR \*(OK\fIname \fR...\*(CK
+-The given names are marked readonly and
+-the values of the these names may not be changed
+-by subsequent assignment.
+-If no arguments are given then a list
+-of all readonly names is printed.
+-.TP
+-\fBset\fR \*(OK\fB\-eknptuvx\fR \*(OK\fIarg \fR...\*(CK\*(CK
+-.RS
+-.PD 0
+-.TP 3m
+-.B \-e
+-If non interactive then exit immediately if a command fails.
+-.TP
+-.B \-k
+-All keyword arguments are placed in the environment for a command,
+-not just those that precede the command name.
+-.TP
+-.B \-n
+-Read commands but do not execute them.
+-.TP
+-.B \-t
+-Exit after reading and executing one command.
+-.TP
+-.B \-u
+-Treat unset variables as an error when substituting.
+-.TP
+-.B \-v
+-Print shell input lines as they are read.
+-.TP
+-.B \-x
+-Print commands and their arguments as they are executed.
+-.TP
+-.B \-
+-Turn off the
+-.B \-x
+-and
+-.B \-v
+-options.
+-.PD
+-.LP
+-These flags can also be used upon invocation of the shell.
+-The current set of flags may be found in
+-.BR $\- .
+-.LP
+-Remaining arguments are positional
+-parameters and are assigned, in order, to
+-.SM
+-.BR $1 ,
+-.SM
+-.BR $2 ,
+-etc.
+-If no arguments are given then the values
+-of all names are printed.
+-.RE
+-.TP
+-.B shift
+-The positional parameters from
+-.SM
+-.BR $2 ...
+-are renamed
+-.SM
+-.BR $1 ...
+-.TP
+-.B times
+-Print the accumulated user and system times for
+-processes run from the shell.
+-.TP
+-\fBtrap\fR \*(OK\fIarg\fR\*(CK \*(OK\fIn\fR\*(CK ...
+-.I Arg
+-is a command to be read and executed when the shell
+-receives signal(s)
+-.I n.
+-(Note that
+-.I arg
+-is scanned once when
+-the trap is set and once when the trap
+-is taken.)
+-Trap commands are executed in order of signal number.
+-If
+-.I arg
+-is absent then all trap(s)
+-.I n
+-are reset
+-to their original values.
+-If
+-.I arg
+-is the null
+-string then this signal is ignored by the shell and by invoked commands.
+-If
+-.I n
+-is 0 then the command
+-.I arg
+-is executed
+-on exit from the shell,
+-otherwise upon receipt of signal
+-.I n
+-as numbered in
+-.IR signal (2).
+-.I Trap
+-with no arguments prints a list
+-of commands associated with each signal number.
+-.TP
+-\fBumask \fR[ \fInnn\fR ]
+-The user file creation mask is set to
+-the octal value
+-.I nnn
+-(see
+-.IR umask (2)).
+-If
+-.I nnn
+-is omitted, the current value of the mask is printed.
+-.TP
+-\fBwait\fP \*(OK\fIn\fP\*(CK
+-Wait for the specified process and
+-report its termination status.
+-If
+-.I n
+-is not given then all currently active child processes are waited for.
+-The return code from this command is that of
+-the process waited for.
+-.PD
+-.LP
+-.PP
+-.B Invocation.
+-.br
+-If the first character of argument zero is
+-.BR \- ,
+-commands are read from
+-.BR \s-2$HOME\s0/.\|profile ,
+-if such a file exists.
+-Commands are then read as described below.
+-The following flags are interpreted by the shell
+-when it is invoked.
+-.PD 0
+-.TP 11n
+-.BI \-c \ string
+-If the
+-.B \-c
+-flag is present then
+-commands are read from
+-.I string\|.
+-.TP 11n
+-.B \-s
+-If the
+-.B \-s
+-flag is present or if no
+-arguments remain
+-then commands are read from the standard input.
+-Shell output is written to
+-file descriptor 2.
+-.TP 11n
+-.B \-i
+-If the
+-.B \-i
+-flag is present or
+-if the shell input and output are attached to a terminal (as told by
+-.IR gtty )
+-then this shell is
+-.I interactive.
+-In this case the terminate signal
+-SIGTERM (see
+-.IR signal (2))
+-is ignored (so that `kill 0'
+-does not kill an interactive shell) and the interrupt signal
+-SIGINT is caught and ignored
+-(so that
+-.B wait
+-is interruptable).
+-In all cases SIGQUIT is ignored by the shell.
+-.PD
+-.LP
+-The remaining flags and arguments are described under the
+-.B set
+-command.
+-.SH FILES
+-.RB $HOME/ . \^profile
+-.br
+-/tmp/sh*
+-.br
+-/dev/null
+-.SH SEE ALSO
+-test(1),
+-exec(2),
+-.SH DIAGNOSTICS
+-Errors detected by the shell, such as syntax errors
+-cause the shell
+-to return a non zero exit status.
+-If the shell is being used non interactively
+-then execution of the shell file is abandoned.
+-Otherwise, the shell returns the exit status of
+-the last command executed (see also
+-.BR exit ).
+-.SH BUGS
+-If \*(LT\*(LT is used to provide standard input to an asynchronous
+-process invoked by &,
+-the shell gets mixed up about naming the input document.
+-A garbage file /tmp/sh* is created, and the shell complains about
+-not being able to find the file by another name.
+//GO.SYSIN DD sh.1
+echo size.1
+sed 's/.//' >size.1 <<'//GO.SYSIN DD size.1'
+-.TH SIZE 1 
+-.SH NAME
+-size \- size of an object file
+-.SH SYNOPSIS
+-.B size
+-[ object ... ]
+-.SH DESCRIPTION
+-.I Size
+-prints the (decimal) number of bytes
+-required by the
+-text, data, and bss
+-portions, and their sum in octal and decimal,
+-of each object-file argument.
+-If no file is specified,
+-.B a.out
+-is used.
+-.SH "SEE ALSO"
+-a.out(5)
+//GO.SYSIN DD size.1
+echo sleep.1
+sed 's/.//' >sleep.1 <<'//GO.SYSIN DD sleep.1'
+-.TH SLEEP 1 
+-.SH NAME
+-sleep \- suspend execution for an interval
+-.SH SYNOPSIS
+-.B sleep
+-time
+-.SH DESCRIPTION
+-.I Sleep
+-suspends execution for
+-.I time
+-seconds.
+-It is used to execute a command
+-after a certain amount of time as in:
+-.PP
+-      (sleep 105; command)&
+-.PP
+-or to execute a command every so often, as in:
+-.PP
+-      while true
+-.br
+-      do
+-.br
+-              command
+-.br
+-              sleep 37
+-.br
+-      done
+-.SH "SEE ALSO"
+-alarm(2), sleep(3)
+-.SH BUGS
+-.I Time
+-must be less than 65536 seconds.
+//GO.SYSIN DD sleep.1
+echo sort.1
+sed 's/.//' >sort.1 <<'//GO.SYSIN DD sort.1'
+-.TH SORT 1 
+-.SH NAME
+-sort \- sort or merge files
+-.SH SYNOPSIS
+-.B sort
+-[
+-.if t \fB\-mubdf\&inrt\fIx\fR
+-.if n -mubdfinrt\b\b\b\b\b\b\b\b\b_________x
+-]
+-[ \fB+\fIpos1 \fR [ \fB\-\fIpos2 \fR]
+-] ...
+-[ 
+-.B \-o 
+-name ] [
+-.B \-T
+-directory ] [ name ] ...
+-.SH DESCRIPTION
+-.I Sort
+-sorts
+-lines of all the named files together
+-and writes the result on
+-the standard output.
+-The name `\-' means
+-the standard input.
+-If no input files are named, the standard input is sorted.
+-.PP
+-The default sort key is an entire line.
+-Default ordering is
+-lexicographic by bytes in machine
+-collating sequence.
+-The ordering is affected globally by the following options,
+-one or more of which may appear.
+-.TP 5
+-.B  b
+-Ignore leading blanks (spaces and tabs) in field comparisons.
+-.TP 5
+-.B  d
+-`Dictionary' order: only letters, digits and blanks
+-are significant in comparisons.
+-.TP 5
+-.B  f
+-Fold upper case
+-letters onto lower case.
+-.TP 5
+-.B  i
+-Ignore characters outside the ASCII range 040-0176
+-in nonnumeric comparisons.
+-.TP 5
+-.B  n
+-An initial numeric string,
+-consisting of optional blanks, optional minus sign,
+-and zero or more digits with optional decimal point,
+-is sorted by arithmetic value.
+-Option
+-.B n
+-implies option
+-.B b.
+-.TP 5
+-.B  r
+-Reverse the sense of comparisons.
+-.TP 5
+-.BI t x
+-`Tab character' separating fields is
+-.IR x .
+-.PP
+-The notation
+-.BI + "pos1 " "\-\fIpos2"
+-restricts a sort key to a field beginning at
+-.I pos1
+-and ending just before
+-.IR pos2 .
+-.I Pos1
+-and
+-.I pos2
+-each have the form
+-.IB m . n\fR,
+-optionally followed by one or more of the flags
+-.B bdf\&inr,
+-where
+-.I m
+-tells a number of fields to skip from the beginning of the line and
+-.I n
+-tells a number of characters to skip further.
+-If any flags are present they override all the global
+-ordering options for this key.
+-If the
+-.B b
+-option is in effect
+-.I n
+-is counted from the first nonblank in the field;
+-.B b
+-is attached independently to 
+-.IR pos2 .
+-A missing
+-\&\fB.\fIn\fR
+-means .0;
+-a missing
+-.BI \- pos2
+-means the end of the line.
+-Under the
+-.BI \-t x
+-option, fields are strings separated by
+-.IR x ;
+-otherwise fields are
+-nonempty nonblank strings separated by blanks.
+-.PP
+-When there are multiple sort keys, later keys
+-are compared only after all earlier keys
+-compare equal.
+-Lines that otherwise compare equal are ordered
+-with all bytes significant.
+-.PP
+-These option arguments are also understood:
+-.TP 5
+-.B c
+-Check that the input file is sorted according to the ordering rules;
+-give no output unless the file is out of sort.
+-.TP 5
+-.B  m
+-Merge only, the input files are already sorted.
+-.TP 5
+-.B  o
+-The next argument is the name of an output file
+-to use instead of the standard output.
+-This file may be the same as one of the inputs.
+-.TP 5
+-.B T
+-The next argument is the name of a directory in which temporary files
+-should be made.
+-.TP 5
+-.B  u
+-Suppress all but one in each
+-set of equal lines.
+-Ignored bytes
+-and bytes outside keys
+-do not participate in
+-this comparison.
+-.PP
+-.B Examples.
+-Print in alphabetical order all the unique spellings
+-in a list of words.
+-Capitalized words differ from uncapitalized.
+-.PP
+-.ti +8
+-sort \-u +0f +0 list
+-.PP
+-Print the password file
+-.RI ( passwd (5))
+-sorted by user id number (the 3rd colon-separated field).
+-.PP
+-.ti +8
+-sort \-t: +2n /etc/passwd
+-.PP
+-Print the first instance of each month in an already sorted file
+-of (month day) entries.
+-The options
+-.B \-um
+-with just one input file make the choice of a
+-unique representative from a set of equal lines predictable.
+-.PP
+-.ti +8
+-sort \-um +0 \-1 dates
+-.SH FILES
+-/usr/tmp/stm*, /tmp/*: first and second tries for
+-temporary files
+-.SH "SEE ALSO"
+-uniq(1),
+-comm(1),
+-rev(1),
+-join(1)
+-.SH DIAGNOSTICS
+-Comments and exits with nonzero status for various trouble
+-conditions and for disorder discovered under option
+-.BR \-c .
+-.SH BUGS
+-Very long lines are silently truncated.
+//GO.SYSIN DD sort.1
+echo spell.1
+sed 's/.//' >spell.1 <<'//GO.SYSIN DD spell.1'
+-.TH SPELL 1 
+-.SH NAME
+-spell, spellin, spellout \- find spelling errors
+-.SH SYNOPSIS
+-.B spell
+-[ option ] ...
+-[ file ] ...
+-.PP
+-.B /usr/src/cmd/spell/spellin
+-[ list ]
+-.PP
+-.B /usr/src/cmd/spell/spellout
+-[
+-.B \-d
+-] list
+-.SH DESCRIPTION
+-.I Spell
+-collects words from the named documents,
+-and looks them up in a spelling list.
+-Words that neither occur among nor are derivable
+-(by applying certain inflections,
+-prefixes or suffixes) from words in the spelling list
+-are printed on the standard output.
+-If no files are named,
+-words are collected from the standard input.
+-.PP
+-.I Spell
+-ignores most
+-.I troff,
+-.I tbl
+-and
+-.IR  eqn (1)
+-constructions.
+-.PP
+-Under the
+-.B \-v
+-option, all words not literally in the spelling list are printed,
+-and plausible derivations from spelling list words are indicated.
+-.PP
+-Under the 
+-.B \-b
+-option, British spelling is checked.
+-Besides preferring
+-.ft I
+-centre, colour, speciality, travelled,
+-.ft R
+-etc.,
+-this option insists upon
+-.I -ise
+-in words like
+-.I standardise,
+-Fowler and the OED to the contrary
+-notwithstanding.
+-.PP
+-Under the 
+-.B \-x
+-option, every plausible stem is printed with `=' for each word.
+-.PP
+-The spelling list is based on many sources,
+-and while more haphazard than an ordinary
+-dictionary, is also more effective in respect to
+-proper names and popular technical words.
+-Coverage of
+-the specialized vocabularies of biology,
+-medicine and chemistry is light.
+-.PP
+-Pertinent auxiliary files may be specified by
+-name arguments, indicated below with their
+-default settings.
+-Copies of all output
+-are accumulated in the history file.
+-The stop list filters out misspellings (e.g. thier=thy\-y+ier)
+-that would otherwise pass.
+-.PP
+-Two routines help maintain the hash lists used by
+-.I spell.
+-Both expect a list of words, one per line,
+-from the standard input.
+-.I Spellin
+-adds the words on the standard input to the
+-preexisting
+-.I list
+-and places a new list on the standard output.
+-If no 
+-.I list
+-is specified, the new list is created from scratch.
+-.I Spellout
+-looks up each word in the standard input and prints
+-on the standard output
+-those that are missing from (or present on, with
+-option
+-.BR \-d )
+-the hash list.
+-.SH FILES
+-D=/usr/dict/hlist[ab]: hashed spelling lists, American & British
+-.br
+-S=/usr/dict/hstop: hashed stop list
+-.br
+-H=/usr/dict/spellhist: history file
+-.br
+-/usr/lib/spell
+-.br
+-deroff(1), sort(1), tee(1), sed(1)
+-.SH BUGS
+-The spelling list's coverage is uneven;
+-new installations will probably wish to 
+-monitor the output for several months to gather
+-local additions.
+-.br
+-British spelling was done by an American.
+//GO.SYSIN DD spell.1
+echo spline.1g
+sed 's/.//' >spline.1g <<'//GO.SYSIN DD spline.1g'
+-.TH SPLINE 1G 
+-.SH NAME
+-spline \- interpolate smooth curve
+-.SH SYNOPSIS
+-.B spline
+-[ option ] ...
+-.SH DESCRIPTION
+-.I Spline
+-takes pairs of numbers from the standard input as abcissas and ordinates
+-of a function.
+-It produces a similar set, which
+-is approximately equally spaced and
+-includes the input set, on the standard output.
+-The cubic spline output
+-(R. W. Hamming,
+-.ft I
+-Numerical Methods for Scientists and Engineers,
+-.ft R
+-2nd ed., 349ff)
+-has two continuous derivatives,
+-and sufficiently many points to look smooth when plotted, for
+-example by
+-.IR  graph (1).
+-.PP
+-The following options are recognized,
+-each as a separate argument.
+-.TP 5
+-.B  \-a
+-Supply abscissas automatically (they are missing from
+-the input); spacing is given by the next
+-argument, or is assumed to be 1 if next argument is not a number.
+-.TP 5
+-.B  \-k
+-The constant
+-.IR k ""
+-used in the boundary value computation
+-.IP
+-.if n .ig
+-.ti +1.5i
+-.ds ' \h'-\w'\(fm\(fm'u'
+-.EQ
+-.nr 99 \n(.s
+-.nr 98 \n(.f
+-'ps 10
+-.ft I
+-.ds 11 "y\(fm\(fm
+-.nr 11 \w'\*(11'
+-.ds 12 "\*'
+-.nr 12 \w'\*(12'
+-'ps 8
+-.ds 13 "\fR0\fP
+-.nr 13 \w'\*(13'
+-.as 12 \v'18u'\s8\*(13\|\s10\v'-18u'
+-'ps 10
+-.nr 12 \n(12+\n(13+\w'\s8\|'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|=\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "ky\(fm\(fm
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\*'
+-.nr 12 \w'\*(12'
+-'ps 8
+-.ds 13 "\fR1\fP
+-.nr 13 \w'\*(13'
+-.as 12 \v'18u'\s8\*(13\|\s10\v'-18u'
+-'ps 10
+-.nr 12 \n(12+\n(13+\w'\s8\|'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 ",
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "y\(fm\(fm
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\*'
+-.nr 12 \w'\*(12'
+-'ps 8
+-.ds 13 "n
+-.nr 13 \w'\*(13'
+-.as 12 \v'18u'\s8\*(13\|\s10\v'-18u'
+-'ps 10
+-.nr 12 \n(12+\n(13+\w'\s8\|'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|=\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\|\|
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "ky\(fm\(fm
+-.nr 12 \w'\*(12'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 12 "\*'
+-.nr 12 \w'\*(12'
+-'ps 8
+-.ds 13 "n\|\(mi\|\fR1\fP
+-.nr 13 \w'\*(13'
+-.as 12 \v'18u'\s8\*(13\|\s10\v'-18u'
+-'ps 10
+-.nr 12 \n(12+\n(13+\w'\s8\|'
+-.as 11 "\*(12
+-.nr 11 \w'\*(11'
+-.ds 11 \x'0'\fI\*(11\s\n(99\f\n(98
+-.ne 78u
+-\*(11
+-'ps \n(99
+-.ft \n(98
+-.EN
+-..
+-.if t .ig
+-.ce
+-(2nd deriv. at end) = k*(2nd deriv. next to end)
+-..
+-.IP
+-.br
+-is set by the next argument.
+-By default
+-.IR k ""
+-= 0.
+-.TP 5
+-.B  \-n
+-Space output points
+-so that approximately
+-.I n
+-intervals occur between the lower and upper
+-.I x
+-limits.
+-(Default
+-.I n
+-= 100.)
+-.TP 5
+-.B  \-p
+-Make output periodic, i.e. match
+-derivatives at ends.
+-First and last input values should normally agree.
+-.TP 5
+-.B  \-x
+-Next 
+-1 (or 2) arguments are lower (and upper) 
+-.I x
+-limits.
+-Normally these limits are calculated from the data.
+-Automatic abcissas start at lower limit
+-(default 0).
+-.SH "SEE ALSO"
+-graph(1)
+-.SH DIAGNOSTICS
+-When data is not strictly monotone in
+-.I x,
+-.I spline
+-reproduces the input without interpolating extra points.
+-.SH BUGS
+-A limit of 1000 input points is enforced silently.
+//GO.SYSIN DD spline.1g
+echo split.1
+sed 's/.//' >split.1 <<'//GO.SYSIN DD split.1'
+-.TH SPLIT 1 
+-.SH NAME
+-split \- split a file into pieces
+-.SH SYNOPSIS
+-.B split
+-[
+-.B \-\fIn
+-]
+-[ file [ name ] ]
+-.SH DESCRIPTION
+-.I Split
+-reads
+-.I file
+-and writes
+-it in
+-.IR n -line
+-pieces
+-(default 1000), as many as necessary,
+-onto
+-a set of output files.  The name of the first output
+-file is
+-.I name
+-with
+-.B aa
+-appended, and so on
+-lexicographically.
+-If no output name is given,
+-.B x
+-is default.
+-.PP
+-If no input file is given, or
+-if
+-.B \-
+-is given in its stead,
+-then the standard input file is used.
+//GO.SYSIN DD split.1
+echo strip.1
+sed 's/.//' >strip.1 <<'//GO.SYSIN DD strip.1'
+-.TH STRIP 1 
+-.SH NAME
+-strip  \-  remove symbols and relocation bits
+-.SH SYNOPSIS
+-.B strip
+-name ...
+-.SH DESCRIPTION
+-.I Strip
+-removes the symbol
+-table and relocation bits ordinarily attached to the output
+-of the assembler and loader.
+-This is useful to save space after a program has been
+-debugged.
+-.PP
+-The effect of
+-.I strip
+-is the same as use of the
+-.B \-s
+-option
+-of
+-.IR ld .
+-.SH FILES
+-/tmp/stm?     temporary file
+-.SH "SEE ALSO"
+-ld(1)
+//GO.SYSIN DD strip.1
+echo struct.1
+sed 's/.//' >struct.1 <<'//GO.SYSIN DD struct.1'
+-.TH STRUCT 1 
+-.SH NAME
+-struct \- structure Fortran programs
+-.SH SYNOPSIS
+-.B struct
+-[ option ] ...
+-file
+-.SH DESCRIPTION
+-.LP
+-.I Struct
+-translates the Fortran program specified by
+-.I file
+-(standard input default)
+-into a Ratfor program.
+-Wherever possible, Ratfor control constructs
+-replace the original Fortran.
+-Statement numbers appear only where still necessary.
+-Cosmetic changes are made, including changing Hollerith strings
+-into quoted strings
+-and relational operators into symbols (.e.g. `.GT.' into `>').
+-The output is appropriately indented.
+-.PP
+-The following options may occur in any order.
+-.TP
+-.B  \-s
+-Input is accepted in standard format, i.e.
+-comments are specified by a c, C, or * in column 1, and continuation lines
+-are specified by a nonzero, nonblank character in column 6.
+-Normally, a statement whose first nonblank character
+-is not alphanumeric is treated as a continuation.
+-.TP
+-.B  \-i
+-Do not turn computed goto statements into
+-switches.
+-(Ratfor does not turn switches back
+-into computed goto statements.)
+-.TP
+-.B  \-a
+-Turn sequences of else ifs into a
+-non-Ratfor switch of the form
+-.IP
+-.nf
+-.ta 5 7
+-switch {
+-              case pred1: code
+-              case pred2: code
+-              case pred3: code
+-              default: code
+-      }
+-.fi
+-.DT
+-.IP
+-The case predicates are tested in order;
+-the code appropriate to only one case is executed.
+-This generalized form of switch statement does not
+-occur in Ratfor.
+-.TP
+-.B  \-b
+-Generate goto's instead of multilevel break statements.
+-.TP
+-.B  \-n
+-Generate goto's instead of multilevel next statements.
+-.TP
+-.TP
+-.BI \-e n
+-If 
+-.I n
+-is 0 (default),
+-place code within a loop only if it can
+-lead to an iteration of the loop.
+-If
+-.I n
+-is nonzero,
+-admit code segments with fewer than
+-.I n
+-statements to a loop
+-if otherwise the loop would have exits to several places including the segment,
+-and the segment can be reached only from the loop.
+-.SH FILES
+-/tmp/struct*
+-.br
+-/usr/lib/struct/*
+-.SH SEE ALSO
+-f77(1)
+-.SH BUGS
+-Struct knows Fortran 66 syntax, but not full Fortran 77
+-(alternate returns, IF...THEN...ELSE, etc.)
+-.br
+-If an input Fortran program contains identifiers which
+-are reserved words in Ratfor, the structured
+-version of the program
+-will not be a valid Ratfor program.
+-.br
+-Extended range DO's generate cryptic errors.
+-.br
+-Columns 73-80 are not special even when
+-.B \-s
+-is in effect.
+-.br
+-Will not generate Ratfor FOR statements.
+//GO.SYSIN DD struct.1
+echo stty.1
+sed 's/.//' >stty.1 <<'//GO.SYSIN DD stty.1'
+-.TH STTY 1 
+-.SH NAME
+-stty \- set terminal options
+-.SH SYNOPSIS
+-.B stty
+-[ option ... ]
+-.SH DESCRIPTION
+-.I Stty
+-sets certain I/O options on the current output terminal.
+-With no argument, it reports the current settings of the options.
+-The option strings are
+-selected from the following set:
+-.TP  8n
+-.B even 
+-allow even parity
+-.br
+-.ns
+-.TP 
+-.B \-even 
+-disallow even parity
+-.br
+-.ns
+-.TP 
+-.B odd 
+-allow odd parity
+-.br
+-.ns
+-.TP 
+-.B \-odd 
+-disallow odd parity
+-.br
+-.ns
+-.TP 
+-.B raw 
+-raw mode input
+-(no erase, kill, interrupt, quit, EOT; parity bit passed back)
+-.br
+-.ns
+-.TP 
+-.B \-raw 
+-negate raw mode
+-.br
+-.ns
+-.TP 
+-.B cooked 
+-same as `\-raw'
+-.br
+-.ns
+-.TP
+-.B cbreak
+-make each character available to
+-.IR read (2)
+-as received; no erase and kill
+-.br
+-.ns
+-.TP
+-.B \-cbreak
+-make characters available to 
+-.I read
+-only when newline is received
+-.br
+-.ns
+-.TP 
+-.B \-nl 
+-allow carriage return for new-line,
+-and output CR-LF for carriage return or new-line
+-.br
+-.ns
+-.TP 
+-.B nl 
+-accept only new-line to end lines
+-.br
+-.ns
+-.TP 
+-.B echo 
+-echo back every character typed
+-.br
+-.ns
+-.TP 
+-.B \-echo 
+-do not echo characters
+-.br
+-.ns
+-.TP 
+-.B lcase 
+-map upper case to lower case
+-.br
+-.ns
+-.TP 
+-.B \-lcase 
+-do not map case
+-.br
+-.ns
+-.TP 
+-.B \-tabs 
+-replace tabs by spaces when printing
+-.br
+-.ns
+-.TP 
+-.B tabs 
+-preserve tabs
+-.br
+-.ns
+-.TP 
+-.B ek 
+-reset erase and kill characters back to normal # and @
+-.br
+-.ns
+-.TP 
+-.BI erase  \ c\fR
+-set erase character to
+-.IR c .
+-.I C
+-can be of the form 
+-.I `^X'
+-which is interpreted as a `control X'.
+-.br
+-.ns
+-.TP 
+-.BI kill  \ c\fR
+-set kill character to
+-.IR c .
+-.I `^X'
+-works here also.
+-.br
+-.ns
+-.TP
+-.B  cr0 cr1 cr2 cr3
+-.br
+-select style of delay for carriage return (see
+-.IR ioctl (2))
+-.br
+-.ns
+-.TP
+-.B  nl0 nl1 nl2 nl3
+-.br
+-select style of delay for linefeed 
+-.br
+-.ns
+-.TP
+-.B  tab0 tab1 tab2 tab3
+-.br
+-select style of delay for tab 
+-.br
+-.ns
+-.TP
+-.B  ff0 ff1
+-select style of delay for form feed 
+-.br
+-.ns
+-.TP
+-.B bs0 bs1
+-select style of delay for backspace
+-.br
+-.ns
+-.TP 
+-.B tty33 
+-set all modes suitable for the
+-Teletype Corporation Model 33 terminal.
+-.br
+-.ns
+-.TP 
+-.B tty37 
+-set all modes suitable for the
+-Teletype Corporation Model 37 terminal.
+-.br
+-.ns
+-.TP 
+-.B vt05 
+-set all modes suitable for Digital Equipment Corp. VT05 terminal
+-.br
+-.ns
+-.TP 
+-.B tn300 
+-set all modes suitable for a General Electric TermiNet 300
+-.br
+-.ns
+-.TP 
+-.B ti700 
+-set all modes suitable for Texas Instruments 700 series terminal
+-.br
+-.ns
+-.TP 
+-.B tek 
+-set all modes suitable for Tektronix 4014 terminal
+-.br
+-.ns
+-.TP 
+-.B hup 
+-hang up dataphone on last close.
+-.br
+-.ns
+-.TP 
+-.B \-hup 
+-do not hang up dataphone on last close.
+-.br
+-.ns
+-.TP 
+-.B 0 
+-hang up phone line immediately
+-.br
+-.ns
+-.TP
+-.B  "50 75 110 134 150 200 300 600 1200 1800 2400 4800 9600 exta extb"
+-.br
+-Set terminal baud rate to the number given, if possible.
+-(These are the speeds supported by the DH-11 interface).
+-.dt
+-.SH "SEE ALSO"
+-ioctl(2), tabs(1)
+//GO.SYSIN DD stty.1
+echo su.1
+sed 's/.//' >su.1 <<'//GO.SYSIN DD su.1'
+-.TH SU 1 
+-.SH NAME
+-su  \-  substitute user id temporarily
+-.SH SYNOPSIS
+-.B su
+-[ userid ]
+-.SH DESCRIPTION
+-.I Su
+-demands the password of the specified
+-.I userid,
+-and if it is given,
+-changes to that 
+-.I userid
+-and invokes the Shell
+-.IR sh (1)
+-without changing the current directory or the
+-user environment (see
+-.IR environ (5)).
+-The new user ID stays in force until the Shell exits.
+-.PP
+-If no 
+-.I userid
+-is specified, `root' is assumed.
+-To remind the super-user of his responsibilities,
+-the Shell substitutes `#' for its usual prompt.
+-.SH "SEE ALSO"
+-sh(1)
+//GO.SYSIN DD su.1
+echo sum.1
+sed 's/.//' >sum.1 <<'//GO.SYSIN DD sum.1'
+-.TH SUM 1 
+-.SH NAME
+-sum \- sum and count blocks in a file
+-.SH SYNOPSIS
+-.B sum
+-file
+-.SH DESCRIPTION
+-.I Sum
+-calculates and prints a 16-bit checksum for the named file,
+-and also prints the number of blocks in the file.
+-It is typically used to look for bad spots, or
+-to validate a file communicated over
+-some transmission line.
+-.SH "SEE ALSO"
+-wc(1)
+-.SH DIAGNOSTICS
+-`Read error'
+-is indistinuishable from end of file on
+-most devices; check the block count.
+//GO.SYSIN DD sum.1
+echo sync.1m
+sed 's/.//' >sync.1m <<'//GO.SYSIN DD sync.1m'
+-.TH SYNC 1M 
+-.SH NAME
+-sync \- update the super block
+-.SH SYNOPSIS
+-.B sync
+-.SH DESCRIPTION
+-.I Sync
+-executes the
+-.I sync
+-system primitive.
+-If the system is to be stopped,
+-.I sync
+-must be called to insure
+-file system integrity.
+-See
+-.IR sync (2)
+-for details.
+-.SH "SEE ALSO"
+-sync(2), update(8)
+//GO.SYSIN DD sync.1m
+echo tabs.1
+sed 's/.//' >tabs.1 <<'//GO.SYSIN DD tabs.1'
+-.TH TABS 1 
+-.SH NAME
+-tabs \- set terminal tabs
+-.SH SYNOPSIS
+-.B tabs
+-[
+-.B \-n
+-] [
+-terminal
+-]
+-.SH DESCRIPTION
+-.I Tabs
+-sets the tabs on a variety of terminals.
+-Various of the terminal names given in
+-.IR term (7)
+-are recognized;
+-the default is, however, suitable for most 300
+-baud terminals.
+-If the
+-.B \-n
+-flag is present then the left
+-margin is not indented as is normal.
+-.SH SEE ALSO
+-stty(1), term(7)
+//GO.SYSIN DD tabs.1
+echo tail.1
+sed 's/.//' >tail.1 <<'//GO.SYSIN DD tail.1'
+-.TH TAIL 1 
+-.SH NAME
+-tail \- deliver the last part of a file
+-.SH SYNOPSIS
+-.B tail
+-.if t [ \(+-number[\fBlbc\fR] ]
+-.if n +\b_number[lbc\b\b\b___]
+-[ file ]
+-.SH DESCRIPTION
+-.I Tail
+-copies the named file to the standard output beginning
+-at a designated place.
+-If no file is named, the standard input is used.
+-.PP
+-Copying begins at distance
+-.I +number
+-from the beginning, or
+-.I \-number
+-from the end of the input.
+-.I Number
+-is counted in units of lines, blocks or characters,
+-according to the appended option
+-.B l,
+-.B b
+-or
+-.B c.
+-When no units are specified, counting is by lines.
+-.SH "SEE ALSO"
+-dd(1)
+-.SH BUGS
+-Tails relative to the end of the file
+-are treasured up in a buffer, and thus 
+-are limited in length.
+-Various kinds of anomalous behavior may happen
+-with character special files.
+//GO.SYSIN DD tail.1
+echo tar.1
+sed 's/.//' >tar.1 <<'//GO.SYSIN DD tar.1'
+-.TH TAR 1 
+-.SH NAME
+-tar  \-  tape archiver
+-.SH SYNOPSIS
+-.B tar
+-[ key ] [ name ... ]
+-.SH DESCRIPTION
+-.I Tar
+-saves and restores files
+-on magtape.
+-Its actions are controlled by the
+-.I key
+-argument.
+-The
+-.I key
+-is a string of characters containing
+-at most one function letter and possibly
+-one or more function modifiers.
+-Other arguments to the command are file or directory
+-names specifying which files are to be dumped or restored.
+-In all cases, appearance of a directory name refers to
+-the files and (recursively) subdirectories of that directory.
+-.PP
+-The function portion of
+-the key is specified by one of the following letters:
+-.TP 8
+-.B  r
+-The named files
+-are written
+-on the end of the tape.
+-The
+-.B c
+-function implies this.
+-.TP 8
+-.B  x
+-The named files are extracted from the tape.
+-If the named file matches a directory whose contents 
+-had been written onto the tape, this directory is (recursively) extracted.
+-The owner, modification time, and mode are restored (if possible).
+-If no file argument is given, the entire content of the
+-tape is extracted.
+-Note that if multiple entries specifying the same file
+-are on the tape, the last one overwrites
+-all earlier.
+-.TP 8
+-.B  t
+-The names of the specified files are listed each time they occur
+-on the tape.
+-If no file argument is given,
+-all of the names on the tape are listed.
+-.TP 8
+-.B  u
+-The named files are added to the tape if either they
+-are not already there or have
+-been modified since last put on the tape.
+-.TP 8
+-.B  c
+-Create a new tape; writing begins on the beginning
+-of the tape instead of after the last file.
+-This command implies
+-.B r.
+-.PP
+-The following characters may be used in addition to the letter
+-which selects the function desired.
+-.TP 10
+-.B  0,...,7
+-This
+-modifier selects the drive on which the tape is mounted.
+-The default is
+-.BR 1 .
+-.TP 10
+-.B  v
+-Normally
+-.I tar
+-does its work silently.
+-The
+-.B v
+-(verbose)
+-option causes it to type the name of each file it treats
+-preceded by the function letter.
+-With the
+-.B t
+-function,
+-.B v
+-gives more information about the
+-tape entries than just the name.
+-.TP 10
+-.B  w
+-causes
+-.I tar
+-to print the action to be taken followed by file name, then
+-wait for user confirmation. If a word beginning with `y'
+-is given, the action is performed. Any other input means
+-don't do it.
+-.TP 10
+-.B f
+-causes 
+-.I tar
+-to use the next argument as the name of the archive instead
+-of /dev/mt?. 
+-If the name of the file is `\-', tar writes to
+-standard output or reads from standard input, whichever is
+-appropriate. Thus,
+-.I tar
+-can be used as the head or tail of a filter chain
+-.I Tar
+-can also be used to move hierarchies with the command
+-.ce 1
+-cd fromdir; tar cf - . | (cd todir; tar xf -)
+-.TP 10
+-.B b
+-causes
+-.I tar
+-to use the next argument as the blocking factor for tape
+-records. The default is 1, the maximum is 20. This option
+-should only be used with raw magnetic tape archives (See
+-.B f
+-above).
+-The block size is determined automatically when reading
+-tapes (key letters `x' and `t').
+-.TP 10
+-.B l
+-tells
+-.I tar
+-to complain if it cannot resolve all of the links
+-to the files dumped. If this is not specified, no
+-error messages are printed.
+-.TP 10
+-.B m
+-tells
+-.I tar
+-to not restore the modification times.
+-The mod time
+-will be the time of extraction.
+-.PP
+-.SH FILES
+-/dev/mt?
+-.br
+-/tmp/tar*
+-.SH DIAGNOSTICS
+-Complaints about bad key characters and tape read/write errors.
+-.br
+-Complaints if enough memory is not available to hold
+-the link tables.
+-.SH BUGS
+-There is no way to ask for the
+-.IR n -th
+-occurrence of a file.
+-.br
+-Tape errors are handled ungracefully.
+-.br
+-The
+-.B u
+-option can be slow.
+-.br
+-The
+-.B b
+-option should not be used with archives that are
+-going to be updated. The current magtape driver cannot
+-backspace raw magtape.
+-If the archive is on a disk file the 
+-.B b
+-option should not be used at all, as updating
+-an archive stored in this manner can destroy it.
+-.br
+-The current limit on file name length is
+-100 characters.
+//GO.SYSIN DD tar.1
+echo tbl.1
+sed 's/.//' >tbl.1 <<'//GO.SYSIN DD tbl.1'
+-.TH TBL 1 
+-.SH NAME
+-tbl \- format tables for nroff or troff
+-.SH SYNOPSIS
+-.B tbl
+-[ files ] ...
+-.SH DESCRIPTION
+-.I Tbl
+-is a preprocessor for formatting tables for
+-.I nroff
+-or
+-.IR troff (1).
+-The input files are copied to the standard output,
+-except for lines between .TS and .TE
+-command lines, which are assumed to describe tables
+-and reformatted.
+-Details are given in the reference manual.
+-.PP
+-As an example, letting \\t represent a tab (which should
+-be typed as a genuine tab)
+-the input
+-.IP ""
+-\&.TS
+-.nf
+-c s s
+-c c s
+-c c c
+-l n n.
+-Household Population
+-Town\\tHouseholds
+-\\tNumber\\tSize
+-Bedminster\\t789\\t3.26
+-Bernards Twp.\\t3087\\t3.74
+-Bernardsville\\t2018\\t3.30
+-Bound Brook\\t3425\\t3.04
+-Branchburg\\t1644\\t3.49
+-Bridgewater\\t7897\\t3.81
+-Far Hills\\t240\\t3.19
+-\&.TE
+-.LP
+-.fi
+-yields
+-.ne 10
+-.IP " "
+-.TS
+-.nr 35 \n(.u
+-.nf
+-.nr 79 0n
+-.nr 80 \n(79
+-.nr 40 \n(79
+-.nr 38 \n(79+\w!Town!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Bedminster!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Bernards Twp.!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Bernardsville!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Bound Brook!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Branchburg!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Bridgewater!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 38 \n(79+\w!Far Hills!
+-.if \n(80<\n(38 .nr 80 \n(38
+-.nr 81 \n(80
+-.nr 41 \n(80
+-.nr 38 \n(80+\w!Number!
+-.if \n(81<\n(38 .nr 81 \n(38
+-.nr 31 0
+-.nr 32 0
+-.nr 38 \w!789!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3087!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!2018!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3425!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!1644!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!7897!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!240!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 61 \n(80+\n(31
+-.nr 38 \n(61+\n(32
+-.if \n(38>\n(81 .nr 81 \n(38
+-.if \n(38<\n(81 .nr 61 +(\n(81-\n(38)/2
+-.nr 82 \n(81
+-.nr 42 \n(81
+-.nr 38 \n(81+\w!Size!
+-.if \n(82<\n(38 .nr 82 \n(38
+-.nr 31 0
+-.nr 32 0
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.26!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.74!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.30!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.04!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.49!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.81!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 38 \w!3!
+-.if \n(31<\n(38 .nr 31 \n(38
+-.nr 38 \w!.19!
+-.if \n(32<\n(38 .nr 32 \n(38
+-.nr 62 \n(81+\n(31
+-.nr 38 \n(62+\n(32
+-.if \n(38>\n(82 .nr 82 \n(38
+-.if \n(38<\n(82 .nr 62 +(\n(82-\n(38)/2
+-.nr 38 \n(79+\w!Household Population!-\n(82
+-.if \n(38>0 .nr 38 \n(38/2
+-.if \n(38<0 .nr 38 0
+-.nr 61 +1*\n(38
+-.nr 81 +1*\n(38
+-.nr 41 +1*\n(38
+-.nr 62 +2*\n(38
+-.nr 82 +2*\n(38
+-.nr 42 +2*\n(38
+-.nr 38 \n(80+\w!Households!-\n(82
+-.if \n(38>0 .nr 38 \n(38/1
+-.if \n(38<0 .nr 38 0
+-.nr 62 +1*\n(38
+-.nr 82 +1*\n(38
+-.nr 42 +1*\n(38
+-.nr 38 1n
+-.nr 41 +3*\n(38
+-.nr 81 +3*\n(38
+-.nr 61 +3*\n(38
+-.if n .if \n(61%24>0 .nr 61 +12u
+-.nr 42 +6*\n(38
+-.nr 82 +6*\n(38
+-.nr 62 +6*\n(38
+-.if n .if \n(62%24>0 .nr 62 +12u
+-.nr TW \n(82
+-.fc ! :
+-.ta \n(82u 
+-\&!:Household Population:!
+-.ta \n(80u \n(82u 
+-\&\h'|\n(40u'!:Town:!\h'|\n(41u'!:Households:!
+-.ta \n(80u \n(81u \n(82u 
+-\&\h'|\n(40u'!::!\h'|\n(41u'!:Number:!\h'|\n(42u'!:Size:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Bedminster:!\h'|\n(41u'!:789!\h'|\n(42u'!:3!!.26:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Bernards Twp.:!\h'|\n(41u'!:3087!\h'|\n(42u'!:3!!.74:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Bernardsville:!\h'|\n(41u'!:2018!\h'|\n(42u'!:3!!.30:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Bound Brook:!\h'|\n(41u'!:3425!\h'|\n(42u'!:3!!.04:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Branchburg:!\h'|\n(41u'!:1644!\h'|\n(42u'!:3!!.49:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Bridgewater:!\h'|\n(41u'!:7897!\h'|\n(42u'!:3!!.81:!
+-.ta \n(80u \n(61u \n(62u \n(82u 
+-\&\h'|\n(40u'!Far Hills:!\h'|\n(41u'!:240!\h'|\n(42u'!:3!!.19:!
+-.fc
+-.mk ##
+-.nr ## -1v
+-.if \n(35>0 .fi
+-.TE
+-.fi
+-.PP
+-If no arguments are given,
+-.I tbl
+-reads the standard input,
+-so it may be used as a filter.
+-When it is used with
+-.I eqn
+-or
+-.I neqn
+-the
+-.I tbl
+-command should be first, to minimize the volume
+-of data passed through
+-pipes.
+-.SH SEE ALSO
+-troff(1), eqn(1)
+-.br
+-M. E. Lesk,
+-.I TBL.
+//GO.SYSIN DD tbl.1
+echo tc.1
+sed 's/.//' >tc.1 <<'//GO.SYSIN DD tc.1'
+-.TH TC 1 
+-.SH NAME
+-tc \- photypesetter simulator
+-.SH SYNOPSIS
+-.B tc
+-[
+-.B \-t
+-]
+-[
+-.B \-s\c
+-N
+-]
+-[
+-.B \-p\c
+-L
+-]
+-[
+-file
+-]
+-.SH DESCRIPTION
+-.I Tc
+-interprets its
+-input (standard input default)
+-as device codes for a Graphic Systems phototypesetter (cat).
+-The standard output of
+-.I tc
+-is intended for a Tektronix 4015 (a 4014 teminal
+-with ASCII and APL character sets).
+-The sixteen typesetter sizes are mapped into the 4014's
+-four sizes;
+-the entire TROFF character set is drawn using the 4014's
+-character generator,
+-using overstruck combinations where necessary.
+-Typical usage:
+-.IP "" 15
+-troff \-t file | tc
+-.PP
+-At the end of each page
+-.I tc
+-waits for a newline (empty line) from the keyboard before
+-continuing on to the next page.
+-In this wait state, the command
+-.B e
+-will suppress the screen erase before the next page;
+-.B s\c
+-N will cause the next N pages to be skipped;
+-and
+-.B !\c
+-line will send line to the shell.
+-.PP
+-The command line options are:
+-.TP
+-.B  \-t
+-Don't wait between pages; for directing output into a file.
+-.TP 
+-.BR \-s N
+-Skip the first N pages.
+-.TP 
+-.BR \-p L
+-Set page length to L.
+-L may include the scale factors
+-.B p
+-(points),
+-.B i
+-(inches),
+-.B c
+-(centimeters),
+-and
+-.B P
+-(picas);
+-default is picas.
+-.TP
+-.BI \(fm\- l\ w \(fm
+-Multiply the default aspect ratio, 1.5, of a displayed page
+-by
+-.I l/w.
+-.SH "SEE ALSO"
+-troff(1),
+-plot(1)
+-.SH BUGS
+-Font distinctions are lost.
+-.br
+-The aspect ratio option is unbelievable.
+//GO.SYSIN DD tc.1
+echo tee.1
+sed 's/.//' >tee.1 <<'//GO.SYSIN DD tee.1'
+-.TH TEE 1 
+-.SH NAME
+-tee \- pipe fitting
+-.SH SYNOPSIS
+-.B tee
+-[
+-.B \-i
+-] [
+-.B \-a
+-]
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Tee
+-transcribes the standard input to the standard
+-output and makes copies in the 
+-.I files.
+-Option
+-.B \-i
+-ignores interrupts;
+-option
+-.B \-a
+-causes the output to be appended to the
+-.I files
+-rather than overwriting them.
+//GO.SYSIN DD tee.1
+echo test.1
+sed 's/.//' >test.1 <<'//GO.SYSIN DD test.1'
+-.TH TEST 1 
+-.SH NAME
+-test \-  condition command
+-.SH SYNOPSIS
+-.B test
+-expr
+-.SH DESCRIPTION
+-.I test
+-evaluates the expression
+-.IR expr ,
+-and if its value is true then returns zero exit status; otherwise, a
+-non zero exit status is returned.
+-.I test
+-returns a non zero exit if there are no arguments.
+-.PP
+-The following primitives are used to construct
+-.IR expr .
+-.TP 9n
+-.BR \-r " file"
+-true if the file exists and is readable.
+-.TP 
+-.BR \-w " file"
+-true if the file exists and is writable.
+-.TP 
+-.BR \-f " file"
+-true if the file exists and is not a directory.
+-.TP 
+-.BR \-d " file"
+-true if the file exists and is a directory.
+-.TP 
+-.BR \-s " file"
+-true if the file exists and has a size greater than zero.
+-.TP 
+-.BR \-t " [ fildes ]"
+-true if the open file whose file descriptor number is
+-.I fildes
+-(1 by default)
+-is associated with a terminal device.
+-.TP 
+-.BR \-z " s1"
+-true if the length of string
+-.I s1
+-is zero.
+-.TP 
+-.BR \-n " s1"
+-true if the length of the string
+-.I s1
+-is nonzero.
+-.TP 
+-.RB s1 " = " s2
+-true
+-if the strings
+-.I s1
+-and
+-.I s2
+-are equal.
+-.TP 
+-.RB s1 " != " s2
+-true
+-if the strings
+-.I s1
+-and
+-.I s2
+-are not equal.
+-.TP 
+-s1
+-true if
+-.I s1
+-is not the null string.
+-.TP 
+-.RB n1 " \-eq " n2
+-true if the integers
+-.I n1
+-and
+-.I n2
+-are algebraically equal.
+-Any of the comparisons
+-.BR \-ne ,
+-.BR \-gt ,
+-.BR \-ge ,
+-.BR \-lt ,
+-or
+-.BR \-le
+-may be used in place of
+-.BR \-eq .
+-.PP
+-These primaries may be combined with the
+-following operators:
+-.TP 
+-.B  !
+-unary negation operator
+-.TP 
+-.B  \-a
+-binary
+-.I and
+-operator
+-.TP 
+-.B  \-o
+-binary
+-.I or
+-operator
+-.TP 
+-.BR "( " "expr" " )"
+-parentheses for grouping.
+-.PP
+-.B \-a
+-has higher precedence than
+-.B \-o.
+-Notice that all the operators and flags are separate
+-arguments to
+-.IR test .
+-Notice also that parentheses are meaningful
+-to the Shell and must be escaped.
+-.SH "SEE ALSO"
+-sh(1), find(1)
+//GO.SYSIN DD test.1
+echo time.1
+sed 's/.//' >time.1 <<'//GO.SYSIN DD time.1'
+-.TH TIME 1 
+-.SH NAME
+-time \- time a command
+-.SH SYNOPSIS
+-.B time
+-command
+-.SH DESCRIPTION
+-The
+-given command is executed; after it is complete,
+-.I time
+-prints the elapsed time during the command, the time
+-spent in the system, and the time spent in execution
+-of the command.
+-Times are reported in seconds.
+-.PP
+-The execution time can depend on what kind of memory
+-the program happens to land in;
+-the user time in MOS is often half what it is in core.
+-.PP
+-The times are printed on the diagnostic output stream.
+-.SH BUGS
+-Elapsed time is accurate to the second,
+-while the CPU times are measured
+-to the 60th second.
+-Thus the sum of the CPU times can be up to a second larger
+-than the elapsed time.
+//GO.SYSIN DD time.1
+echo tk.1
+sed 's/.//' >tk.1 <<'//GO.SYSIN DD tk.1'
+-.TH TK 1 
+-.SH NAME
+-tk \- paginator for the Tektronix 4014
+-.SH SYNOPSIS
+-.B tk
+-[
+-.B \-t
+-]
+-[
+-.B \-\c
+-.I  N
+-]
+-[
+-.B \-p\c
+-.I  L
+-]
+-[
+-file
+-]
+-.SH DESCRIPTION
+-The output of
+-.I tk
+-is intended for a Tektronix 4014 terminal.
+-.I Tk
+-arranges for 66 lines to fit on the screen,
+-divides the screen into
+-.I N
+-columns,
+-and
+-contributes an eight space page offset
+-in the (default) single-column case.
+-Tabs, spaces, and backspaces are collected and plotted
+-when necessary.
+-Teletype Model 37 half- and reverse-line sequences
+-are interpreted and plotted.
+-At the end of each page
+-.I tk
+-waits for a newline (empty line) from the keyboard before
+-continuing on to the next page.
+-In this wait state, the command
+-.BI ! command
+-will send the
+-.I command
+-to the shell.
+-.PP
+-The command line options are:
+-.TP
+-.B \-t
+-Don't wait between pages; for directing output into a file.
+-.PP
+-.TP
+-.BI \- N
+-Divide the screen into \fIN\fR columns and
+-wait after the last column.
+-.TP
+-.BI \-p L
+-Set page length to \fIL\fR
+-lines.
+-.SH SEE ALSO
+-pr(1)
+//GO.SYSIN DD tk.1
+echo touch.1
+sed 's/.//' >touch.1 <<'//GO.SYSIN DD touch.1'
+-.TH TOUCH 1 
+-.SH NAME
+-touch \- update date last modified of a file
+-.SH SYNOPSIS
+-.B touch
+-[
+-.B \-c
+-]
+-file ...
+-.SH DESCRIPTION
+-.I Touch
+-attempts to set the modified date of each
+-.I file.
+-This is done by reading a character from the file
+-and writing it back.
+-.PP
+-If a
+-.I file
+-does not exist,
+-an attempt will be made to create it unless the
+-.B \-c
+-option is specified.
+//GO.SYSIN DD touch.1
+echo tp.1
+sed 's/.//' >tp.1 <<'//GO.SYSIN DD tp.1'
+-.TH TP 1  deprecated
+-.SH NAME
+-tp \- manipulate tape archive
+-.SH SYNOPSIS
+-.B tp
+-[ key ] [ name ... ]
+-.SH DESCRIPTION
+-.I Tp
+-saves and restores files
+-on DECtape or magtape.
+-Its actions are controlled by the
+-.I key
+-argument.
+-The key is a string of characters containing
+-at most one function letter and possibly
+-one or more function modifiers.
+-Other arguments to the command are file or directory
+-names specifying which files are to be dumped, restored,
+-or listed.
+-In all cases, appearance of a directory name refers to
+-the files and (recursively) subdirectories of that directory.
+-.PP
+-The function portion of
+-the key is specified by one of the following letters:
+-.TP 8
+-.B  r
+-The named files
+-are written
+-on the tape.
+-If files with the same names
+-already exist, they are replaced.
+-`Same' is determined by string comparison, so
+-`./abc' can never be the same as `/usr/dmr/abc' even
+-if `/usr/dmr' is the current directory.
+-If no file argument is given, `\fB.\fR' is the default.
+-.TP 8
+-.B  u
+-updates the tape.
+-.B u
+-is like
+-.B r,
+-but a file is replaced only if its
+-modification date is later than the date stored on the tape;
+-that is to say, if it has changed since it was dumped.
+-.B u
+-is the default command if none is given.
+-.TP 8
+-.B  d
+-deletes the named files from
+-the tape.
+-At least one name argument must be given.
+-This function is not permitted on magtapes.
+-.TP 8
+-.B  x
+-extracts the named files from the tape to the file system.
+-The owner and mode are restored.
+-If no file argument is given, the entire contents of the
+-tape are extracted.
+-.TP 8
+-.B  t
+-lists the names of the specified files.
+-If no file argument is given,
+-the entire contents of the tape is listed.
+-.PP
+-The following characters may be used in addition to the letter
+-which selects the function desired.
+-.TP 10
+-.B  m
+-Specifies magtape as opposed to DECtape.
+-.TP 10
+-.B  0,...,7
+-This
+-modifier selects the drive on which the tape is mounted.
+-For DECtape, 
+-.B x
+-is default; for magtape
+-`0' is the default.
+-.TP 10
+-.B  v
+-Normally
+-.I tp
+-does its work silently.
+-The
+-.B v
+-(verbose)
+-option causes it to type the name of each file it treats
+-preceded by the function letter.
+-With the
+-.B t
+-function,
+-.B v
+-gives more information about the
+-tape entries than just the name.
+-.TP 10
+-.B  c
+-means a fresh dump is being created; the tape directory
+-is cleared before beginning.
+-Usable only with
+-.B r
+-and
+-.B u.
+-This option is assumed with magtape since
+-it is impossible to selectively overwrite
+-magtape.
+-.TP 10
+-.B  i
+-Errors reading and writing the
+-tape are noted, but no action is taken.
+-Normally, errors cause a return to the command level.
+-.TP 10
+-.B f
+-Use the first named file, rather than a tape,
+-as the archive.
+-This option is known to work only with
+-.BR x .
+-.TP 10
+-.B  w
+-causes
+-.I tp
+-to pause before treating each file, type
+-the indicative letter and the file name (as with
+-.BR v )
+-and await the user's response.
+-Response
+-.B y
+-means `yes', so the file is treated.
+-Null response
+-means `no', and the file does not take part
+-in whatever is being done.
+-Response
+-.B x
+-means `exit';
+-the
+-.I tp
+-command terminates immediately.
+-In the
+-.B x
+-function,
+-files previously asked about
+-have been extracted already.
+-With
+-.B "r, u,"
+-and
+-.B d
+-no change has been made to the tape.
+-.PP
+-.SH FILES
+-/dev/tap?
+-.br
+-/dev/mt?
+-.SH SEE ALSO
+-ar(1), tar(1)
+-.SH DIAGNOSTICS
+-Several; the non-obvious one is
+-`Phase error', which means the file changed after it was selected for
+-dumping but before it was dumped.
+-.SH BUGS
+-A single file with several links to it is treated like several files.
+-.PP
+-Binary-coded control information makes
+-magnetic tapes written by
+-.I tp
+-difficult to carry to other machines;
+-.IR tar (1)
+-avoids the problem.
+//GO.SYSIN DD tp.1
+echo tr.1
+sed 's/.//' >tr.1 <<'//GO.SYSIN DD tr.1'
+-.TH TR 1 
+-.SH NAME
+-tr \- translate characters
+-.SH SYNOPSIS
+-.B tr
+-[
+-.B \-cds
+-] [ string1 [ string2 ] ]
+-.SH DESCRIPTION
+-.I Tr
+-copies the standard input to the standard output with 
+-substitution or deletion of selected characters.
+-Input characters found in 
+-.I string1
+-are mapped into the corresponding characters of
+-.IR string2 .
+-When 
+-.I string2
+-is short it is padded to the length of 
+-.I string1
+-by duplicating its last character.
+-Any combination of the options
+-.B \-cds
+-may be used:
+-.B \-c
+-complements the set of characters in
+-.I string1
+-with respect to the universe of characters
+-whose ASCII codes are 01 through 0377 octal;
+-.B \-d
+-deletes all input characters in
+-.I string1;
+-.B \-s
+-squeezes all strings of repeated output characters that are
+-in 
+-.I string2
+-to single characters.
+-.PP
+-In either string the notation
+-.IB a \- b
+-means a range of characters from
+-.I a
+-to
+-.I b
+-in increasing ASCII order.
+-The character
+-`\e' followed by 1, 2 or 3 octal digits stands for the
+-character whose ASCII code is given by those digits.
+-A `\e' followed by any other character stands
+-for that character.
+-.PP
+-The following example creates a list of all
+-the words in `file1' one per line in `file2',
+-where a word is taken to be a maximal string of alphabetics.
+-The second string is quoted
+-to protect `\e' from the Shell.
+-012 is the ASCII code for newline.
+-.IP
+-tr \-cs A\-Za\-z \'\e012\' <file1 >file2
+-.SH "SEE ALSO"
+-ed(1), ascii(7)
+-.SH BUGS
+-Won't handle ASCII NUL in
+-.I string1
+-or
+-.I string2;
+-always deletes NUL from input.
+//GO.SYSIN DD tr.1
+echo troff.1
+sed 's/.//' >troff.1 <<'//GO.SYSIN DD troff.1'
+-.TH TROFF 1 
+-.SH NAME
+-troff, nroff \- text formatting and typesetting
+-.SH SYNOPSIS
+-.B troff
+-[ option ] ...
+-[ file ] ...
+-.PP
+-.B nroff
+-[ option ] ...
+-[ file ] ...
+-.SH DESCRIPTION
+-.I Troff
+-formats text in the named
+-.I files
+-for
+-printing on a Graphic Systems C/A/T phototypesetter;
+-.I nroff
+-for typewriter-like devices.
+-Their capabilities are described in the
+-.I Nroff/Troff user's manual.
+-.PP
+-If no
+-.I file
+-argument is present, the standard input is read.
+-An argument consisting of a single minus
+-.RB ( \- )
+-is taken to be
+-a file name corresponding to the standard input.
+-The options, which may appear in any order so long as they appear
+-before the files, are:
+-.TP "\w'\f3\-m\f1name 'u"
+-.BI \-o list
+-Print only pages whose page numbers appear in
+-the comma-separated
+-.I list
+-of numbers and ranges.
+-A range
+-.IB N \- M
+-means pages
+-.I N
+-through
+-.IR M ;
+-an initial
+-.I \-N
+-means
+-from the beginning to page
+-.IR N ;
+-and a final
+-.IR N \-
+-means
+-from
+-.I N
+-to the end.
+-.TP
+-.BI \-n N
+-Number first generated page
+-.IR N .
+-.TP
+-.BI \-s N
+-Stop every
+-.I N
+-pages.
+-.I Nroff
+-will halt prior to every
+-.I N
+-pages (default
+-.IR N =1)
+-to allow paper loading or
+-changing, and will resume upon receipt of a newline.
+-.I Troff
+-will stop the phototypesetter every
+-.I N
+-pages,
+-produce a trailer to allow changing cassettes,
+-and resume when the typesetter's start button is pressed.
+-.TP
+-.BI \-m name
+-Prepend the macro file
+-.BI /usr/lib/tmac/tmac. name
+-to the input
+-.IR files .
+-.TP
+-.BI \-r aN
+-Set register
+-.I a
+-(one-character) to
+-.IR N .
+-.TP
+-.B \-i
+-Read standard input after the input files are exhausted.
+-.TP
+-.B \-q
+-Invoke the simultaneous input-output mode of the
+-.B rd
+-request.
+-.HP
+-.bd I 3
+-.I Nroff only
+-.br
+-.bd I
+-.TP
+-.BI \-T name
+-Prepare output for specified terminal.
+-Known
+-.I names
+-are
+-.B 37
+-for the (default) 
+-Teletype Corporation Model 37 terminal,
+-.B tn300
+-for the GE TermiNet\ 300 (or any terminal without half-line
+-capability),
+-.B 300S
+-for the \s-1DASI\s+1-300S,
+-.B 300
+-for the \s-1DASI\s+1-300,
+-and
+-.B 450
+-for the \s-1DASI\s+1-450
+-(Diablo Hyterm).
+-.TP
+-.B \-e
+-Produce equally-spaced words in adjusted
+-lines, using full terminal resolution.
+-.TP
+-.B \-h
+-Use output tabs during horizontal spacing
+-to speed output and reduce output character count.
+-Tab settings are assumed to be every
+-8 nominal character widths.
+-.HP
+-.bd I 3
+-.I Troff only
+-.br
+-.bd I
+-.TP
+-.B \-t
+-Direct output to the standard output instead
+-of the phototypesetter.
+-.TP
+-.B \-f
+-Refrain from feeding out paper and stopping
+-phototypesetter at the end of the run.
+-.TP
+-.B \-w
+-Wait until phototypesetter is available, if
+-currently busy.
+-.TP
+-.B \-b
+-Report whether the phototypesetter
+-is busy or available.
+-No text processing is done.
+-.TP
+-.B \-a
+-Send a printable ASCII approximation
+-of the results to the standard output.
+-.TP
+-.BR \-p N
+-Print all characters in point size
+-.I  N
+-while retaining all prescribed spacings and motions,
+-to reduce phototypesetter elasped time.
+-.TP
+-.B \-g
+-Prepare output for a GCOS
+-phototypesetter and direct it to the standard output
+-(see
+-.IR gcat (1)).
+-.PP
+-If the file
+-.I /usr/adm/tracct
+-is writable,
+-.I troff
+-keeps phototypesetter accounting records there.
+-The integrity of that file may be secured by making
+-.I troff
+-a `set user-id' program.
+-.SH FILES
+-.ta \w'/usr/lib/tmac/tmac.*  'u
+-/usr/lib/suftab       suffix hyphenation tables
+-.br
+-/tmp/ta*      temporary file
+-.br
+-/usr/lib/tmac/tmac.*  standard macro files
+-.br
+-/usr/lib/term/*       terminal driving tables for
+-.I nroff
+-.br
+-/usr/lib/font/*       font width tables for
+-.I troff
+-.br
+-/dev/cat      phototypesetter
+-.br
+-/usr/adm/tracct       accounting statistics for /dev/cat
+-.SH "SEE ALSO"
+-J. F. Ossanna,
+-.I Nroff/Troff user's manual
+-.br
+-B. W. Kernighan,
+-.I
+-A TROFF Tutorial
+-.br
+-eqn(1), tbl(1)
+-.br
+-col(1), tk(1)
+-.RI ( nroff
+-only)
+-.br
+-tc(1), gcat(1)
+-.RI ( troff
+-only)
+//GO.SYSIN DD troff.1
+echo true.1
+sed 's/.//' >true.1 <<'//GO.SYSIN DD true.1'
+-.TH TRUE 1 
+-.SH NAME
+-true, false \- provide truth values
+-.SH SYNOPSIS
+-.B true
+-.PP
+-.B false
+-.SH DESCRIPTION
+-.I True
+-does nothing, successfully.
+-.I False
+-does nothing, unsuccessfully.
+-They are typically used in input to
+-.IR  sh (1)
+-such as:
+-.PP
+-      while true
+-.br
+-      do
+-.br
+-              command
+-.br
+-      done
+-.SH "SEE ALSO"
+-sh(1)
+-.SH DIAGNOSTICS
+-.I True
+-has exit status zero,
+-.I false
+-nonzero.
+//GO.SYSIN DD true.1
+echo tsort.1
+sed 's/.//' >tsort.1 <<'//GO.SYSIN DD tsort.1'
+-.TH TSORT 1 
+-.SH NAME
+-tsort \- topological sort
+-.SH SYNOPSIS
+-.B tsort
+-[ file ]
+-.SH DESCRIPTION
+-.I Tsort
+-produces on the standard output a totally ordered list of items
+-consistent with a partial ordering of items
+-mentioned in the input
+-.IR file .
+-If no
+-.I file
+-is specified, the standard input is understood.
+-.PP
+-The input consists of pairs of items (nonempty strings)
+-separated by blanks.
+-Pairs of different items indicate ordering.
+-Pairs of identical items indicate presence, but not ordering.
+-.SH "SEE ALSO"
+-lorder(1)
+-.SH DIAGNOSTICS
+-Odd data: there is an odd number of fields in the input file.
+-.SH BUGS
+-Uses a quadratic algorithm;
+-not worth fixing for the typical use of ordering
+-a library archive file.
+//GO.SYSIN DD tsort.1
+echo tty.1
+sed 's/.//' >tty.1 <<'//GO.SYSIN DD tty.1'
+-.TH TTY 1 
+-.SH NAME
+-tty \- get terminal name
+-.SH SYNOPSIS
+-.B tty
+-.SH DESCRIPTION
+-.I Tty
+-prints the pathname of the user's terminal.
+-.SH DIAGNOSTICS
+-`not a tty' if the standard input file is not a terminal.
+//GO.SYSIN DD tty.1
+echo uniq.1
+sed 's/.//' >uniq.1 <<'//GO.SYSIN DD uniq.1'
+-.TH UNIQ 1 
+-.SH NAME
+-uniq \- report repeated lines in a file
+-.SH SYNOPSIS
+-.B uniq
+-[
+-.B \-udc
+-[
+-.BR + n
+-] [
+-.BR \- n
+-]
+-] [ input [ output ] ]
+-.SH DESCRIPTION
+-.I Uniq
+-reads the input
+-file comparing adjacent lines.
+-In the normal case, the second and succeeding copies
+-of repeated lines are
+-removed; the remainder is written on the output file.
+-Note that repeated lines must be adjacent
+-in order to be found;
+-see
+-.IR  sort (1).
+-If the
+-.B \-u
+-flag is used,
+-just the lines that are not repeated
+-in the original file are output.
+-The
+-.B \-d
+-option specifies that
+-one copy of just the repeated lines is to
+-be written.
+-The normal mode output is the union of the
+-.B \-u
+-and
+-.B \-d
+-mode outputs.
+-.PP
+-The
+-.B \-c
+-option supersedes
+-.B \-u
+-and
+-.B \-d
+-and generates
+-an output report in default style
+-but with each line preceded by a count of the
+-number of times it occurred.
+-.PP
+-The
+-.I n
+-arguments specify skipping an initial portion of each line
+-in the comparison:
+-.TP 8
+-.BI \- n
+-The first
+-.IR n 
+-fields
+-together with any blanks before each are ignored.
+-A field is defined as a string of non-space, non-tab characters
+-separated by tabs and spaces from its neighbors.
+-.TP 8
+-.BI + n
+-The first
+-.IR n 
+-characters are ignored.
+-Fields are skipped before characters.
+-.PP
+-.SH "SEE ALSO"
+-sort(1), comm(1)
+//GO.SYSIN DD uniq.1
+echo units.1
+sed 's/.//' >units.1 <<'//GO.SYSIN DD units.1'
+-.if n .ds / /
+-.if t .ds / \z/\h'\w'*'u'
+-.TH UNITS 1 
+-.SH NAME
+-units \- conversion program
+-.SH SYNOPSIS
+-.B units
+-.SH DESCRIPTION
+-.I Units
+-converts quantities expressed
+-in various standard scales to
+-their equivalents in other scales.
+-It works interactively in this fashion:
+-.PP
+-.I "  You have:"
+-inch
+-.br
+-.I "  You want:"
+-cm
+-.br
+-.I "          * 2.54000e+00
+-.br
+-.I "          \*/ 3.93701e\-01
+-.PP
+-A quantity is specified as a multiplicative combination of
+-units optionally preceded by a numeric multiplier.
+-Powers are indicated by suffixed positive integers,
+-division by the usual sign:
+-.PP
+-.I "  You have:"
+-15 pounds force/in2
+-.br
+-.I "  You want:"
+-atm
+-.br
+-.I "          * 1.02069e+00"
+-.br
+-.I "          \*/ 9.79730e\-01"
+-.PP
+-.I Units 
+-only does multiplicative scale changes.
+-Thus it can convert Kelvin to Rankine, but not Centigrade to
+-Fahrenheit.
+-Most familiar units,
+-abbreviations, and metric prefixes are recognized,
+-together with a generous leavening of exotica
+-and a few constants of nature including:
+-.PP
+-.nf
+-      pi      ratio of circumference to diameter
+-      c       speed of light
+-      e       charge on an electron
+-      g       acceleration of gravity 
+-      force   same as g
+-      mole    Avogadro's number
+-      water   pressure head per unit height of water
+-      au      astronomical unit
+-.PP
+-.fi
+-`Pound' is a unit of
+-mass.
+-Compound names are run together, e.g. `lightyear'.
+-British units that differ from their US counterparts
+-are prefixed thus: `brgallon'.
+-Currency is denoted `belgiumfranc', `britainpound', ...
+-.PP
+-For a complete list of units, `cat /usr/lib/units'.
+-.SH FILES
+-/usr/lib/units
+-.SH BUGS
+-Don't base your
+-financial plans on the currency conversions.
+//GO.SYSIN DD units.1
+echo uucp.1c
+sed 's/.//' >uucp.1c <<'//GO.SYSIN DD uucp.1c'
+-.TH UUCP 1C 
+-.SH NAME
+-uucp, uulog \- unix to unix copy
+-.SH SYNOPSIS
+-.B uucp
+-[ option ] ...
+-source-file ...  destination-file
+-.PP
+-.B uulog
+-[ option ] ...
+-.SH DESCRIPTION
+-.I Uucp
+-copies files named by the source-file arguments
+-to the destination-file argument.
+-A file name may be a path name on your machine, or may 
+-have the form
+-.IP
+-system-name!pathname
+-.LP
+-where `system-name' is taken from a list of system names
+-which
+-.I uucp
+-knows about.
+-Shell metacharacters ?*[] appearing in the pathname part
+-will be expanded on the appropriate system.
+-.PP
+-Pathnames may be one of
+-.IP (1)
+-a full pathname;
+-.IP (2)
+-a pathname preceded by
+-.IR ~user ;
+-where
+-.I user
+-is a userid on the specified system
+-and is replaced by that user's login directory;
+-.IP (3)
+-anything else is prefixed by the current directory.
+-.PP
+-If the result is an erroneous pathname for the remote system
+-the copy will fail.
+-If the destination-file is a directory, the last part of the
+-source-file name is used.
+-.ig
+-If a simple
+-.I ~user
+-destination is inaccessible to 
+-.I uucp,
+-data is copied to a spool directory and the user
+-is notified by
+-.IR mail (1).
+-..
+-.PP
+-.I Uucp
+-preserves execute permissions across the transmission
+-and gives 0666 read and write permissions (see
+-.IR chmod (2)).
+-.PP
+-The following options are interpreted by
+-.IR uucp .
+-.TP 
+-.B \-d
+-Make all necessary directories for the file copy.
+-.TP 
+-.B \-c
+-Use the source file when copying out rather than
+-copying the file to the spool directory.
+-.TP 
+-.B \-m
+-Send mail to the requester when the copy is complete.
+-.PP
+-.I Uulog
+-maintains a summary log
+-of 
+-.I uucp
+-and
+-.IR uux (1)
+-transactions in the file
+-`/usr/spool/uucp/LOGFILE' by gathering
+-information from partial log files named `/usr/spool/uucp/LOG.*.?'.
+-It removes the partial log files.
+-.PP
+-The options cause 
+-.I uulog 
+-to print logging information:
+-.TP
+-.BI \-s sys
+-Print information about work involving system
+-.I sys.
+-.TP
+-.BI \-u user
+-Print information about work done for the specified
+-.I user.
+-.SH FILES
+-/usr/spool/uucp - spool directory
+-.br
+-/usr/lib/uucp/* - other data and program files
+-.SH SEE ALSO
+-uux(1), mail(1)
+-.br
+-D. A. Nowitz,
+-.I Uucp Implementation Description
+-.SH WARNING
+-The domain of remotely accessible files can
+-(and for obvious security reasons, usually should)
+-be severely restricted.
+-You will very likely not be able to fetch files
+-by pathname;
+-ask a responsible person on the remote system to
+-send them to you.
+-For the same reasons you will probably not be able
+-to send files to arbitrary pathnames.
+-.SH BUGS
+-.br
+-All files received by
+-.I uucp
+-will be owned by uucp.
+-.br
+-The \-m option will only work sending files or receiving
+-a single file.
+-(Receiving multiple files specified by special shell
+-characters ?*[] will not activate
+-the \-m option.)
+//GO.SYSIN DD uucp.1c
+echo uux.1c
+sed 's/.//' >uux.1c <<'//GO.SYSIN DD uux.1c'
+-.TH UUX 1C
+-.SH NAME
+-uux \- unix to unix command execution
+-.SH SYNOPSIS
+-.B uux
+-[
+-.B \-
+-]
+-command-string
+-.SH DESCRIPTION
+-.I Uux
+-will gather 0 or more files from various systems,
+-execute a command on a specified system
+-and send standard output to a file on a specified
+-system.
+-.PP
+-The command-string is made up of one or more arguments that look
+-like a shell command line,
+-except that the command and file names
+-may be prefixed by system-name!.
+-A null system-name is interpreted as the local system.
+-.PP
+-File names may be one of
+-.IP
+-(1) a full pathname;
+-.IP
+-(2) a pathname preceded by
+-.IR ~xxx ;
+-where
+-.I xxx
+-is a userid on the specified system
+-and is replaced by that user's login directory;
+-.br
+-.IP
+-(3) anything else is prefixed by the current directory.
+-.PP
+-The `\-' option will cause the standard input to the
+-.I uux
+-command to be the standard input to the command-string.
+-.PP
+-For example, the command
+-.IP
+-uux "!diff usg!/usr/dan/f1 pwba!/a4/dan/f1 > !fi.diff"
+-.PP
+-will get the f1 files from the usg and pwba machines,
+-execute a
+-.I diff
+-command
+-and put the results in f1.diff in the local directory.
+-.PP
+-Any special shell characters such as <>;| should be quoted either
+-by quoting the entire command-string, or quoting the special
+-characters as individual arguments.
+-.SH FILES
+-/usr/uucp/spool - spool directory
+-.br
+-/usr/uucp/* - other data and programs
+-.SH SEE ALSO
+-uucp(1)
+-.br
+-D. A. Nowitz,
+-.I Uucp implementation description
+-.SH WARNING
+-An installation may, and for security reasons
+-generally will, limit the list of
+-commands executable on behalf of an incoming request from
+-.I uux.
+-Typically, a restricted site will permit little other than
+-the receipt of mail via 
+-.I uux.
+-.SH BUGS
+-Only the first command of a shell pipeline may
+-have a system-name!.
+-All other commands are executed on the system of the first
+-command.
+-.br
+-The use of the shell metacharacter
+-.B *
+-will probably not do what you want it to do.
+-.br
+-The shell tokens << and >> are not implemented.
+-.br
+-There is no notification of denial of execution
+-on the remote machine.
+//GO.SYSIN DD uux.1c
+echo wait.1
+sed 's/.//' >wait.1 <<'//GO.SYSIN DD wait.1'
+-.TH WAIT 1 
+-.SH NAME
+-wait \- await completion of process
+-.SH SYNOPSIS
+-.B wait
+-.SH DESCRIPTION
+-Wait until all processes started with
+-.B &
+-have completed,
+-and report on abnormal terminations.
+-.PP
+-Because the
+-.IR  wait (2)
+-system call
+-must be executed in the parent process,
+-the Shell itself executes
+-.I wait,
+-without creating a new process.
+-.SH "SEE ALSO"
+-sh(1)
+-.SH BUGS
+-Not all the processes of a 3- or more-stage
+-pipeline are children of the Shell, and
+-thus can't be waited for.
+//GO.SYSIN DD wait.1
+echo wall.1m
+sed 's/.//' >wall.1m <<'//GO.SYSIN DD wall.1m'
+-.TH WALL 1M 
+-.SH NAME
+-wall  \-  write to all users
+-.SH SYNOPSIS
+-.B /etc/wall
+-.SH DESCRIPTION
+-.I Wall
+-reads its standard input until an end-of-file.
+-It then sends this message,
+-preceded by
+-`Broadcast Message ...',
+-to all logged in users.
+-.PP
+-The sender should be super-user to override
+-any protections the users may have invoked.
+-.SH FILES
+-/dev/tty?
+-.br
+-/etc/utmp
+-.SH "SEE ALSO"
+-mesg(1), write(1)
+-.SH DIAGNOSTICS
+-`Cannot send to ...' when the open on
+-a user's tty file fails.
+//GO.SYSIN DD wall.1m
+echo wc.1
+sed 's/.//' >wc.1 <<'//GO.SYSIN DD wc.1'
+-.TH WC 1 
+-.SH NAME
+-wc \- word count
+-.SH SYNOPSIS
+-.B wc
+-[
+-.B \-lwc
+-]
+-[ name ... ]
+-.SH DESCRIPTION
+-.I Wc
+-counts lines, words and characters in the named files,
+-or in the standard input if no name appears.
+-A word is a maximal string of characters
+-delimited by spaces, tabs or newlines.
+-.PP
+-If the optional argument is present,
+-just the specified counts (lines, words or characters)
+-are selected by the letters
+-.BR l ,
+-.BR w ,
+-or
+-.BR c .
+//GO.SYSIN DD wc.1
+echo who.1
+sed 's/.//' >who.1 <<'//GO.SYSIN DD who.1'
+-.TH WHO 1 
+-.SH NAME
+-who  \-  who is on the system
+-.SH SYNOPSIS
+-.B who
+-[ who-file ] [
+-.B "am I"
+-]
+-.SH DESCRIPTION
+-.I Who,
+-without an argument,
+-lists the login name, terminal name, and login time
+-for each current UNIX user.
+-.PP
+-Without an argument,
+-.I who
+-examines the /etc/utmp
+-file to obtain its information.
+-If a file is given, that file is examined.
+-Typically the given file will be /usr/adm/wtmp,
+-which contains a record of all the logins since it
+-was created.
+-Then
+-.I who
+-lists
+-logins, logouts, and crashes since the creation of
+-the wtmp file.
+-Each login is listed with user name,
+-terminal name (with `/dev/'
+-suppressed),
+-and date and time.
+-When an argument is given, logouts produce a similar line without a user name.
+-Reboots produce a line with `x' in the place of the device name,
+-and a fossil time indicative of when the system went down.
+-.PP
+-With two arguments,
+-as in `who am I' (and also `who are you'),
+-.I who
+-tells who you are logged in as.
+-.SH FILES
+-/etc/utmp
+-.SH "SEE ALSO"
+-getuid(2), utmp(5)
+//GO.SYSIN DD who.1
+echo write.1
+sed 's/.//' >write.1 <<'//GO.SYSIN DD write.1'
+-.TH WRITE 1 
+-.SH NAME
+-write  \-  write to another user
+-.SH SYNOPSIS
+-.B write
+-user [ ttyname ]
+-.SH DESCRIPTION
+-.I Write
+-copies lines from your terminal to that of
+-another user.
+-When first called,
+-it sends the message
+-.PP
+-     Message from yourname yourttyname...
+-.PP
+-The recipient of the message should write back at this point.
+-Communication continues until an end of file is
+-read from the terminal or an interrupt is sent.
+-At that point
+-.I write
+-writes `EOT' on the other terminal and exits.
+-.PP
+-If you want to write to a user who is logged in more than once,
+-the
+-.I ttyname
+-argument may be used to indicate the
+-appropriate terminal name.
+-.PP
+-Permission to write may be denied or granted by use of the
+-.I mesg
+-command.
+-At the outset writing is allowed.
+-Certain commands, in particular
+-.I nroff
+-and
+-.IR  pr (1)
+-disallow
+-messages in order to prevent messy output.
+-.PP
+-If the character `!' is found at the beginning of a line,
+-.I write
+-calls the shell
+-to execute the rest of the
+-line as a command.
+-.PP
+-The following protocol is suggested for using
+-.IR write :
+-when you first write to another user, wait for him to
+-write back before starting to send.
+-Each party should end each message with a distinctive
+-signal\(em\fB(o)\fR
+-for `over' is conventional\(emthat the other may reply.
+-.B (oo)
+-for `over and out' is suggested when conversation
+-is about to be terminated.
+-.SH FILES
+-/etc/utmp     to find user
+-.br
+-/bin/sh               to execute `!'
+-.SH "SEE ALSO"
+-mesg(1), who(1), mail(1)
+//GO.SYSIN DD write.1
+echo xsend.1
+sed 's/.//' >xsend.1 <<'//GO.SYSIN DD xsend.1'
+-.TH "XSEND, XGET, ENROLL" 1
+-.SH NAME
+-xsend, xget, enroll \- secret mail
+-.SH SYNOPSIS
+-.B xsend
+-person
+-.br
+-.B xget
+-.br
+-.B enroll
+-.SH DESCRIPTION
+-These commands implement a secure communication
+-channel;
+-it is like
+-.IR mail (1),
+-but no one can read the messages except the intended recipient.
+-The method embodies a public-key cryptosystem using knapsacks.
+-.PP
+-To receive messages, use
+-.IR enroll ;
+-it asks you for a password that you must subsequently quote
+-in order to receive secret mail.
+-.PP
+-To receive secret mail,
+-use
+-.IR xget .
+-It asks for your password, then gives you the messages.
+-.PP
+-To send secret mail, use
+-.IR xsend
+-in the same manner as the ordinary mail command.
+-(However, it will accept only one target).
+-A message announcing the receipt of secret mail is also sent
+-by ordinary mail.
+-.SH FILES
+-/usr/spool/secretmail/*.key: keys
+-/usr/spool/secretmail/*.[0-9]: messages
+-.SH SEE ALSO
+-mail (1)
+-.SH BUGS
+-It should be integrated with ordinary mail.
+-The announcement of secret mail makes traffic analysis possible.
+//GO.SYSIN DD xsend.1
+echo yacc.1
+sed 's/.//' >yacc.1 <<'//GO.SYSIN DD yacc.1'
+-.TH YACC 1 
+-.SH NAME
+-yacc \- yet another compiler-compiler
+-.SH SYNOPSIS
+-.B yacc
+-[
+-.B \-vd
+-]
+-grammar
+-.SH DESCRIPTION
+-.I Yacc
+-converts a context-free grammar into a set of
+-tables for a simple automaton which executes an LR(1) parsing
+-algorithm.
+-The grammar may be ambiguous;
+-specified precedence rules are used to break ambiguities.
+-.PP
+-The output file,
+-.IR y.tab.c ,
+-must be compiled by the C compiler
+-to produce a program
+-.IR yyparse .
+-This program must be loaded with the lexical analyzer program,
+-.IR yylex ,
+-as well as
+-.I main
+-and
+-.IR yyerror ,
+-an error handling routine.
+-These routines must be supplied by the user;
+-.IR Lex (1)
+-is useful for creating lexical analyzers usable by
+-.IR yacc .
+-.PP
+-If the
+-.B \-v
+-flag is given, the file
+-.I y.output
+-is prepared, which contains a description of the parsing tables
+-and a report on
+-conflicts generated by ambiguities in the grammar.
+-.PP
+-If the \-\fBd\fR flag is used, the file
+-.I y.tab.h
+-is generated with the
+-.I define
+-statements that associate the
+-.I yacc\c
+--assigned `token codes' with the user-declared `token names'.
+-This allows source files other than
+-.I y.tab.c
+-to access the token codes.
+-.SH FILES
+-.ta \w'yacc.tmp, yacc.acts 'u
+-y.output
+-.br
+-y.tab.c
+-.br
+-y.tab.h       defines for token names
+-.br
+-yacc.tmp, yacc.acts   temporary files
+-.br
+-/usr/lib/yaccpar      parser prototype for C programs
+-.br
+-/lib/liby.a   library with default `main' and `yyerror'
+-.SH "SEE ALSO"
+-.IR lex (1)
+-.br
+-.I "LR Parsing"
+-by A. V. Aho and S. C. Johnson,
+-Computing Surveys, June, 1974.
+-.br
+-.I "YACC \- Yet Another Compiler Compiler"
+-by S. C. Johnson.
+-.SH DIAGNOSTICS
+-The number of reduce-reduce and shift-reduce conflicts
+-is reported on the standard output;
+-a more detailed report is
+-found in the
+-.I y.output
+-file.
+-Similarly, if some rules are not reachable from the
+-start symbol, this is also reported.
+-.SH BUGS
+-Because file names are fixed, at most one
+-.I yacc
+-process can be active in a given directory at
+-a time.
+//GO.SYSIN DD yacc.1
diff --git a/doc/7thEdMan/vol1/man2.bun b/doc/7thEdMan/vol1/man2.bun
new file mode 100644 (file)
index 0000000..269c847
--- /dev/null
@@ -0,0 +1,3459 @@
+# To unbundle, run this file
+echo access.2
+sed 's/.//' >access.2 <<'//GO.SYSIN DD access.2'
+-.TH ACCESS 2 
+-.SH NAME
+-access \- determine accessibility of file
+-.SH SYNOPSIS
+-.B access(name, mode)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Access
+-checks the given
+-file
+-.I name
+-for accessibility according to
+-.I mode,
+-which is 4 (read), 2 (write) or 1 (execute) or a combination thereof.
+-Specifying mode 0
+-tests whether the directories leading to the file can be
+-searched and the file exists.
+-.PP
+-An appropriate error indication is returned if 
+-.I name
+-cannot be found or if any
+-of the desired access modes would not be granted.
+-On disallowed accesses
+-\-1 is returned and the error code is in
+-.IR errno .
+-0 is returned from successful tests.
+-.PP
+-The user and group IDs with respect to which permission is checked
+-are the real UID and GID of the process, so this call is
+-useful to set-UID programs.
+-.PP
+-Notice that it is only access bits that are checked.
+-A directory may be announced as writable by
+-.I access,
+-but an attempt to open it for writing will fail
+-(although files may be created there);
+-a file may look executable, but
+-.I exec
+-will fail unless it is in proper format.
+-.PP
+-.SH SEE ALSO
+-stat(2)
+-.SH ASSEMBLER
+-(access = 33.)
+-.br
+-.B sys access; name; mode
+//GO.SYSIN DD access.2
+echo acct.2
+sed 's/.//' >acct.2 <<'//GO.SYSIN DD acct.2'
+-.TH ACCT 2 
+-.SH NAME
+-acct \- turn accounting on or off
+-.SH SYNOPSIS
+-.B acct(file)
+-.br
+-.B char *file;
+-.SH DESCRIPTION
+-The system is prepared to write a record
+-in an accounting
+-.I file
+-for each process as it terminates.
+-This
+-call, with a null-terminated string naming an existing file
+-as argument, turns on accounting;
+-records for each terminating process are appended to
+-.IR file .
+-An argument of 0 causes accounting to be turned off.
+-.PP
+-The accounting file format is given in
+-.IR acct (5).
+-.SH "SEE ALSO"
+-acct(5), sa(1)
+-.SH DIAGNOSTICS
+-On error \-1 is returned.
+-The file must exist and the call may be exercised only by the super-user.
+-It is erroneous to try to turn on accounting when it is already on.
+-.SH BUGS
+-No accounting is produced for programs running
+-when a crash occurs.
+-In particular nonterminating programs are never
+-accounted for.
+-.SH ASSEMBLER
+-(acct = 51.)
+-.br
+-.B sys acct; file
+//GO.SYSIN DD acct.2
+echo alarm.2
+sed 's/.//' >alarm.2 <<'//GO.SYSIN DD alarm.2'
+-.TH ALARM 2 
+-.SH NAME
+-alarm \- schedule signal after specified time
+-.SH SYNOPSIS
+-.B alarm(seconds)
+-.br
+-.B unsigned seconds;
+-.SH DESCRIPTION
+-.I Alarm
+-causes signal SIGALRM, see
+-.IR signal (2),
+-to be sent to the invoking process
+-in a number of seconds given by the argument.
+-Unless caught or ignored, the signal terminates the process.
+-.PP
+-Alarm requests are not stacked;
+-successive calls reset the alarm clock.
+-If the argument is 0, any alarm request is cancelled.
+-Because the clock has a 1-second resolution,
+-the signal may occur up to one second early;
+-because of scheduling delays,
+-resumption of execution of when the signal is
+-caught may be delayed an arbitrary amount.
+-The longest specifiable delay time is 65535 seconds.
+-.PP
+-The return value is the amount of time
+-previously remaining in the alarm clock.
+-.SH "SEE ALSO"
+-pause(2), signal(2), sleep(3)
+-.SH ASSEMBLER
+-(alarm = 27.)
+-.br
+-(seconds in r0)
+-.br
+-.B sys alarm
+-.br
+-(previous amount in r0)
+//GO.SYSIN DD alarm.2
+echo brk.2
+sed 's/.//' >brk.2 <<'//GO.SYSIN DD brk.2'
+-.TH BRK 2 
+-.SH NAME
+-brk, sbrk, break \- change core allocation
+-.SH SYNOPSIS
+-.B char *brk(addr)
+-.PP
+-.B char *sbrk(incr)
+-.SH DESCRIPTION
+-.I Brk
+-sets the system's idea of the lowest location not used by the program
+-(called the break)
+-to
+-.I addr
+-(rounded up to the next multiple of 64 bytes
+-on the PDP11, 256 bytes on the Interdata 8/32, 512 bytes on the VAX-11/780).
+-Locations not less than
+-.I addr
+-and below the stack pointer
+-are not in the address space and will thus
+-cause a memory violation if accessed.
+-.PP
+-In the alternate function
+-.I sbrk,
+-.I incr
+-more bytes are added to the
+-program's data space and a pointer to the
+-start of the new area is returned.
+-.PP
+-When a program begins execution via
+-.I exec
+-the break is set at the
+-highest location defined by the program
+-and data storage areas.
+-Ordinarily, therefore, only programs with growing
+-data areas need to use
+-.IR break .
+-.SH "SEE ALSO"
+-exec(2),
+-malloc(3),
+-end(3)
+-.SH DIAGNOSTICS
+-Zero is returned if the break could be set;
+-\-1 if the program requests more
+-memory than the system limit
+-or if too many segmentation
+-registers would be required to implement the break.
+-.SH BUGS
+-Setting the break in the range
+-0177701 to 0177777 (on the PDP11) is the same as setting it to zero.
+-.SH ASSEMBLER
+-(break = 17.)
+-.br
+-.B sys break; addr
+-.PP
+-.I Break
+-performs the function of
+-.IR brk .
+-The name of the routine differs from that in C
+-for historical reasons.
+//GO.SYSIN DD brk.2
+echo chdir.2
+sed 's/.//' >chdir.2 <<'//GO.SYSIN DD chdir.2'
+-.TH "CHDIR" 2 
+-.SH NAME
+-chdir, chroot \- change default directory
+-.SH SYNOPSIS
+-.B chdir(dirname)
+-.br
+-.B char *dirname;
+-.PP
+-.B chroot(dirname)
+-.br
+-.B char *dirname;
+-.SH DESCRIPTION
+-.I Dirname
+-is the address of the pathname of a directory, terminated by a null byte.
+-.I Chdir
+-causes this directory
+-to become the current working directory,
+-the starting point for path names not beginning with `/'.
+-.PP
+-.I Chroot
+-sets the root directory, the
+-starting point for path names beginning with `/'.
+-The call is restricted to the super-user.
+-.SH "SEE ALSO"
+-cd(1)
+-.SH DIAGNOSTICS
+-Zero is returned if the directory is changed; \-1
+-is returned
+-if the given name is not that of a directory
+-or is not searchable.
+-.SH ASSEMBLER
+-(chdir = 12.)
+-.br
+-.B sys chdir; dirname
+-.PP
+-(chroot = 61.)
+-.br
+-.B sys chroot; dirname
+//GO.SYSIN DD chdir.2
+echo chmod.2
+sed 's/.//' >chmod.2 <<'//GO.SYSIN DD chmod.2'
+-.TH CHMOD 2 
+-.SH NAME
+-chmod \- change mode of file
+-.SH SYNOPSIS
+-.B chmod(name, mode)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-The file whose name
+-is given as the null-terminated string pointed to by
+-.I name
+-has its mode changed to
+-.IR mode .
+-Modes are constructed by ORing together some
+-combination of the following:
+-.PP
+-.RS
+- 04000 set user ID on execution
+- 02000 set group ID on execution
+- 01000 save text image after execution
+- 00400 read by owner
+- 00200 write by owner
+- 00100 execute (search on directory) by owner
+- 00070 read, write, execute (search) by group
+- 00007 read, write, execute (search) by others
+-.RE
+-.PP
+-If an executable file is set up for sharing
+-(\fB\-n\fR or \fB\-i\fR option of
+-.IR ld (1))
+-then mode 1000 prevents the system from
+-abandoning the swap-space image of the program-text portion
+-of the file when its last user
+-terminates.
+-Thus when the next user of the file executes it,
+-the text need not be read from the file
+-system but can simply be swapped in,
+-saving time.
+-Ability to set this bit is restricted to the super-user
+-since swap space is consumed
+-by the images; it is only worth while for heavily used commands.
+-.PP
+-Only the owner of a file (or the super-user) may change the mode.
+-Only the super-user can set the 1000 mode.
+-.SH "SEE ALSO"
+-chmod(1)
+-.SH DIAGNOSTIC
+-Zero is returned if the mode is changed;
+-\-1 is returned if
+-.I name
+-cannot be found or if current user
+-is neither the owner of the file nor the super-user.
+-.SH ASSEMBLER
+-(chmod = 15.)
+-.br
+-.B sys chmod; name; mode
+//GO.SYSIN DD chmod.2
+echo chown.2
+sed 's/.//' >chown.2 <<'//GO.SYSIN DD chown.2'
+-.TH CHOWN 2 
+-.SH NAME
+-chown \- change owner and group of a file
+-.SH SYNOPSIS
+-.B chown(name, owner, group)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-The file
+-whose name is given by the null-terminated string pointed
+-to by
+-.I name
+-has its
+-.I owner
+-and 
+-.I group
+-changed as specified.
+-Only the super-user may
+-execute this call,
+-because if users were able to give files away,
+-they could defeat the (nonexistent)
+-file-space accounting procedures.
+-.SH "SEE ALSO"
+-chown(1), passwd(5)
+-.SH DIAGNOSTICS
+-Zero is returned if the owner is changed;
+-\-1 is returned
+-on illegal owner changes.
+-.SH ASSEMBLER
+-(chown = 16.)
+-.br
+-.B sys chown; name; owner; group
+//GO.SYSIN DD chown.2
+echo close.2
+sed 's/.//' >close.2 <<'//GO.SYSIN DD close.2'
+-.TH CLOSE 2 
+-.SH NAME
+-close  \-  close a file
+-.SH SYNOPSIS
+-.B close(fildes)
+-.PP
+-.SH DESCRIPTION
+-Given
+-a file descriptor such as returned from an
+-.I open,
+-.I creat,
+-.I dup
+-or
+-.IR pipe (2)
+-call,
+-.I close
+-closes the associated file.
+-A close of all files is automatic on
+-.I exit,
+-but since
+-there is a limit on the number of open files per process,
+-.I close
+-is necessary for programs which deal with many files.
+-.PP
+-Files are closed upon termination of a process, and
+-certain file descriptors may be closed by
+-.IR exec (2)
+-(see
+-.IR ioctl (2)).
+-.SH "SEE ALSO"
+-creat(2), open(2), pipe(2), exec(2), ioctl(2)
+-.SH DIAGNOSTICS
+-Zero is returned if a file is closed;
+-\-1 is returned for an unknown file descriptor.
+-.SH ASSEMBLER
+-(close = 6.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys close
+-.PP
+//GO.SYSIN DD close.2
+echo creat.2
+sed 's/.//' >creat.2 <<'//GO.SYSIN DD creat.2'
+-.TH CREAT 2 
+-.SH NAME
+-creat  \-  create a new file
+-.SH SYNOPSIS
+-.B creat(name, mode)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Creat
+-creates a new file or prepares to rewrite an existing
+-file called 
+-.I name,
+-given as the address of a null-terminated string.
+-If the file did not exist, it is given
+-mode
+-.IR mode ,
+-as modified by the process's mode mask (see
+-.IR umask (2)).
+-Also see
+-.IR  chmod (2)
+-for the
+-construction of the
+-.I mode
+-argument.
+-.PP
+-If the file did exist, its mode and owner remain unchanged
+-but it is truncated to 0 length.
+-.PP
+-The file is also opened for writing, and its file descriptor
+-is returned.
+-.PP
+-The
+-.I mode
+-given is arbitrary; it need not allow
+-writing.
+-This feature is used by programs which deal with temporary
+-files of fixed names.
+-The creation is done with
+-a mode that forbids writing.
+-Then if a second
+-instance of the program attempts a
+-.I creat,
+-an error is
+-returned and the program knows that the name is unusable
+-for the moment.
+-.SH "SEE ALSO"
+-write(2), close(2), chmod(2), umask (2)
+-.SH DIAGNOSTICS
+-The value \-1 is returned if:
+-a needed directory is not searchable;
+-the file does not exist and the directory
+-in which it is to be created is not writable; the file
+-does exist and is unwritable;
+-the file is a directory;
+-there are already too many files open.
+-.SH ASSEMBLER
+-(creat = 8.)
+-.br
+-.B sys creat; name; mode
+-.br
+-(file descriptor in r0)
+//GO.SYSIN DD creat.2
+echo dup.2
+sed 's/.//' >dup.2 <<'//GO.SYSIN DD dup.2'
+-.TH DUP 2 
+-.SH NAME
+-dup, dup2 \- duplicate an open file descriptor
+-.SH SYNOPSIS
+-.B dup(fildes)
+-.br
+-.B int fildes;
+-.PP
+-.B dup2(fildes, fildes2)
+-.br
+-.B int fildes, fildes2;
+-.SH DESCRIPTION
+-Given
+-a file descriptor returned from
+-an
+-.I open,
+-.I pipe,
+-or
+-.I creat
+-call,
+-.I dup
+-allocates another file descriptor
+-synonymous
+-with
+-the original.
+-The new file descriptor is returned.
+-.PP
+-In the second form of the call,
+-.I fildes
+-is a file descriptor referring to an open file, and
+-.I fildes2
+-is a non-negative integer less than the maximum value
+-allowed for file descriptors (approximately 19).
+-.I Dup2
+-causes
+-.I fildes2
+-to refer to the same file as
+-.I fildes.
+-If
+-.I fildes2
+-already referred to an open file, it is closed first.
+-.SH "SEE ALSO"
+-creat(2), open(2), close(2), pipe(2)
+-.SH DIAGNOSTICS
+-The value \-1 is returned if:
+-the given file descriptor is invalid;
+-there are already too many open files.
+-.SH ASSEMBLER
+-(dup = 41.)
+-.br
+-(file descriptor in r0)
+-.br
+-(new file descriptor in r1)
+-.br
+-.B sys dup
+-.br
+-(file descriptor in r0)
+-.PP
+-The
+-.I dup2
+-entry is implemented by adding 0100 to
+-.I fildes.
+//GO.SYSIN DD dup.2
+echo exec.2
+sed 's/.//' >exec.2 <<'//GO.SYSIN DD exec.2'
+-.TH EXEC 2 
+-.SH NAME
+-execl, execv, execle, execve, execlp, execvp, exec, exece, environ  \- execute a file
+-.SH SYNOPSIS
+-.B execl(name, arg0, arg1, ..., argn, 0)
+-.br
+-.B char *name, *arg0, *arg1, ..., *argn;
+-.PP
+-.B execv(name, argv)
+-.br
+-.B char *name, *argv[ ];
+-.PP
+-.B "execle(name, arg0, arg1, ..., argn, 0, envp)
+-.br
+-.B "char *name, *arg0, *arg1, ..., *argn, *envp[ ];
+-.PP
+-.B execve(name, argv, envp);
+-.br
+-.B char *name, *argv[ ], *envp[ ];
+-.PP
+-.B extern char **environ;
+-.SH DESCRIPTION
+-.I Exec
+-in all its forms
+-overlays the calling process with the named file, then
+-transfers to the
+-entry point of the core image of the file.
+-There can be no return from a successful exec; the calling
+-core image is lost.
+-.PP
+-Files remain open across
+-.I exec
+-unless explicit arrangement has been made;
+-see
+-.IR ioctl (2).
+-Ignored signals remain ignored across
+-these calls, but
+-signals that are caught (see
+-.IR signal (2))
+-are reset
+-to their default values.
+-.PP
+-Each user has a
+-.I real
+-user ID and group ID and an
+-.I effective
+-user ID and group ID.
+-The
+-real
+-ID
+-identifies the person using the system;
+-the
+-effective
+-ID
+-determines his access privileges.
+-.I Exec
+-changes the effective user and group ID to
+-the owner of the executed file if the file has the `set-user-ID'
+-or `set-group-ID'
+-modes.
+-The
+-real
+-user ID is not affected.
+-.PP
+-The
+-.I name
+-argument
+-is a pointer to the name of the file
+-to be executed.
+-The pointers
+-.IR arg [ 0 ],
+-.IR arg [ 1 "] ..."
+-address null-terminated strings.
+-Conventionally
+-.IR arg [ 0 ]
+-is the name of the
+-file.
+-.PP
+-From C, two interfaces are available.
+-.I Execl
+-is useful when a known file with known arguments is
+-being called;
+-the arguments to
+-.I execl
+-are the character strings
+-constituting the file and the arguments;
+-the first argument is conventionally
+-the same as the file name (or its last component).
+-A 0 argument must end the argument list.
+-.PP
+-The
+-.I execv
+-version is useful when the number of arguments is unknown
+-in advance;
+-the arguments to
+-.I execv
+-are the name of the file to be
+-executed and a vector of strings containing
+-the arguments.
+-The last argument string must be followed
+-by a 0 pointer.
+-.PP
+-When a C program is executed,
+-it is called as follows:
+-.PP
+-      main(argc, argv, envp)
+-.br
+-      int argc;
+-.br
+-      char **argv, **envp;
+-.PP
+-where
+-.IR argc ""
+-is the argument count
+-and
+-.IR argv ""
+-is an array of character pointers
+-to the arguments themselves.
+-As indicated,
+-.IR argc ""
+-is conventionally at least one
+-and the first member of the array points to a
+-string containing the name of the file.
+-.PP
+-.I Argv
+-is directly usable in another
+-.I execv
+-because
+-.IR argv [ argc ]
+-is 0.
+-.PP
+-.I Envp
+-is a pointer to an array of strings that constitute
+-the
+-.I environment
+-of the process.
+-Each string consists of a name, an ``='', and a null-terminated value.
+-The array of pointers is terminated by a null pointer.
+-The shell
+-.IR sh (1)
+-passes an environment entry for each global shell variable
+-defined when the program is called.
+-See
+-.IR environ (5)
+-for some conventionally
+-used names.
+-The C run-time start-off routine places a copy of
+-.I envp
+-in the global cell
+-.I environ,
+-which is used
+-by
+-.IR execv \ and \ execl
+-to pass the environment to any subprograms executed by the
+-current program.
+-The
+-.I exec
+-routines use lower-level routines as follows
+-to pass an environment explicitly:
+-.RS
+-.nf
+-execle(file, arg0, arg1, . . . , argn, 0, environ);
+-execve(file, argv, environ);
+-.fi
+-.RE
+-.PP
+-.I Execlp
+-and
+-.I execvp
+-are called with the same arguments as
+-.I execl
+-and
+-.I execv,
+-but duplicate the shell's actions in searching for an executable
+-file in a list of directories.
+-The directory list is obtained from the environment.
+-.SH FILES
+-.ta \w'/bin/sh  'u
+-/bin/sh       shell, invoked if command file found
+-by
+-.I execlp
+-or
+-.I execvp
+-.SH "SEE ALSO"
+-fork(2), environ(5)
+-.SH DIAGNOSTICS
+-If the file cannot be found,
+-if it is not executable,
+-if it does not start with a valid magic number (see
+-.IR a.out (5)),
+-if maximum memory is exceeded,
+-or if the arguments require too much space,
+-a return
+-constitutes the diagnostic;
+-the return value is \-1.
+-Even for the super-user,
+-at least one of the execute-permission bits must be set for
+-a file to be executed.
+-.SH BUGS
+-If
+-.I execvp
+-is called to execute a file that turns out to be a shell
+-command file,
+-and if it is impossible to execute the shell,
+-the values of
+-.I argv[0]
+-and
+-.I argv[\-1]
+-will be modified before return.
+-.SH ASSEMBLER
+-.DT
+-(exec = 11.)
+-.br
+-.B sys exec; name; argv
+-.PP
+-(exece = 59.)
+-.br
+-.B sys exece; name; argv; envp
+-.PP
+-Plain
+-.I exec
+-is obsoleted by
+-.I exece,
+-but remains for historical reasons.
+-.PP
+-When the called file starts execution on the PDP11,
+-the stack pointer points to a word containing the number of arguments.
+-Just above
+-this number is a list of pointers to the argument strings,
+-followed by a null pointer, followed by the pointers to
+-the environment strings and then another null pointer.
+-The strings themselves follow;
+-a 0 word is left at the very top of memory.
+-.PP
+-  sp\(->      nargs
+-.br
+-      arg0
+-.br
+-      ...
+-.br
+-      argn
+-.br
+-      0
+-.br
+-      env0
+-.br
+-      ...
+-.br
+-      envm
+-.br
+-      0
+-.PP
+- arg0:        <arg0\e0>
+-.br
+-      ...
+-.br
+- env0:        <env0\e0>
+-.br
+-      0
+-.PP
+-On the Interdata 8/32,
+-the stack begins at a conventional place
+-(currently 0xD0000)
+-and grows upwards.
+-After
+-.I exec,
+-the layout of data on the stack is as follows.
+-.PP
+-.nf
+-      int     0
+- arg0:        byte    ...
+-      ...
+-argp0:        int     arg0
+-      ...
+-      int     0
+-envp0:        int     env0
+-      ...
+-      int     0
+- %2\(->       space   40
+-      int     nargs
+-      int     argp0
+-      int     envp0
+- %3\(->
+-.fi
+-.PP
+-This arrangement happens to conform well to C calling conventions.
+//GO.SYSIN DD exec.2
+echo exit.2
+sed 's/.//' >exit.2 <<'//GO.SYSIN DD exit.2'
+-.TH EXIT 2 
+-.SH NAME
+-exit \- terminate process
+-.SH SYNOPSIS
+-.B exit(status)
+-.br
+-.B int status;
+-.PP
+-.B _exit(status)
+-.br
+-.B int status;
+-.SH DESCRIPTION
+-.I Exit
+-is the normal means of terminating a process.
+-.I Exit
+-closes all the process's files and notifies the parent process
+-if it is executing a
+-.IR wait .
+-The low-order 8 bits of 
+-.I status
+-are available to the parent process.
+-.PP
+-This call can never return.
+-.PP
+-The C function
+-.I exit
+-may cause cleanup actions before the
+-final `sys exit'.
+-The function
+-.I _exit
+-circumvents all cleanup.
+-.SH "SEE ALSO"
+-wait(2)
+-.SH ASSEMBLER
+-(exit = 1.)
+-.br
+-(status in r0)
+-.br
+-.B sys exit
+//GO.SYSIN DD exit.2
+echo fork.2
+sed 's/.//' >fork.2 <<'//GO.SYSIN DD fork.2'
+-.TH FORK 2 
+-.SH NAME
+-fork  \-  spawn new process
+-.SH SYNOPSIS
+-.B fork( )
+-.SH DESCRIPTION
+-.I Fork
+-is the only way new processes are created.
+-The new process's core image is a copy of
+-that of the caller of
+-.IR fork .
+-The only distinction
+-is the fact
+-that the value returned in the old (parent) process
+-contains the process ID
+-of the new (child) process,
+-while the value returned in the child is 0.
+-Process ID's range from 1 to 30,000.
+-This process ID is used by
+-.IR wait (2).
+-.PP
+-Files open before the fork
+-are shared, and have a common read-write pointer.
+-In particular,
+-this is the way that standard input and output
+-files are passed and also how
+-pipes are set up.
+-.SH "SEE ALSO"
+-wait(2), exec(2)
+-.SH DIAGNOSTICS
+-Returns \-1 and fails to create a process if:
+-there is inadequate swap space,
+-the user is not super-user and has too many processes,
+-or the system's process table is full.
+-Only the super-user can take the last process-table slot.
+-.SH ASSEMBLER
+-(fork = 2.)
+-.br
+-.B sys fork
+-.br
+-(new process return)
+-.br
+-(old process return, new process ID in r0)
+-.PP
+-The return locations in the old and new process
+-differ by one word.
+-The C-bit is set in the old process if a new
+-process could not be created.
+//GO.SYSIN DD fork.2
+echo getpid.2
+sed 's/.//' >getpid.2 <<'//GO.SYSIN DD getpid.2'
+-.TH GETPID 2 
+-.SH NAME
+-getpid  \-  get process identification
+-.SH SYNOPSIS
+-.B getpid( )
+-.SH DESCRIPTION
+-.I Getpid
+-returns
+-the process ID of
+-the current process.
+-Most often it is used to generate
+-uniquely-named
+-temporary files.
+-.SH "SEE ALSO"
+-mktemp(3)
+-.SH ASSEMBLER
+-(getpid = 20.)
+-.br
+-.B sys getpid
+-.br
+-(pid in r0)
+//GO.SYSIN DD getpid.2
+echo getuid.2
+sed 's/.//' >getuid.2 <<'//GO.SYSIN DD getuid.2'
+-.TH GETUID 2 
+-.SH NAME
+-getuid, getgid, geteuid, getegid \- get user and group identity
+-.SH SYNOPSIS
+-.B getuid( )
+-.PP
+-.B geteuid( )
+-.PP
+-.B getgid( )
+-.PP
+-.B getegid( )
+-.SH DESCRIPTION
+-.I Getuid
+-returns the real user ID of the current process,
+-.I geteuid
+-the effective user ID.
+-The real user ID identifies the person who is logged in,
+-in contradistinction to the effective user ID, which
+-determines his access permission at the moment.
+-It is thus useful to programs which operate using
+-the `set user ID' mode, to find out who invoked them.
+-.PP
+-.I Getgid
+-returns the real group ID,
+-.I getegid
+-the effective group ID.
+-.SH "SEE ALSO"
+-setuid(2)
+-.SH ASSEMBLER
+-(getuid = 24.)
+-.br
+-.B sys getuid
+-.br
+-(real user ID in r0, effective user ID in r1)
+-.PP
+-(getgid = 47.)
+-.br
+-.B sys getgid
+-.br
+-(real group ID in r0, effective group ID in r1)
+//GO.SYSIN DD getuid.2
+echo indir.2
+sed 's/.//' >indir.2 <<'//GO.SYSIN DD indir.2'
+-.TH INDIR 2 
+-.SH NAME
+-indir \- indirect system call
+-.SH ASSEMBLER
+-(indir = 0.)
+-.br
+-.B sys indir; call
+-.PP
+-The system call at the location
+-.I call
+-is executed.
+-Execution resumes after the
+-.I indir
+-call.
+-.PP
+-The main purpose of
+-.I indir
+-is to allow a program to
+-store arguments in system calls and execute them
+-out of line in the data segment.
+-This preserves the purity of the text segment.
+-.PP
+-If
+-.I indir
+-is executed indirectly,
+-it is a no-op.
+-If the instruction at the indirect
+-location is not a system call,
+-.I indir
+-returns error code EINVAL;
+-see
+-.IR intro (2).
+//GO.SYSIN DD indir.2
+echo intro.2
+sed 's/.//' >intro.2 <<'//GO.SYSIN DD intro.2'
+-.TH INTRO 2 
+-.de en
+-.HP
+-\\$1  \\$2  \\$3
+-.br
+-..
+-.SH NAME
+-intro, errno \- introduction to system calls and error numbers
+-.SH SYNOPSIS
+-.B #include <errno.h>
+-.SH DESCRIPTION
+-Section 2 of this manual
+-lists all the entries into the system.
+-Most of these calls have an error return.
+-.pg
+-An error condition is indicated by an otherwise
+-impossible returned value.
+-Almost always this is \(mi1;
+-the individual sections specify the details.
+-An error number is also made available
+-in the external variable
+-.IR errno .
+-.I Errno
+-is not cleared on successful calls, so it should be tested only
+-after an error has occurred.
+-.PP
+-There is a table of messages
+-associated with each error, and a routine for printing the
+-message;
+-See
+-.IR perror (3).
+-The possible error numbers
+-are not recited with each writeup in section 2, since many
+-errors are possible for most of the calls.
+-Here is a list of the error numbers,
+-their names as defined in <errno.h>,
+-and the messages available using
+-.IR perror .
+-.en 0 \h'\w'EIO'u' "Error 0
+-Unused.
+-.en 1 EPERM "Not owner
+-Typically this error indicates
+-an attempt to modify a file in some way forbidden
+-except to its owner or super-user.
+-It is also returned for attempts
+-by ordinary users to do things
+-allowed only to the super-user.
+-.en 2 ENOENT "No such file or directory
+-This error occurs when a file name is specified
+-and the file should exist but doesn't, or when one
+-of the directories in a path name does not exist.
+-.en 3 ESRCH "No such process
+-The process whose number was given to
+-.I signal
+-and
+-.I ptrace
+-does not exist, or is already dead.
+-.en 4 EINTR "Interrupted system call
+-An asynchronous signal (such as interrupt or quit),
+-which the user has elected to catch,
+-occurred during a system call.
+-If execution is resumed
+-after processing the signal,
+-it will appear as if the interrupted system call
+-returned this error condition.
+-.en 5 EIO "I/O error
+-Some physical I/O error occurred during a
+-.I read
+-or
+-.IR write .
+-This error may in some cases occur
+-on a call following the one to which it actually applies.
+-.en 6 ENXIO "No such device or address
+-I/O on a special file refers to a subdevice that does not
+-exist,
+-or beyond the limits of the device.
+-It may also occur when, for example, a tape drive
+-is not dialled in or no disk pack is loaded on a drive.
+-.en 7 E2BIG "Arg list too long
+-An argument list longer than 5120 bytes
+-is presented to
+-.IR exec .
+-.en 8 ENOEXEC "Exec format error
+-A request is made to execute a file
+-which, although it has the appropriate permissions,
+-does not start with a valid magic number, see
+-.IR a.out (5).
+-.en 9 EBADF "Bad file number
+-Either a file descriptor refers to no
+-open file,
+-or a read (resp. write) request is made to
+-a file that is open only for writing (resp. reading).
+-.en 10 ECHILD "No children
+-.I Wait
+-and the process has no
+-living or unwaited-for children.
+-.en 11 EAGAIN "No more processes
+-In a
+-.I fork,
+-the system's process table is full
+-or the user is not allowed to create any more
+-processes.
+-.en 12 ENOMEM "Not enough core
+-During an
+-.I exec
+-or
+-.I break,
+-a program asks for more core than the system is able to supply.
+-This is not a temporary condition; the maximum core size
+-is a system parameter.
+-The error may also occur if the arrangement
+-of text, data, and stack segments
+-requires too many segmentation registers.
+-.en 13 EACCES "Permission denied
+-An attempt was made to access a file in a way forbidden
+-by the protection system.
+-.en 14 EFAULT "Bad address
+-The system encountered a hardware fault in attempting to
+-access the arguments of a system call.
+-.en 15 ENOTBLK "Block device required
+-A plain file was mentioned where a block device was required,
+-e.g. in
+-.IR mount .
+-.en 16 EBUSY "Mount device busy
+-An attempt to mount a device that was already mounted or
+-an attempt was made to dismount a device
+-on which there is an active file
+-(open file, current directory, mounted-on file, active text segment).
+-.en 17 EEXIST "File exists
+-An existing file was mentioned in an inappropriate context,
+-e.g.
+-.IR link .
+-.en 18 EXDEV "Cross-device link
+-A link to a file on another device
+-was attempted.
+-.en 19 ENODEV "No such device
+-An attempt was made to apply an inappropriate
+-system call to a device;
+-e.g. read a write-only device.
+-.en 20 ENOTDIR "Not a directory
+-A non-directory was specified where a directory
+-is required,
+-for example in a path name or
+-as an argument to
+-.IR chdir .
+-.en 21 EISDIR "Is a directory
+-An attempt to write on a directory.
+-.en 22 EINVAL "Invalid argument
+-Some invalid argument:
+-dismounting a non-mounted
+-device,
+-mentioning an unknown signal in
+-.I signal,
+-reading or writing a file for which
+-.I seek
+-has generated a negative pointer.
+-Also set by math functions, see 
+-.IR intro (3).
+-.en 23 ENFILE "File table overflow
+-The system's table of open files is full,
+-and temporarily no more
+-.I opens
+-can be accepted.
+-.en 24 EMFILE "Too many open files
+-Customary configuration limit is 20 per process.
+-.en 25 ENOTTY "Not a typewriter
+-The file mentioned in
+-.I stty
+-or
+-.I gtty
+-is not a terminal or one of the other
+-devices to which these calls apply.
+-.en 26 ETXTBSY "Text file busy
+-An attempt to execute a pure-procedure
+-program that is currently open for writing
+-(or reading!).
+-Also an attempt to open for writing a pure-procedure
+-program that is being executed.
+-.en 27 EFBIG "File too large
+-The size of a file exceeded the maximum (about
+-.if t 10\u\s-29\s+2\d
+-.if n 1.0E9
+-bytes).
+-.en 28 ENOSPC "No space left on device
+-During a
+-.I write
+-to an ordinary file,
+-there is no free space left on the device.
+-.en 29 ESPIPE "Illegal seek
+-An
+-.I lseek
+-was issued to a pipe.
+-This error should also be issued for
+-other non-seekable devices.
+-.en 30 EROFS "Read-only file system
+-An attempt to modify a file or directory
+-was made
+-on a device mounted read-only.
+-.en 31 EMLINK "Too many links
+-An attempt to make more than 32767 links to a file.
+-.en 32 EPIPE "Broken pipe
+-A write on a pipe for which there is no process
+-to read the data.
+-This condition normally generates a signal;
+-the error is returned if the signal is ignored.
+-.en 33 EDOM "Math argument
+-The argument of a function in the math package (3M)
+-is out of the domain of the function.
+-.en 34 ERANGE "Result too large
+-The value of a function in the math package (3M)
+-is unrepresentable within machine precision.
+-.SH SEE ALSO
+-intro(3)
+-.SH ASSEMBLER
+-.B as /usr/include/sys.s file ...
+-.PP
+-The PDP11 assembly language interface is given for each
+-system call.
+-The assembler symbols are defined in `/usr/include/sys.s'.
+-.PP
+-Return values appear in registers r0 and r1;
+-it is unwise to count on these registers being preserved
+-when no value is expected.
+-An erroneous call is always
+-indicated by turning on the c-bit of the condition codes.
+-The error number is returned in r0.
+-The presence of an error is most easily tested
+-by the instructions
+-.I bes
+-and
+-.I bec
+-(`branch on error set (or clear)').
+-These are synonyms for
+-the
+-.I bcs
+-and
+-.I bcc
+-instructions.
+-.PP
+-On the Interdata 8/32, the system call arguments
+-correspond well to the arguments of the C routines.
+-The sequence is:
+-.IP
+-.nf
+-la    %2,errno
+-l     %0,&callno
+-svc   0,args
+-.fi
+-.PP
+-Thus register 2 points to a word into which the error number will be
+-stored as needed; it is cleared if no error occurs.
+-Register 0 contains the system call number; the nomenclature
+-is identical to that on the PDP11.
+-The argument of the
+-.I svc
+-is the address of the arguments, laid out in storage
+-as in the C calling sequence.
+-The return value is in register 2 (possibly 3 also, as in
+-.IR pipe )
+-and is \-1 in case of error.
+-The overflow bit in the program status word is also
+-set when errors occur.
+//GO.SYSIN DD intro.2
+echo ioctl.2
+sed 's/.//' >ioctl.2 <<'//GO.SYSIN DD ioctl.2'
+-.TH IOCTL 2 
+-.SH NAME
+-ioctl, stty, gtty \- control device
+-.SH SYNOPSIS
+-.B #include <sgtty.h>
+-.PP
+-.B ioctl(fildes, request, argp)
+-.br
+-.B struct sgttyb *argp;
+-.PP
+-.B stty(fildes, argp)
+-.br
+-.B struct sgttyb *argp;
+-.PP
+-.B gtty(fildes, argp)
+-.br
+-.B struct sgttyb *argp;
+-.SH DESCRIPTION
+-.I Ioctl
+-performs a variety of functions
+-on character special files (devices).
+-The writeups of various devices
+-in section 4 discuss how
+-.I ioctl
+-applies to them.
+-.PP
+-For certain status setting and status inquiries
+-about terminal devices, the functions
+-.I stty
+-and
+-.I gtty
+-are equivalent to
+-.RS
+-.B ioctl(fildes, TIOCSETP, argp)
+-.br
+-.B ioctl(fildes, TIOCGETP, argp)
+-.RE
+-.LP
+-respectively; see
+-.IR tty (4).
+-.PP
+-The following two calls, however, apply to any open file:
+-.PP
+-.RS
+-.B ioctl(fildes, FIOCLEX, NULL);
+-.br
+-.B ioctl(fildes, FIONCLEX, NULL);
+-.RE
+-.LP
+-The first causes the file to be closed automatically during
+-a successful
+-.I exec
+-operation;
+-the second reverses the effect of the first.
+-.SH "SEE ALSO"
+-stty(1), tty(4), exec(2)
+-.SH DIAGNOSTICS
+-Zero is returned if the call was successful;
+-\-1 if the file descriptor does not refer to
+-the kind of file for which it was intended.
+-.SH BUGS
+-Strictly speaking,
+-since 
+-.I ioctl
+-may be extended in different ways to devices with
+-different properties,
+-.I argp
+-should have an open-ended declaration like
+-.IP
+-.B union { struct sgttyb
+-.RB ... ;
+-\&...
+-.B } *argp;
+-.PP
+-The important thing is that the size is fixed by `struct sgttyb'.
+-.SH ASSEMBLER
+-(ioctl = 54.)
+-.br
+-.B sys ioctl; fildes; request; argp
+-.PP
+-(stty = 31.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B stty; argp
+-.PP
+-(gtty = 32.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys gtty; argp
+//GO.SYSIN DD ioctl.2
+echo kill.2
+sed 's/.//' >kill.2 <<'//GO.SYSIN DD kill.2'
+-.TH KILL 2 
+-.SH NAME
+-kill  \-  send signal to a process
+-.SH SYNOPSIS
+-.B kill(pid, sig);
+-.SH DESCRIPTION
+-.I Kill
+-sends the signal
+-.I sig
+-to the process specified by the
+-process number in r0.
+-See
+-.IR signal (2)
+-for a list of signals.
+-.PP
+-The sending and receiving processes must
+-have the same effective user ID, otherwise
+-this call is restricted to the super-user.
+-.PP
+-If the process number is 0,
+-the signal is sent to all other processes in the
+-sender's process group;
+-see
+-.IR tty (4).
+-.PP
+-If the process number is \-1, and the user is the super-user,
+-the signal is broadcast universally
+-except to processes 0 and 1, the scheduler
+-and initialization processes,
+-see
+-.IR init (8).
+-.PP
+-Processes may send signals to themselves.
+-.SH "SEE ALSO"
+-signal(2), kill(1)
+-.SH DIAGNOSTICS
+-Zero is returned if the process is killed;
+-\-1 is returned if the process does not
+-have the same effective user ID and the
+-user is not super-user, or if the process
+-does not exist.
+-.SH ASSEMBLER
+-(kill = 37.)
+-.br
+-(process number in r0)
+-.br
+-.B sys kill; sig
+//GO.SYSIN DD kill.2
+echo link.2
+sed 's/.//' >link.2 <<'//GO.SYSIN DD link.2'
+-.TH LINK 2 
+-.SH NAME
+-link \- link to a file
+-.SH SYNOPSIS
+-.B link(name1, name2)
+-.br
+-.B char *name1, *name2;
+-.SH DESCRIPTION
+-A link
+-to
+-.I name1
+-is created;
+-the link has the name
+-.IR name2 .
+-Either name may be an arbitrary path name.
+-.SH "SEE ALSO"
+-ln(1), unlink(2)
+-.SH DIAGNOSTICS
+-Zero is returned when a link is made;
+-\-1 is returned when
+-.I name1
+-cannot be found; when
+-.I name2
+-already exists; when the directory of
+-.I name2
+-cannot be written; when
+-an attempt is made to link to a directory by a user
+-other than the super-user;
+-when an attempt is made to link
+-to a file on another file system;
+-when a file has too many links.
+-.SH ASSEMBLER
+-(link = 9.)
+-.br
+-.B sys link; name1; name2
+//GO.SYSIN DD link.2
+echo lock.2
+sed 's/.//' >lock.2 <<'//GO.SYSIN DD lock.2'
+-.TH LOCK 2 local
+-.SH NAME
+-lock \- lock a process in primary memory
+-.SH SYNOPSIS
+-.B lock(flag)
+-.SH DESCRIPTION
+-If the
+-.I flag
+-argument is non-zero,
+-the process executing this call
+-will not be swapped except if it is required
+-to grow.
+-If the argument is zero,
+-the process is
+-.RI un lock ed.
+-This call may only be executed by
+-the super-user.
+-.SH BUGS
+-.IR Lock ed
+-processes interfere with the compaction of primary memory
+-and can cause deadlock.
+-This system call is not considered
+-a permanent part of the system.
+-.SH ASSEMBLER
+-(lock = 53.)
+-.br
+-.B sys lock; flag
+//GO.SYSIN DD lock.2
+echo lseek.2
+sed 's/.//' >lseek.2 <<'//GO.SYSIN DD lseek.2'
+-.TH LSEEK 2 
+-.SH NAME
+-lseek, tell \- move read/write pointer
+-.SH SYNOPSIS
+-.B long lseek(fildes, offset, whence)
+-.br
+-.B long offset;
+-.PP
+-.B long tell(fildes)
+-.SH DESCRIPTION
+-The file
+-descriptor refers to a file open for reading or writing.
+-The read (resp. write) pointer for the file is set as follows:
+-.IP
+-If
+-.I whence
+-is 0, the pointer is set to
+-.I offset
+-bytes.
+-.IP
+-If
+-.I whence
+-is 1, the pointer is set to its current location plus
+-.IR offset .
+-.IP
+-If
+-.I whence
+-is 2, the pointer is set to the size of the
+-file plus
+-.IR offset .
+-.PP
+-The returned value is the resulting pointer location.
+-.PP
+-The obsolete function
+-.IR tell ( fildes )
+-is identical to
+-.IR lseek ( "fildes, 0L, 1" ).
+-.PP
+-Seeking far beyond the end of a file, then writing,
+-creates a gap or `hole', which occupies no
+-physical space and reads as zeros.
+-.SH "SEE ALSO"
+-open(2), creat(2), fseek(3)
+-.SH DIAGNOSTICS
+-\-1
+-is returned for
+-an undefined file descriptor,
+-seek on a pipe,
+-or seek to a position before the beginning of file.
+-.SH BUGS
+-.I Lseek
+-is a no-op on character special files.
+-.SH ASSEMBLER
+-(lseek = 19.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys lseek; offset1; offset2; whence
+-.PP
+-.I Offset1
+-and
+-.I offset2
+-are the high and low words of 
+-.IR offset ;
+-r0 and r1 contain
+-the pointer upon return.
+//GO.SYSIN DD lseek.2
+echo mknod.2
+sed 's/.//' >mknod.2 <<'//GO.SYSIN DD mknod.2'
+-.TH MKNOD 2 
+-.SH NAME
+-mknod \- make a directory or a special file
+-.SH SYNOPSIS
+-.B mknod(name, mode, addr)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Mknod
+-creates a new file
+-whose name is the null-terminated string pointed
+-to by
+-.IR name .
+-The mode of the new file
+-(including directory and special file bits)
+-is initialized from
+-.IR mode .
+-(The protection part of the mode
+-is modified by the process's mode mask; see
+-.IR umask (2)).
+-The first block pointer of the i-node
+-is initialized from
+-.IR addr .
+-For ordinary files and directories
+-.I addr
+-is normally zero.
+-In the case of a special file,
+-.I addr
+-specifies which special file.
+-.PP
+-.I Mknod
+-may be invoked only by the super-user.
+-.SH "SEE ALSO"
+-mkdir(1), mknod(1), filsys(5)
+-.SH DIAGNOSTICS
+-Zero is returned if the file has been made; \-1
+-if the file already exists
+-or if the user is not the super-user.
+-.SH ASSEMBLER
+-(mknod = 14.)
+-.br
+-.B sys  mknod; name; mode; addr
+//GO.SYSIN DD mknod.2
+echo mount.2
+sed 's/.//' >mount.2 <<'//GO.SYSIN DD mount.2'
+-.TH MOUNT 2 
+-.SH NAME
+-mount, umount \- mount or remove file system
+-.SH SYNOPSIS
+-.B mount(special, name, rwflag)
+-.br
+-.B char *special, *name;
+-.PP
+-.B umount(special)
+-.br
+-.B char *special;
+-.SH DESCRIPTION
+-.I Mount
+-announces to the system that a removable file system has
+-been mounted on
+-the block-structured special file
+-.I special;
+-from now on, references to file
+-.I name
+-will refer to
+-the root file on the newly mounted file system.
+-.I Special
+-and
+-.I name
+-are pointers to null-terminated strings
+-containing the appropriate path names.
+-.PP
+-.I Name
+-must exist already. 
+-.I Name
+-must be a directory (unless the root of the mounted file system
+-is not a directory).
+-Its old contents
+-are inaccessible while the file system
+-is mounted.
+-.PP
+-The
+-.I rwflag
+-argument determines whether
+-the file system can be written on; if it is 0 writing
+-is allowed, if non-zero no writing is done.
+-Physically write-protected and magnetic
+-tape file systems must be mounted read-only or
+-errors will occur when access times are updated,
+-whether or not any
+-explicit write is attempted.
+-.PP
+-.I Umount
+-announces to the system that the
+-.I special
+-file is no longer to contain a removable file system.
+-The associated file reverts to its ordinary interpretation.
+-.SH "SEE ALSO"
+-mount(1)
+-.SH DIAGNOSTICS
+-.I Mount
+-returns 0 if the action occurred; \-1 if
+-.I special
+-is inaccessible or not an appropriate file; if
+-.I name
+-does not exist; if
+-.I special
+-is already mounted; if
+-.I name
+-is in use; or if
+-there are already too many
+-file systems mounted.
+-.PP
+-.I Umount
+-returns 0 if the action occurred; \-1 if
+-if the special file is inaccessible or
+-does not have a mounted file system,
+-or if there are active files in the mounted 
+-file system.
+-.SH ASSEMBLER
+-(mount = 21.)
+-.br
+-.B sys  mount; special; name; rwflag
+-.PP
+-(umount = 22.)
+-.br
+-.B sys  umount; special
+//GO.SYSIN DD mount.2
+echo mpx.2
+sed 's/.//' >mpx.2 <<'//GO.SYSIN DD mpx.2'
+-.TH MPX 2 
+-.SH NAME
+-mpx \- create and manipulate multiplexed files
+-.SH SYNOPSIS
+-.B mpx(name, access)
+-.B char *name;
+-.PP
+-.B join(fd, xd)
+-.PP
+-.B chan(xd)
+-.PP
+-.B extract(i, xd)
+-.PP
+-.B attach(i, xd)
+-.PP
+-.B detach(i, xd)
+-.PP
+-.B connect(fd, cd, end)
+-.PP
+-.B npgrp(i, xd, pgrp)
+-.PP
+-.B ckill(i, xd, signal)
+-.PP
+-.B #include <sys/mx.h>
+-.br
+-.B mpxcall(cmd, vec)
+-.br
+-.B int *vec;
+-.SH DESCRIPTION
+-.PP
+-.B mpxcall(cmd, vec)
+-is the system call shared by the 
+-library routines described below.
+-.I Cmd
+-selects a command using values
+-defined in
+-.IR <sys/mx.h> .
+-.I Vec
+-is the address of a
+-structure containing the arguments
+-for the command.
+-.PP
+-.B mpx(name, access)
+-.PP
+-.I Mpx
+-creates and opens the file 
+-.I name
+-with access permission
+-.I access
+-(see
+-.IR creat (2))
+-and returns a file descriptor available for
+-reading and writing.
+-A \-1 is returned if the file cannot be created,
+-if
+-.I name
+-already exists, or
+-if the file table or other operating system
+-data structures are full.
+-The file descriptor is required for use
+-with other routines.
+-.PP
+-If
+-.I name
+-designates a null string,
+-a file descriptor is returned as described
+-but no entry is created in the file system.
+-.PP
+-Once created an mpx file may be opened
+-(see
+-.IR open (2))
+-by any process.
+-This provides a form of interprocess communication
+-whereby a process B can `call' process A
+-by opening an mpx file 
+-created by A.
+-To B, the file is ordinary with one exception:
+-the
+-.I connect
+-primitive could be applied to it.
+-Otherwise the functions
+-described below are used only in process A
+-and descendants that inherit the open mpx file.
+-.PP
+-When a process opens an mpx file, the owner of the
+-file receives a control message when the file is next read.
+-The method for `answering' 
+-this kind of call involves 
+-using
+-.I attach
+-and
+-.I detach
+-as described in more detail below.
+-.PP
+-Once B has opened A's mpx file
+-it is said to have a
+-.I channel
+-to A.
+-A channel is a pair of data streams:
+-in this case, one from B to A and the
+-other from A to B.
+-Several processes may open the same mpx file
+-yielding multiple channels within the one mpx file.
+-By accessing the appropriate channel,
+-A can communicate with B and any others.
+-When A reads (see
+-.IR read (2))
+-from the mpx file
+-data written to A by the other processes appears
+-in A's buffer using a record format
+-described in
+-.IR mpxio (5).
+-When A writes (see
+-.IR write (2))
+-on its mpx file the data must be formatted in a similar way.
+-.PP
+-The following commands
+-are used to manipulate mpx files and channels.
+-.IP
+-.IR join \-
+-adds a new channel on an mpx file to an open file F.
+-I/O on the new channel is I/O on F.
+-.br
+-.IR chan \-
+-creates a new channel.
+-.br
+-.IR extract \-
+-file descriptor maintenance.
+-.br
+-.IR connect \-
+-similar to join except that the open file F is connected
+-to an existing channel.
+-.br
+-.I attach
+-and
+-.IR detach \-
+-used with call protocol.
+-.br
+-.IR npgrp \-
+-manipulates process group numbers so that a channel
+-can act as a control terminal (see
+-.IR tty (4)).
+-.br
+-.IR ckill \-
+-send signal (see
+-.IR signal (2))
+-to process group through channel.
+-.PP
+-A maximum of 15 channels may be connected to an
+-mpx file.
+-They are numbered 0 through 14.
+-.I Join
+-may be used to make one mpx file appear as a channel
+-on another mpx file.
+-A hierarchy or tree of mpx files may be set up in this way.
+-In this case
+-one of the mpx files must be the root of a tree
+-where the other mpx files are interior nodes.
+-The maximum depth of such a tree
+-is 4.
+-.PP
+-An
+-.I index
+-is a 16-bit value
+-that denotes a location
+-in an mpx tree other than the root:
+-the path through mpx `nodes' from the root
+-to the location is expressed as a sequence of
+-4-bit nibbles.
+-The branch taken at the root is represented by
+-the low-order 4-bits of an index.
+-Each succeeding branch is specified by the next
+-higher-order nibble.
+-If the length of a path to be expressed
+-is less than 4,
+-then the illegal channel number, 15,
+-must be used to terminate the sequence.
+-This is not strictly necessary for the
+-simple case of a tree consisting of
+-only a root node: its channels
+-can be expressed by the numbers
+-0 through 14.
+-An index
+-.I i
+-and file descriptor
+-.I xd
+-for the root of an mpx tree are
+-required as arguments to most
+-of the commands described below.
+-Indices also serve as channel identifiers
+-in the record formats given in
+-.IR mpxio (5).
+-Since -1 is not a valid index,
+-it can be returned as a error indication
+-by subroutines that normally return
+-indices.
+-.PP
+-The operating system informs the process managing an mpx file
+-of changes in the status of channels attached to the file
+-by generating messages that
+-are read along with data from the channels.
+-The form and content of these messages is described
+-in
+-.IR mpxio (5).
+-.PP
+-.B join(fd, xd)
+-establishes a connection (channel) between an mpx file
+-and another object.
+-.I Fd
+-is an open file descriptor for a character device
+-or an mpx file and
+-.I xd
+-is the file descriptor of an
+-mpx file.
+-.I Join
+-returns the index for the new channel
+-if the operation succeeds and \-1
+-if it does not.
+-.PP
+-Following  join,
+-.I fd
+-may still be used in any system call that would
+-have been meaningful before the join operation.
+-Thus
+-a process can read and write directly to
+-.I fd
+-as well as access it via
+-.I xd.
+-If the number of channels
+-required for a tree of mpx files
+-exceeds the number of open files
+-permitted a process by the operating system,
+-some of the file descriptors can be released using
+-the standard  
+-.IR close (2)
+-call.
+-Following a close on an active file descriptor for a channel
+-or internal mpx node,
+-that object may still be accessed through the root of the
+-tree.
+-.PP
+-.B chan(xd)
+-allocates a channel and connects
+-one end of it to the mpx file
+-represented by file descriptor
+-.I xd.
+-.I Chan
+-returns the index of the new channel or
+-a \-1 indicating failure.
+-The
+-.I extract
+-primitive can be used to get a non-multiplexed
+-file descriptor for the free end of a channel
+-created by
+-.I chan.
+-.PP
+-Both
+-.I chan
+-and
+-.I join
+-operate on the mpx file specified by
+-.IR xd .
+-File descriptors for interior nodes of an
+-mpx tree must be preserved or reconstructed with
+-.I extract
+-for use with
+-.I join
+-or
+-.IR chan .
+-For the remaining commands described here,
+-.I xd
+-denotes the file descriptor for the
+-root of an mpx tree.
+-.PP
+-.B Extract(i, xd)
+-returns a file descriptor for the object with
+-index
+-.I i
+-on the mpx tree with root file descriptor
+-.I xd.
+-A \-1 is returned by extract if a file descriptor is not available
+-or if the arguments do not refer to an existing
+-channel and mpx file.
+-.PP
+-.B attach(i, xd)
+-.br
+-.BR "detach(i, xd)" .
+-If a process A has created an mpx file represented
+-by file descriptor
+-.I xd,
+-then a process B
+-can open (see
+-.IR open (2))
+-the mpx file.
+-The purpose is to establish a channel between
+-A and B through the mpx file.
+-.I Attach
+-and 
+-.I Detach
+-are used by A to respond to
+-such opens.
+-.PP
+-An open request by B fails immediately if a 
+-new channel cannot be allocated on the mpx file,
+-if the mpx file does not exist,
+-or if it does exist
+-but there is no process (A)
+-with a multiplexed file descriptor
+-for the mpx file
+-(i.e.
+-.I xd
+-as returned by
+-.IR mpx (2)).
+-Otherwise a channel
+-with index number
+-.I i
+-is allocated.
+-The next time A reads on file descriptor
+-.IR xd ,
+-the WATCH control message
+-(see
+-.IR mpxio (5))
+-will be delivered on channel
+-.I i.
+-A  responds to this message with
+-.I attach
+-or 
+-.I detach.
+-The former causes the open to complete and
+-return a file descriptor to B.
+-The latter deallocates channel
+-.I i
+-and causes the open to fail.
+-.PP
+-One mpx file may be placed in `listener' mode.
+-This is done by writing
+-.I "ioctl(xd, MXLSTN, 0)"
+-where
+-.I xd
+-is an mpx file descriptor
+-and MXLSTN is defined in 
+-.IR /usr/include/sgtty.h .
+-The semantics of listener mode are that
+-all file names discovered by 
+-.IR open (2)
+-to have 
+-the syntax
+-.I "system!pathname"
+-(see
+-.IR uucp (1))
+-are treated as opens on the mpx file.
+-The operating system sends the listener process 
+-an OPEN message (see
+-.IR mpxio (5))
+-which includes the file name being opened.
+-.I Attach
+-and
+-.I detach
+-then apply as described above.
+-.PP
+-.I Detach
+-has two other uses:
+-it closes and releases the resources
+-of any active channel it is applied to,
+-and should be used to respond to
+-a CLOSE message (see
+-.IR mpxio (5))
+-on a channel so the channel may be reused.
+-.PP
+-.BR "connect(fd, cd, end)" .
+-.I Fd
+-is a character file descriptor and
+-.I cd
+-is a file descriptor for a channel,
+-such as might be obtained via
+-.I "extract( chan(xd), xd)"
+-or by
+-.IR open (2)
+-followed by
+-.I attach.
+-.I Connect
+-splices the two streams together.
+-If
+-.I end
+-is negative, only
+-the output of
+-.I fd
+-is spliced to the input of
+-.I cd.
+-If
+-.I end
+-is positive, the output of
+-.I cd
+-is spliced to the input of
+-.I fd.
+-If
+-.I end
+-is zero, then both splices are made.
+-.PP
+-.BR "npgrp(i, xd, pgrp)" .
+-If
+-.I xd
+-is negative
+-.I npgrp
+-applies to the process executing it,
+-otherwise
+-.I i
+-and
+-.I xd
+-are interpreted as a channel index and
+-mpx file descriptor
+-and
+-.I npgrp
+-is applied to the process on the
+-non-multiplexed end of the channel.
+-If
+-.I pgrp
+-is zero, the process group number of the indicated process
+-is set to the process number of that process,
+-otherwise the value of
+-.I pgrp
+-is used as the process group number.
+-.PP
+-.I Npgrp
+-normally returns the new process group number.
+-If
+-.I i
+-and
+-.I xd
+-specify  a nonexistant channel,
+-.I npgrp
+-returns \-1.
+-.PP
+-.B ckill(i, xd, signal)
+-sends the specified signal (see
+-.IR signal (2))
+-through the channel specified by
+-.I i
+-and
+-.I xd.
+-If the channel is connected to anything other
+-than a process,
+-.I ckill
+-is a null operation.
+-If there is a process at the other end of the channel,
+-the process group will be interrupted (see
+-.IR signal (2),
+-.IR kill (2)).
+-.I Ckill
+-normally returns 
+-.I signal.
+-If
+-.I ch
+-and
+-.I xd
+-specify a nonexistent channel,
+-.I ckill
+-returns \-1.
+-.SH FILES
+-/usr/include/sys/mx.h
+-.br
+-/usr/include/sgtty.h
+-.SH "SEE ALSO"
+-mpxio(5)
+-.SH BUGS
+-.PP
+-Mpx files are an experimental part of the operating
+-system more subject to change and prone to bugs
+-than other parts.
+-Maintenance programs, e.g.
+-.IR icheck (1),
+-diagnose mpx files as  an illegal mode.
+-Channels may only be connected to objects in the operating
+-system that are accessible through the line discipline
+-mechanism.
+-Higher performace line disciplines are needed.
+-The maximum tree depth restriction is not really checked.
+-A non-destructive
+-.I disconnect
+-primitive (inverse of
+-.IR connect )
+-is not provided.
+-A non-blocking flow control strategy
+-based on messages defined in
+-.IR mpxio (5)
+-should not be attempted by novices;
+-the enabling
+-.I ioctl
+-command should be protected.
+-The
+-.I join
+-operation could be subsumed by
+-.I connect.
+-A mechanism is needed for moving a channel from one
+-location in an mpx tree to another.
+//GO.SYSIN DD mpx.2
+echo mpxcall.2
+sed 's/.//' >mpxcall.2 <<'//GO.SYSIN DD mpxcall.2'
+-.TH MPXCALL 2
+-.SH NAME
+-mpxcall \- multiplexor and channel interface
+-.SH SYNOPSIS
+-.B mpxcall(arg1, arg2, arg3, cmd)
+-.SH DESCRIPTION
+-.I Mpxcall
+-supplies a primitive interface to the kernel
+-used by the routines listed below.
+-Each routine that uses
+-.I mpxcall
+-passes an integer
+-.I cmd
+-as the fourth argument.
+-These are defined in
+-.I /usr/include/mx.h.
+-.I Mpxcall
+-always returns an integer which is to be interpreted
+-in accordance with the definition of
+-.I cmd.
+-.SH "SEE ALSO"
+-group(2), join(2), extract(2), connect(2), chan(2), attach(2), detach(2)
+-.SH DIAGNOSTICS
+-The value \-1 is returned on error.
+//GO.SYSIN DD mpxcall.2
+echo nice.2
+sed 's/.//' >nice.2 <<'//GO.SYSIN DD nice.2'
+-.TH NICE 2 
+-.SH NAME
+-nice \- set program priority
+-.SH SYNOPSIS
+-.B nice(incr)
+-.SH DESCRIPTION
+-The scheduling
+-priority of the process is augmented by
+-.IR incr .
+-Positive priorities get less
+-service than normal.
+-Priority 10 is recommended to users
+-who wish to execute long-running programs
+-without flak from the administration.
+-.PP
+-Negative increments are ignored except on behalf of 
+-the super-user.
+-The priority is limited to the range
+-\-20 (most urgent) to 20 (least).
+-.PP
+-The priority of a process is
+-passed to a child process by
+-.IR fork (2).
+-For a privileged process to return to normal priority
+-from an unknown state,
+-.I nice
+-should be called successively with arguments
+-\-40 (goes to priority \-20 because of truncation),
+-20 (to get to 0),
+-then 0 (to maintain compatibility with previous versions
+-of this call).
+-.SH "SEE ALSO"
+-nice(1)
+-.SH ASSEMBLER
+-(nice = 34.)
+-.br
+-(priority in r0)
+-.br
+-.B sys nice
+//GO.SYSIN DD nice.2
+echo open.2
+sed 's/.//' >open.2 <<'//GO.SYSIN DD open.2'
+-.TH OPEN 2 
+-.SH NAME
+-open \- open for reading or writing
+-.SH SYNOPSIS
+-.B open(name, mode)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Open
+-opens the file
+-.I name
+-for reading
+-(if
+-.I mode
+-is 0),
+-writing (if
+-.I mode
+-is 1) or for both reading and writing
+-(if
+-.I mode
+-is 2).
+-.I Name
+-is the address of a string of ASCII characters representing
+-a path name, terminated by a null character.
+-.PP
+-The file is positioned at the beginning (byte 0).
+-The returned file descriptor must be used for subsequent calls
+-for other input-output functions on the file.
+-.SH "SEE ALSO"
+-creat(2), read(2), write(2), dup(2), close(2)
+-.SH DIAGNOSTICS
+-The value \-1 is returned
+-if the file does not exist,
+-if one of the necessary directories
+-does not exist or is unreadable, if the file is not
+-readable (resp. writable), or if too many files are open.
+-.SH ASSEMBLER
+-(open = 5.)
+-.br
+-.B sys open; name; mode
+-.br
+-(file descriptor in r0)
+//GO.SYSIN DD open.2
+echo pause.2
+sed 's/.//' >pause.2 <<'//GO.SYSIN DD pause.2'
+-.TH PAUSE 2 
+-.SH NAME
+-pause \- stop until signal
+-.SH SYNOPSIS
+-.B pause( )
+-.SH DESCRIPTION
+-.I Pause
+-never returns normally.
+-It is used to give up control while waiting for
+-a signal from
+-.IR kill (2)
+-or
+-.IR alarm (2).
+-.SH SEE ALSO
+-kill(1), kill(2), alarm(2), signal(2), setjmp(3)
+-.SH ASSEMBLER
+-(pause = 29.)
+-.br
+-.B sys pause
+//GO.SYSIN DD pause.2
+echo phys.2
+sed 's/.//' >phys.2 <<'//GO.SYSIN DD phys.2'
+-.TH PHYS 2 PDP11
+-.SH NAME
+-phys \- allow a process to access physical addresses
+-.SH SYNOPSIS
+-.B phys(segreg, size, physadr)
+-.SH DESCRIPTION
+-The argument
+-.I segreg
+-specifies a process virtual (data-space) address
+-range of 8K bytes starting
+-at virtual address
+-.IR segreg \(mu8K
+-bytes.
+-This address range is mapped into
+-physical address
+-.IR physadr \(mu64
+-bytes.
+-Only the first
+-.IR size \(mu64
+-bytes of this mapping is addressable.
+-If
+-.I size
+-is zero,
+-any previous mapping of this
+-virtual address range is nullified.
+-For example,
+-the call
+-.PP
+-      phys(6, 1, 0177775);
+-.PP
+-will map virtual addresses 0160000-0160077 into
+-physical addresses 017777500-017777577.
+-In particular,
+-virtual address 0160060 is the PDP-11 console
+-located at physical address 017777560.
+-.PP
+-This call may only be executed by the super-user.
+-.SH "SEE ALSO"
+-PDP-11 segmentation hardware
+-.SH DIAGNOSTICS
+-The function value zero is returned if
+-the physical mapping is in effect.
+-The value \-1 is returned
+-if not super-user,
+-if
+-.I segreg
+-is not in the range 0-7,
+-if
+-.I size
+-is not in the range 0-127,
+-or if
+-the specified
+-.I segreg
+-is already used for other than
+-a previous call to
+-.IR phys .
+-.SH BUGS
+-This system call is obviously very machine
+-dependent and very dangerous.
+-This system call is not considered
+-a permanent part of the system.
+-.SH ASSEMBLER
+-(phys = 52.)
+-.br
+-.B sys phys; segreg; size; physadr
+//GO.SYSIN DD phys.2
+echo pipe.2
+sed 's/.//' >pipe.2 <<'//GO.SYSIN DD pipe.2'
+-.TH PIPE 2 
+-.SH NAME
+-pipe \- create an interprocess channel
+-.SH SYNOPSIS
+-.B pipe(fildes)
+-.br
+-.B int fildes[2];
+-.SH DESCRIPTION
+-The
+-.I pipe
+-system call
+-creates an I/O mechanism called a pipe.
+-The file descriptors returned can
+-be used in read and write operations.
+-When the pipe is written using the descriptor
+-.IR fildes [1]
+-up to 4096 bytes of data are buffered
+-before the writing process is suspended.
+-A read using the descriptor
+-.IR fildes [0]
+-will pick up the data.
+-Writes with a count of 4096 bytes or less are atomic;
+-no other process can intersperse data.
+-.PP
+-It is assumed that after the
+-pipe has been set up,
+-two (or more)
+-cooperating processes
+-(created by subsequent
+-.I fork
+-calls)
+-will pass data through the
+-pipe with
+-.I read
+-and
+-.I write
+-calls.
+-.PP
+-The Shell has a syntax
+-to set up a linear array of processes
+-connected by pipes.
+-.PP
+-Read calls on an empty
+-pipe (no buffered data) with only one end
+-(all write file descriptors closed)
+-returns an end-of-file.
+-.SH "SEE ALSO"
+-sh(1), read(2), write(2), fork(2)
+-.SH DIAGNOSTICS
+-The function value zero is returned if the
+-pipe was created; \-1 if
+-too many files are already open.
+-A signal is generated if a write on a pipe with only one end is attempted.
+-.SH BUGS
+-Should more than 4096 bytes be necessary in any
+-pipe among a loop of processes, deadlock will occur.
+-.SH ASSEMBLER
+-(pipe = 42.)
+-.br
+-.B sys pipe
+-.br
+-(read file descriptor in r0)
+-.br
+-(write file descriptor in r1)
+//GO.SYSIN DD pipe.2
+echo pkon.2
+sed 's/.//' >pkon.2 <<'//GO.SYSIN DD pkon.2'
+-.TH PKON 2
+-.SH NAME
+-pkon, pkoff \- establish packet protocol
+-.SH SYNOPSIS
+-.B pkon(fd, size)
+-.PP
+-.B pkoff(fd)
+-.SH DESCRIPTION
+-.I Pkon
+-establishes packet protocol (see
+-.IR pk (4))
+-on the open character special file whose file
+-descriptor is
+-.I fd.
+-.I Size
+-is a desired packet size, a power of 2 in the range
+-.RI 32\(<= size \(<=4096.
+-The size is negotiated with a remote packet driver,
+-and a possibly smaller actual packet size is returned.
+-.PP
+-An asynchronous line used for packet
+-communication should be in raw mode;
+-see
+-.IR tty (4).
+-.PP
+-.I Pkoff
+-turns off the packet driver on the channel whose
+-file descriptor is
+-.I fd.
+-.SH SEE ALSO
+-pk(4), pkopen(3), tty(4), signal(2)
+-.SH DIAGNOSTICS
+-.I Pkon
+-returns \-1 if 
+-.I fd
+-does not describe an open file, or if
+-packet communication cannot
+-be established.
+-.PP
+-.I Pkoff
+-returns \-1 for an unknown file descriptor.
+-.PP
+-Writing on a packet driver link that has been shut down
+-by
+-.I close
+-or
+-.I pkoff
+-at the other end raises signal SIGPIPE
+-in the writing process.
+//GO.SYSIN DD pkon.2
+echo profil.2
+sed 's/.//' >profil.2 <<'//GO.SYSIN DD profil.2'
+-.TH PROFIL 2 
+-.SH NAME
+-profil \- execution time profile
+-.SH SYNOPSIS
+-.B profil(buff, bufsiz, offset, scale)
+-.br
+-.B char *buff;
+-.br
+-.B int bufsiz, offset, scale;
+-.SH DESCRIPTION
+-.I Buff
+-points to an area of core whose length (in bytes) is given by
+-.IR bufsiz .
+-After this call, the user's program counter (pc)
+-is examined each clock tick (60th second);
+-.I offset
+-is subtracted from it, and the result multiplied by
+-.IR scale .
+-If the resulting number corresponds to a word
+-inside
+-.I buff,
+-that word is incremented.
+-.PP
+-The scale is interpreted as an unsigned,
+-fixed-point fraction with binary point at the
+-left: 0177777(8) gives a 1-1 mapping of pc's to words
+-in
+-.I buff;
+-077777(8) maps each pair of instruction words
+-together.
+-02(8) maps all instructions onto the beginning of
+-.I buff
+-(producing a non-interrupting core clock).
+-.PP
+-Profiling is turned off by giving a
+-.I scale
+-of 0 or 1.
+-It is rendered
+-ineffective by giving a
+-.I bufsiz
+-of 0.
+-Profiling is turned off when an
+-.I exec
+-is executed, but remains on in child and parent both
+-after a
+-.IR fork .
+-Profiling may be turned off if an update in
+-.I buff
+-would cause a memory fault.
+-.SH "SEE ALSO"
+-monitor(3), prof(1)
+-.SH ASSEMBLER
+-(profil = 44.)
+-.br
+-.B sys profil; buff; bufsiz; offset; scale
+//GO.SYSIN DD profil.2
+echo ptrace.2
+sed 's/.//' >ptrace.2 <<'//GO.SYSIN DD ptrace.2'
+-.TH PTRACE 2 
+-.SH NAME
+-ptrace  \-  process trace
+-.SH SYNOPSIS
+-#include <signal.h>
+-.PP
+-.B ptrace(request, pid, addr, data)
+-.br
+-.B int *addr;
+-.SH DESCRIPTION
+-.I Ptrace
+-provides a means by which a parent process
+-may control the execution of a child process,
+-and examine and change its core image.
+-Its primary use is for the implementation of breakpoint debugging.
+-There are four arguments whose interpretation
+-depends on a
+-.I request
+-argument.
+-Generally,
+-.I pid
+-is the process ID of the traced process,
+-which must be a child (no more distant descendant)
+-of the tracing process.
+-A process being traced
+-behaves normally until it encounters some signal whether internally generated
+-like `illegal instruction' or externally generated like `interrupt.'
+-See
+-.IR signal (2)
+-for the list.
+-Then the traced process enters a stopped state
+-and its parent is notified via
+-.IR  wait (2).
+-When the child is in the stopped state,
+-its core image can be examined and modified
+-using
+-.IR ptrace .
+-If desired, another
+-.I ptrace
+-request can then cause the child either to terminate
+-or to continue, possibly ignoring the signal.
+-.PP
+-The value of the
+-.I request
+-argument determines the precise
+-action of the call:
+-.TP 4
+-0
+-This request is the only one used by the child process;
+-it declares that the process is to be traced by its parent.
+-All the other arguments are ignored.
+-Peculiar results will ensue
+-if the parent does not expect to trace the child.
+-.TP 4
+-1,2
+-The
+-word in the child process's address space
+-at
+-.I addr
+-is returned.
+-If I and D space are separated, request 1 indicates I space,
+-2 D space.
+-.I Addr
+-must be even.
+-The child must be stopped.
+-The input
+-.I data
+-is ignored.
+-.TP 4
+-3
+-The word
+-of the system's per-process data area corresponding to
+-.I addr
+-is returned.
+-.I Addr
+-must be even and less than 512.
+-This space contains the registers and other information about
+-the process;
+-its layout corresponds to the
+-.I user
+-structure in the system.
+-.TP 4
+-4,5
+-The
+-given
+-.I data
+-is written at the word in the process's address space corresponding to
+-.I addr,
+-which must be even.
+-No useful value is returned.
+-If I and D space are separated, request 4 indicates I space, 
+-5 D space.
+-Attempts to write in pure procedure
+-fail if another process is executing the same file.
+-.TP 4
+-6
+-The process's system data is written,
+-as it is read with request 3.
+-Only a few locations can be written in this way:
+-the general registers,
+-the floating point status and registers,
+-and certain bits of the processor status word.
+-.TP 4
+-7
+-The
+-.I data
+-argument is taken as a signal number
+-and the child's execution continues
+-at location
+-.I addr
+-as if it had incurred that signal.
+-Normally the signal number will be
+-either 0 to indicate that the signal that caused the stop
+-should be ignored,
+-or that value fetched out of the
+-process's image indicating which signal caused
+-the stop.
+-If
+-.I addr
+-is (int *)1 then execution continues from where it stopped.
+-.TP 4
+-8
+-The traced process terminates.
+-.TP 4
+-9
+-Execution continues as in request 7;
+-however, as soon as possible after execution of at least one instruction,
+-execution stops again.
+-The signal number from the stop is
+-SIGTRAP.
+-(On the PDP-11 the T-bit is used and just one instruction
+-is executed;
+-on the Interdata the stop does not take place
+-until a store instruction is executed.)
+-This is part of the mechanism for implementing breakpoints.
+-.PP
+-As indicated,
+-these calls
+-(except for request 0)
+-can be used only when the subject process has stopped.
+-The
+-.I wait
+-call is used to determine
+-when a process stops;
+-in such a case the `termination' status
+-returned by
+-.I wait
+-has the value 0177 to indicate stoppage rather
+-than genuine termination.
+-.PP
+-To forestall possible fraud,
+-.I ptrace
+-inhibits the set-user-id facility
+-on subsequent
+-.IR  exec (2)
+-calls.
+-If a traced process calls
+-.I exec,
+-it will stop before executing the first instruction of the new image
+-showing signal SIGTRAP.
+-.PP
+-On the Interdata 8/32,
+-`word' means a 32-bit word and `even' means 0 mod 4.
+-.SH "SEE ALSO"
+-wait(2), signal(2), adb(1)
+-.SH DIAGNOSTICS
+-The value \-1 is returned if
+-.I request 
+-is invalid,
+-.I pid
+-is not a traceable process,
+-.I addr
+-is out of bounds,
+-or
+-.I data
+-specifies an illegal signal number.
+-.SH BUGS
+-On the Interdata 8/32,
+-`as soon as possible' (request 7)
+-means `as soon as a store instruction has been executed.'
+-.PP
+-The request 0 call should be able to specify
+-signals which are to be treated normally and not cause a stop.
+-In this way, for example,
+-programs with simulated floating point (which
+-use `illegal instruction' signals at a very high rate)
+-could be efficiently debugged.
+-.br
+-The error indication, \-1, is a legitimate function value;
+-.I errno,
+-see
+-.IR intro (2),
+-can be used to disambiguate.
+-.PP
+-It should be possible to stop a process on occurrence of a system
+-call;
+-in this way a completely controlled environment could
+-be provided.
+-.SH ASSEMBLER
+-(ptrace = 26.)
+-.br
+-(data in r0)
+-.br
+-.B sys ptrace; pid; addr; request
+-.br
+-(value in r0)
+//GO.SYSIN DD ptrace.2
+echo read.2
+sed 's/.//' >read.2 <<'//GO.SYSIN DD read.2'
+-.TH READ 2 
+-.SH NAME
+-read \- read from file
+-.SH SYNOPSIS
+-.B read(fildes, buffer, nbytes)
+-.br
+-.B char *buffer;
+-.SH DESCRIPTION
+-A file descriptor is a word
+-returned from a successful
+-.I "open, creat, dup,"
+-or
+-.I pipe
+-call.
+-.I Buffer
+-is the location of
+-.I nbytes
+-contiguous
+-bytes into which the input will be placed.
+-It is not guaranteed
+-that all
+-.I nbytes
+-bytes will be read; for example
+-if the file refers to a typewriter at most one line
+-will be returned.
+-In any event the number of characters read is returned.
+-.PP
+-If the returned value is 0, then
+-end-of-file has been reached.
+-.SH "SEE ALSO"
+-open(2), creat(2), dup(2), pipe(2)
+-.SH DIAGNOSTICS
+-As mentioned,
+-0 is returned when the end of the file has been reached.
+-If the read was otherwise unsuccessful
+-the return value is \-1.
+-Many conditions
+-can generate an error:
+-physical I/O errors, bad buffer address,
+-preposterous
+-.I nbytes,
+-file descriptor not that of
+-an input file.
+-.SH ASSEMBLER
+-(read = 3.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys read; buffer; nbytes
+-.br
+-(byte count in r0)
+//GO.SYSIN DD read.2
+echo setuid.2
+sed 's/.//' >setuid.2 <<'//GO.SYSIN DD setuid.2'
+-.TH SETUID 2 
+-.SH NAME
+-setuid, setgid \- set user and group ID
+-.SH SYNOPSIS
+-.B setuid(uid)
+-.PP
+-.B setgid(gid)
+-.SH DESCRIPTION
+-The user ID (group ID) of the current process is set to
+-the argument.
+-Both the effective and the real ID are set.
+-These calls are only permitted to the super-user
+-or if the argument is the real ID.
+-.SH "SEE ALSO"
+-getuid(2)
+-.SH DIAGNOSTICS
+-Zero is returned if the user (group) ID is set;
+-\-1 is returned otherwise.
+-.SH ASSEMBLER
+-(setuid = 23.)
+-.br
+-(user ID in r0)
+-.br
+-.B sys setuid
+-.PP
+-(setgid = 46.)
+-.br
+-(group ID in r0)
+-.br
+-.B sys  setgid
+//GO.SYSIN DD setuid.2
+echo signal.2
+sed 's/.//' >signal.2 <<'//GO.SYSIN DD signal.2'
+-.TH SIGNAL 2 
+-.SH NAME
+-signal \- catch or ignore signals
+-.SH SYNOPSIS
+-.B #include <signal.h>
+-.PP
+-.B (*signal(sig, func))()
+-.br
+-.B (*func)();
+-.SH DESCRIPTION
+-A signal
+-is generated by some abnormal event,
+-initiated either by user at a typewriter (quit, interrupt),
+-by a program error (bus error, etc.),
+-or by request of another program (kill).
+-Normally all signals
+-cause termination of the receiving process,
+-but a
+-.I signal
+-call allows them either to be ignored
+-or to cause an interrupt to a specified location.
+-Here is the list of signals with names as in
+-the include file.
+-.LP
+-.nf
+-.ta \w'SIGMMMM 'u +\w'15*  'u
+-SIGHUP        1       hangup
+-SIGINT        2       interrupt
+-SIGQUIT       3*      quit
+-SIGILL        4*      illegal instruction (not reset when caught)
+-SIGTRAP       5*      trace trap (not reset when caught)
+-SIGIOT        6*      IOT instruction
+-SIGEMT        7*      EMT instruction
+-SIGFPE        8*      floating point exception
+-SIGKILL       9       kill (cannot be caught or ignored)
+-SIGBUS        10*     bus error
+-SIGSEGV       11*     segmentation violation
+-SIGSYS        12*     bad argument to system call
+-SIGPIPE       13      write on a pipe or link with no one to read it
+-SIGALRM       14      alarm clock
+-SIGTERM       15      software termination signal
+-      16      unassigned
+-.fi
+-.PP
+-The starred signals in the list above cause a core image
+-if not caught or ignored.
+-.PP
+-If
+-.I func
+-is SIG_DFL, the default action
+-for signal
+-.I sig
+-is reinstated; this default is termination,
+-sometimes with a core image.
+-If
+-.I func
+-is SIG_IGN the signal is ignored.
+-Otherwise
+-when the signal occurs
+-.I func
+-will be called with the
+-signal number as argument.
+-A return from the function will
+-continue the process at the point it was interrupted.
+-Except as indicated,
+-a signal is reset to SIG_DFL after being caught.
+-Thus if it is desired to
+-catch every such signal,
+-the catching routine must
+-issue another
+-.I signal
+-call.
+-.PP
+-When a caught signal occurs
+-during certain system calls, the call terminates prematurely.
+-In particular this can occur
+-during a
+-.I read
+-or
+-.IR write (2)
+-on a slow device (like a typewriter; but not a file);
+-and during
+-.I pause
+-or
+-.IR wait (2).
+-When such a signal occurs, the saved user status
+-is arranged in such a way that when return from the
+-signal-catching takes place, it will appear that the
+-system call returned an error status.
+-The user's program may then, if it wishes,
+-re-execute the call.
+-.PP
+-The value of
+-.I signal
+-is the previous (or initial)
+-value of
+-.I func
+-for the particular signal.
+-.PP
+-After a
+-.IR  fork (2)
+-the child inherits
+-all signals.
+-.IR  Exec (2)
+-resets all
+-caught signals to default action.
+-.SH "SEE ALSO"
+-kill(1), kill(2),
+-ptrace(2),
+-setjmp(3)
+-.SH DIAGNOSTICS
+-The value (int)\-1 is returned if the
+-given signal is out of range.
+-.SH BUGS
+-If a repeated signal arrives before the last one can be
+-reset, there is no chance to catch it.
+-.PP
+-The type specification of the routine and its
+-.I func
+-argument are problematical.
+-.SH ASSEMBLER
+-(signal = 48.)
+-.br
+-.B sys  signal; sig; label
+-.br
+-(old label in r0)
+-.PP
+-If
+-.I label
+-is 0,
+-default action is reinstated.
+-If
+-.I label
+-is odd, the signal is ignored.
+-Any other even
+-.I label
+-specifies an address in the process
+-where an interrupt is simulated.
+-An RTI or RTT instruction will return from the
+-interrupt.
+//GO.SYSIN DD signal.2
+echo stat.2
+sed 's/.//' >stat.2 <<'//GO.SYSIN DD stat.2'
+-.TH STAT 2 
+-.SH NAME
+-stat, fstat \- get file status
+-.SH SYNOPSIS
+-.B #include <sys/types.h>
+-.br
+-.B #include <sys/stat.h>
+-.PP
+-.B stat(name, buf)
+-.br
+-.B char *name;
+-.br
+-.B struct stat *buf;
+-.PP
+-.B fstat(fildes, buf)
+-.br
+-.B struct stat *buf;
+-.SH DESCRIPTION
+-.I Stat
+-obtains detailed information about a named file.
+-.I Fstat
+-obtains the same information about an open file
+-known by the file descriptor from a successful
+-.I open, creat, dup
+-or
+-.IR pipe (2)
+-call.
+-.PP
+-.I Name
+-points to a null-terminated string naming
+-a file;
+-.I buf
+-is the address of a buffer
+-into which information is placed concerning the file.
+-It is unnecessary to have any
+-permissions at all with respect to the file, but all directories
+-leading to the file must be searchable.
+-The layout of the structure pointed to by buf
+-as defined in
+-.I <stat.h>
+-is given below.
+-.I St_mode 
+-is encoded according to the `#define' statements.
+-.PP
+-.nf
+-.so /usr/include/sys/stat.h
+-.fi
+-.PP
+-The mode bits 0000070 and 0000007 encode group and
+-others permissions (see
+-.IR chmod (2)).
+-The defined types,
+-.I 
+-ino_t, off_t, time_t,
+-name various width integer values;
+-.I dev_t
+-encodes
+-major and minor device numbers;
+-their exact definitions are in
+-the include file <sys/types.h>
+-(see
+-.IR types (5).
+-.PP
+-When
+-.I fildes
+-is associated with a pipe,
+-.I fstat
+-reports an ordinary file
+-with restricted permissions.
+-The size is the number of bytes queued in the pipe.
+-.PP
+-.I st_atime
+-is the file was last read.
+-For reasons of efficiency, it is not set when a directory
+-is searched, although this would be more logical.
+-.I st_mtime
+-is the time the file was last written or created.
+-It is not set by changes of owner, group, link count, or mode.
+-.I st_ctime
+-is set both both by writing and changing the i-node.
+-.SH "SEE ALSO"
+-ls(1), filsys(5)
+-.SH DIAGNOSTICS
+-Zero is returned if a status is available;
+-\-1 if the file cannot be found.
+-.SH ASSEMBLER
+-(stat = 18.)
+-.br
+-.B sys stat; name; buf
+-.PP
+-(fstat = 28.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys fstat; buf
+//GO.SYSIN DD stat.2
+echo stime.2
+sed 's/.//' >stime.2 <<'//GO.SYSIN DD stime.2'
+-.TH STIME 2 
+-.SH NAME
+-stime \- set time
+-.SH SYNOPSIS
+-.B stime(tp)
+-.br
+-.B long *tp;
+-.SH DESCRIPTION
+-.I Stime
+-sets the system's idea of the time and date.
+-Time, pointed to by
+-.I tp,
+-is measured in seconds from 0000 GMT Jan 1, 1970.
+-Only the super-user may use this call.
+-.SH "SEE ALSO"
+-date(1), time(2), ctime(3)
+-.SH DIAGNOSTICS
+-Zero is returned if the time was set;
+-\-1 if user is not the super-user.
+-.SH ASSEMBLER
+-(stime = 25.)
+-.br
+-(time in r0-r1)
+-.br
+-.B sys stime
+-.PP
+//GO.SYSIN DD stime.2
+echo sync.2
+sed 's/.//' >sync.2 <<'//GO.SYSIN DD sync.2'
+-.TH SYNC 2 
+-.SH NAME
+-sync \- update super-block
+-.SH SYNOPSIS
+-.B sync( )
+-.SH DESCRIPTION
+-.I Sync
+-causes all information in core
+-memory that should be on disk to be written out.
+-This includes modified super blocks,
+-modified i-nodes, and delayed block I/O.
+-.PP
+-It should be used by programs which examine a file system,
+-for example
+-.I "icheck, df,"
+-etc.
+-It is mandatory before a boot.
+-.SH "SEE ALSO"
+-sync(1), update(8)
+-.SH BUGS
+-The writing, although scheduled, is not necessarily
+-complete upon return from 
+-.IR sync .
+-.SH ASSEMBLER
+-(sync = 36.)
+-.br
+-.B sys sync
+//GO.SYSIN DD sync.2
+echo time.2
+sed 's/.//' >time.2 <<'//GO.SYSIN DD time.2'
+-.TH TIME 2 
+-.SH NAME
+-time, ftime \- get date and time
+-.SH SYNOPSIS
+-.B long time(0)
+-.PP
+-.B long time(tloc)
+-.br
+-.B long *tloc;
+-.sp
+-.B #include <sys/types.h>
+-.br
+-.B #include <sys/timeb.h>
+-.br
+-.B ftime(tp)
+-.br
+-.B struct timeb *tp;
+-.SH DESCRIPTION
+-.I Time
+-returns the time since 00:00:00 GMT, Jan. 1, 1970, measured
+-in seconds.
+-.PP
+-If
+-.I tloc
+-is nonnull,
+-the return value is also stored in the
+-place to which
+-.I tloc
+-points.
+-.PP
+-The
+-.I ftime
+-entry fills in a structure pointed to by its argument,
+-as defined by
+-.IR <sys/timeb.h> :
+-.PP
+-.nf
+-.ta .5i +\w'unsigned 'u
+-.so /usr/include/sys/timeb.h
+-.fi
+-.PP
+-The structure contains the time since the epoch in seconds,
+-up to 1000 milliseconds of more-precise interval,
+-the local timezone (measured in minutes of time westward from Greenwich),
+-and a flag that, if nonzero, indicates that
+-Daylight Saving time applies locally during the appropriate part of the year.
+-.SH "SEE ALSO"
+-date(1), stime(2), ctime(3)
+-.SH ASSEMBLER
+-(ftime = 35.)
+-.br
+-.B sys ftime; bufptr
+-.PP
+-(time = 13.; obsolete call)
+-.br
+-.B sys time
+-.br
+-(time since 1970 in r0-r1)
+//GO.SYSIN DD time.2
+echo times.2
+sed 's/.//' >times.2 <<'//GO.SYSIN DD times.2'
+-.TH TIMES 2 
+-.SH NAME
+-times \- get process times
+-.SH SYNOPSIS
+-.B times(buffer)
+-.br
+-.B struct tbuffer *buffer;
+-.SH DESCRIPTION
+-.I Times
+-returns time-accounting information
+-for the current process
+-and for the terminated child processes
+-of the current process.
+-All times are in 1/HZ seconds,
+-where HZ=60 in North America.
+-.PP
+-After the call, the buffer will appear as follows:
+-.PP
+-.nf
+-struct tbuffer {
+-      long    proc_user_time;
+-      long    proc_system_time;
+-      long    child_user_time;
+-      long    child_system_time;
+-};
+-.PP
+-.fi
+-The children times are the sum
+-of the children's process times and
+-their children's times.
+-.SH "SEE ALSO"
+-time(1), time(2)
+-.SH ASSEMBLER
+-(times = 43.)
+-.br
+-.B sys times; buffer
+//GO.SYSIN DD times.2
+echo umask.2
+sed 's/.//' >umask.2 <<'//GO.SYSIN DD umask.2'
+-.TH UMASK 2
+-.SH NAME
+-umask \- set file creation mode mask
+-.SH SYNOPSIS
+-.B umask(complmode)
+-.SH DESCRIPTION
+-.I Umask
+-sets a mask used whenever a file is created by
+-.IR creat (2)
+-or
+-.IR mknod (2):
+-the actual mode (see
+-.IR chmod (2))
+-of the newly-created file is the logical
+-.B and
+-of the given mode and the complement of the argument.
+-Only the low-order 9 bits of the mask (the protection bits)
+-participate.
+-In other words, the mask shows the bits to be turned off
+-when files are created.
+-.PP
+-The previous value of the mask is returned by the call.
+-The value is initially 0 (no restrictions).
+-The mask is inherited by child processes.
+-.SH SEE ALSO
+-creat(2), mknod(2), chmod(2)
+-.SH ASSEMBLER
+-(umask = 60.)
+-.br
+-.B sys umask; complmode
+//GO.SYSIN DD umask.2
+echo unlink.2
+sed 's/.//' >unlink.2 <<'//GO.SYSIN DD unlink.2'
+-.TH UNLINK 2 
+-.SH NAME
+-unlink \- remove directory entry
+-.SH SYNOPSIS
+-.B unlink(name)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Name
+-points to a null-terminated string.
+-.I Unlink
+-removes the entry for the file pointed to by
+-.I name
+-from its directory.
+-If this entry was the last link to the file,
+-the contents of the file are freed and the file is destroyed.
+-If, however, the file was open in any process, the actual
+-destruction is delayed until it is closed, even though
+-the directory entry has disappeared.
+-.SH "SEE ALSO"
+-rm(1), link(2)
+-.SH DIAGNOSTICS
+-Zero is normally returned;
+-\-1 indicates that the file does not
+-exist, that its directory cannot be written,
+-or that the file contains pure procedure text
+-that is currently in use.
+-Write permission is not required on the file itself.
+-It is also illegal to unlink a directory
+-(except for the super-user).
+-.SH ASSEMBLER
+-(unlink = 10.)
+-.br
+-.B sys  unlink; name
+//GO.SYSIN DD unlink.2
+echo utime.2
+sed 's/.//' >utime.2 <<'//GO.SYSIN DD utime.2'
+-.TH UTIME 2
+-.SH NAME
+-utime \- set file times
+-.SH SYNOPSIS
+-.B #include <sys/types.h>
+-.br
+-.B utime(file, timep)
+-.br
+-.B char *file;
+-.br
+-.B time_t timep[2];
+-.SH DESCRIPTION
+-The
+-.I utime
+-call
+-uses the
+-`accessed' and `updated' times in that order
+-from the
+-.I timep
+-vector
+-to set the corresponding recorded times for
+-.I file.
+-.PP
+-The caller must be the owner of the file or the super-user.
+-The `inode-changed' time of the file is set to the current time.
+-.SH SEE ALSO
+-stat (2)
+-.SH ASSEMBLER
+-(utime = 30.)
+-.br
+-.B sys utime; file; timep
+//GO.SYSIN DD utime.2
+echo wait.2
+sed 's/.//' >wait.2 <<'//GO.SYSIN DD wait.2'
+-.TH WAIT 2 
+-.SH NAME
+-wait \- wait for process to terminate
+-.SH SYNOPSIS
+-.B wait(status)
+-.br
+-.B int *status;
+-.PP
+-.B wait(0)
+-.SH DESCRIPTION
+-.I Wait
+-causes its caller to delay until a signal is received or
+-one of its child
+-processes terminates.
+-If any child has died since the last
+-.I wait,
+-return is immediate;
+-if there are no children, return is immediate with
+-the error bit set
+-(resp. with a value of \-1 returned).
+-The normal return yields the process ID of the terminated child.
+-In the case of several children several
+-.I wait
+-calls are needed
+-to learn of all the deaths.
+-.PP
+-If
+-.RI (int) status
+-is nonzero, the high byte of the word pointed to
+-receives the low byte of the
+-argument of
+-.I exit
+-when the child terminated.
+-The low byte
+-receives the termination status
+-of the process.
+-See
+-.IR signal (2)
+-for a list of termination statuses (signals);
+-0 status indicates normal termination.
+-A special status (0177) is returned for a stopped process
+-which has not terminated and can be restarted.
+-See
+-.IR ptrace (2).
+-If the 0200 bit of the termination status
+-is set,
+-a core image of the process was produced
+-by the system.
+-.PP
+-If the parent process terminates without
+-waiting on its children,
+-the initialization process
+-(process ID = 1)
+-inherits the children.
+-.SH "SEE ALSO"
+-exit(2), fork(2), signal(2)
+-.SH DIAGNOSTICS
+-Returns
+-\-1 if there are no children not previously waited for.
+-.SH ASSEMBLER
+-(wait = 7.)
+-.br
+-.B sys  wait
+-.br
+-(process ID in r0)
+-.br
+-(status in r1)
+-.PP
+-The high byte of the status is
+-the low byte of r0 in the child at termination.
+//GO.SYSIN DD wait.2
+echo write.2
+sed 's/.//' >write.2 <<'//GO.SYSIN DD write.2'
+-.TH WRITE 2 
+-.SH NAME
+-write \- write on a file
+-.SH SYNOPSIS
+-.B write(fildes, buffer, nbytes)
+-.br
+-.B char *buffer;
+-.SH DESCRIPTION
+-A file descriptor is a word returned from a
+-successful
+-.I open,
+-.I creat,
+-.I dup,
+-or
+-.IR pipe (2)
+-call.
+-.PP
+-.I Buffer
+-is the address of
+-.I nbytes
+-contiguous
+-bytes which are written on the output file.
+-The number of characters actually written is returned.
+-It should be regarded as an error
+-if this is not the same as requested.
+-.PP
+-Writes which are multiples
+-of 512 characters long and begin on a 512-byte boundary
+-in the file
+-are more efficient than any others.
+-.SH "SEE ALSO"
+-creat(2), open(2), pipe(2)
+-.SH DIAGNOSTICS
+-Returns
+-\-1 on error: bad descriptor, buffer address, or
+-count; physical I/O errors.
+-.SH ASSEMBLER
+-(write = 4.)
+-.br
+-(file descriptor in r0)
+-.br
+-.B sys  write; buffer; nbytes
+-.br
+-(byte count in r0)
+//GO.SYSIN DD write.2
diff --git a/doc/7thEdMan/vol1/man3.bun b/doc/7thEdMan/vol1/man3.bun
new file mode 100644 (file)
index 0000000..b921418
--- /dev/null
@@ -0,0 +1,3651 @@
+# To unbundle, run this file
+echo abort.3
+sed 's/.//' >abort.3 <<'//GO.SYSIN DD abort.3'
+-.TH ABORT 3
+-.SH NAME
+-abort \- generate IOT fault
+-.SH DESCRIPTION
+-.I Abort
+-executes the PDP11 IOT instruction.
+-This causes a signal that normally terminates
+-the process with a core dump, which may be used for debugging.
+-.SH SEE ALSO
+-adb(1), signal(2), exit(2)
+-.SH DIAGNOSTICS
+-Usually `IOT trap \- core dumped' from the shell.
+//GO.SYSIN DD abort.3
+echo abs.3
+sed 's/.//' >abs.3 <<'//GO.SYSIN DD abs.3'
+-.TH ABS 3 
+-.SH NAME
+-abs \- integer absolute value
+-.SH SYNOPSIS
+-.B abs(i)
+-.SH DESCRIPTION
+-.I Abs
+-returns
+-the absolute value of its integer operand.
+-.SH SEE ALSO
+-floor(3) for
+-.I fabs
+-.SH BUGS
+-You get what the hardware gives on the largest negative integer.
+//GO.SYSIN DD abs.3
+echo assert.3x
+sed 's/.//' >assert.3x <<'//GO.SYSIN DD assert.3x'
+-.TH ASSERT 3X
+-.SH NAME
+-assert \-
+-program verification
+-.SH SYNOPSIS
+-.B #include <assert.h>
+-.PP
+-.B assert (expression)
+-.SH DESCRIPTION
+-.PP
+-.I Assert
+-is a macro that indicates
+-.I expression
+-is expected to be true at this point in the program.
+-It causes an
+-.IR exit (2)
+-with a diagnostic comment on the standard output
+-when
+-.I expression
+-is false (0).
+-Compiling with the 
+-.IR cc (1)
+-option
+-.SM
+-.B \-DNDEBUG
+-effectively deletes
+-.I assert
+-from the program.
+-.SH DIAGNOSTICS
+-`Assertion failed: file
+-.I f
+-line
+-.I n.'
+-.I F
+-is the source file and
+-.I n
+-the source line number
+-of the
+-.I assert
+-statement.
+//GO.SYSIN DD assert.3x
+echo atof.3
+sed 's/.//' >atof.3 <<'//GO.SYSIN DD atof.3'
+-.TH ATOF 3 
+-.SH NAME
+-atof, atoi, atol \- convert ASCII to numbers
+-.SH SYNOPSIS
+-.B double atof(nptr)
+-.br
+-.B char *nptr;
+-.PP
+-.B atoi(nptr)
+-.br
+-.B char *nptr;
+-.PP
+-.B long atol(nptr)
+-.br
+-.B char *nptr;
+-.SH DESCRIPTION
+-These functions convert a string pointed to by
+-.I nptr
+-to floating, integer, and long integer
+-representation respectively.
+-The first unrecognized character ends the string.
+-.PP
+-.I Atof
+-recognizes an optional string of tabs and spaces,
+-then an optional sign, then
+-a string of digits optionally containing a decimal
+-point, then an optional `e' or `E' followed
+-by an optionally signed integer.
+-.PP
+-.I Atoi
+-and
+-.I atol
+-recognize an optional string of tabs and spaces,
+-then an optional sign, then a string of
+-digits.
+-.SH SEE ALSO
+-scanf(3)
+-.SH BUGS
+-There are no provisions for overflow.
+//GO.SYSIN DD atof.3
+echo crypt.3
+sed 's/.//' >crypt.3 <<'//GO.SYSIN DD crypt.3'
+-.TH CRYPT 3 
+-.SH NAME
+-crypt, setkey, encrypt \- DES encryption
+-.SH SYNOPSIS
+-.B char *crypt(key, salt)
+-.br
+-.B char *key, *salt;
+-.PP
+-.B setkey(key)
+-.br
+-.B char *key;
+-.PP
+-.B encrypt(block, edflag)
+-.br
+-.B char *block;
+-.SH DESCRIPTION
+-.I Crypt
+-is the password encryption routine.
+-It is based on the NBS Data Encryption Standard, with
+-variations intended (among other things) to frustrate use of hardware
+-implementations of the DES for key search.
+-.PP
+-The first argument to
+-.I crypt
+-is a user's typed password.
+-The second is a 2-character string chosen from the
+-set [a-zA-Z0-9./].
+-The
+-.I salt
+-string is used to perturb the DES algorithm in one of 4096
+-different ways, after which the password
+-is used as the key to encrypt repeatedly a constant string.
+-The returned value points to the encrypted password,
+-in the same alphabet as the salt.
+-The first two characters are the salt itself.
+-.PP
+-The other entries provide (rather primitive)
+-access to the actual DES algorithm.
+-The argument of
+-.I setkey
+-is a character array of length 64 containing only the characters
+-with numerical value 0 and 1.
+-If this string is divided into groups of 8,
+-the low-order bit in each group is ignored,
+-leading to a 56-bit key which is set into the machine.
+-.PP
+-The argument to the
+-.I encrypt
+-entry is likewise a character array of length 64
+-containing 0's and 1's.
+-The argument array is modified in place
+-to a similar array
+-representing the bits of the argument after having been
+-subjected to the DES algorithm using the key set by
+-.I setkey.
+-If
+-.I edflag
+-is 0, the argument is encrypted;
+-if non-zero,
+-it is decrypted.
+-.SH "SEE ALSO"
+-passwd(1), passwd(5), login(1), getpass(3)
+-.SH BUGS
+-The return value
+-points to static data whose content is overwritten
+-by each call.
+//GO.SYSIN DD crypt.3
+echo ctime.3
+sed 's/.//' >ctime.3 <<'//GO.SYSIN DD ctime.3'
+-.TH CTIME 3 
+-.SH NAME
+-ctime, localtime, gmtime, asctime, timezone \-  convert date and time to ASCII
+-.SH SYNOPSIS
+-.B char *ctime(clock)
+-.br
+-.B long *clock;
+-.PP
+-.B #include <time.h>
+-.PP
+-.B struct tm *localtime(clock)
+-.br
+-.B long *clock;
+-.PP
+-.B struct tm *gmtime(clock)
+-.br
+-.B long *clock;
+-.PP
+-.B char *asctime(tm)
+-.br
+-.B struct tm *tm;
+-.PP
+-.B char *timezone(zone, dst)
+-.SH DESCRIPTION
+-.I Ctime
+-converts a time pointed to by
+-.I clock
+-such as returned by
+-.IR time (2)
+-into ASCII
+-and returns a pointer to a
+-26-character string
+-in the following form.
+-All the fields have constant width.
+-.PP
+-    Sun Sep 16 01:03:52 1973\\n\\0
+-.PP
+-.I Localtime
+-and
+-.I gmtime
+-return pointers to structures containing
+-the broken-down time.
+-.I Localtime
+-corrects for the time zone and possible daylight savings time;
+-.I gmtime
+-converts directly to GMT, which is the time UNIX uses.
+-.I Asctime
+-converts a broken-down time to ASCII and returns a pointer
+-to a 26-character string.
+-.PP
+-The structure declaration from the include file is:
+-.RS
+-.PP
+-.nf
+-.so /usr/include/time.h
+-.fi
+-.RE
+-.PP
+-These quantities give the time on a 24-hour clock,
+-day of month (1-31), month of year (0-11), day of week
+-(Sunday = 0), year \- 1900, day of year (0-365),
+-and a flag that is nonzero if daylight saving time is in effect.
+-.PP
+-When local time is called for,
+-the program consults the system to determine the time zone and
+-whether the standard U.S.A. daylight saving time adjustment is
+-appropriate.
+-The program knows about the peculiarities
+-of this conversion in 1974 and 1975;
+-if necessary,
+-a table for these years can be extended.
+-.PP
+-.I Timezone
+-returns the name of the time zone associated with its first argument,
+-which is measured in minutes westward from Greenwich.
+-If the second argument is 0, the standard name is used,
+-otherwise the Daylight Saving version.
+-If the required name does not appear in a table
+-built into the routine,
+-the difference from GMT is produced; e.g.
+-in Afghanistan
+-.I timezone(\-(60*4+30), 0)
+-is appropriate because it is 4:30 ahead of GMT
+-and the string
+-.B GMT+4:30
+-is produced.
+-.SH "SEE ALSO"
+-time(2)
+-.SH BUGS
+-The return values point to static data
+-whose content is overwritten by each call.
+//GO.SYSIN DD ctime.3
+echo ctype.3
+sed 's/.//' >ctype.3 <<'//GO.SYSIN DD ctype.3'
+-.TH CTYPE 3 
+-.SH NAME
+-isalpha, isupper, islower, isdigit, isalnum, isspace, ispunct, 
+-isprint, iscntrl, isascii \-
+-character classification
+-.SH SYNOPSIS
+-.B #include <ctype.h>
+-.PP
+-.B isalpha(c)
+-.PP
+-.B . . .
+-.SH DESCRIPTION
+-These macros classify ASCII-coded integer values
+-by table lookup.
+-Each is a predicate returning nonzero for true,
+-zero for false.
+-.I Isascii
+-is defined on all integer values; the rest
+-are defined only where 
+-.I isascii
+-is true and on the single non-ASCII value
+-EOF (see
+-.IR stdio (3)).
+-.TP 15n
+-.I isalpha
+-.I c
+-is a letter
+-.TP
+-.I isupper
+-.I c
+-is an upper case letter
+-.TP
+-.I islower 
+-.I c
+-is a lower case letter
+-.TP
+-.I isdigit
+-.I c
+-is a digit
+-.TP
+-.I isalnum
+-.I c
+-is an alphanumeric character
+-.TP
+-.I isspace
+-.I c
+-is a space, tab, carriage return, newline, or formfeed
+-.TP
+-.I ispunct
+-.I c
+-is a punctuation character (neither control nor alphanumeric)
+-.TP
+-.I isprint
+-.I c
+-is a printing character, code 040(8) (space) through 0176 (tilde)
+-.TP
+-.I iscntrl
+-.I c
+-is a delete character (0177) or ordinary control character
+-(less than 040).
+-.TP
+-.I isascii
+-.I c
+-is an ASCII character, code less than 0200
+-.SH "SEE ALSO"
+-ascii(7)
+//GO.SYSIN DD ctype.3
+echo dbm.3x
+sed 's/.//' >dbm.3x <<'//GO.SYSIN DD dbm.3x'
+-.TH DBM 3X 
+-.SH NAME
+-dbminit, fetch, store, delete, firstkey, nextkey \- data base subroutines
+-.SH SYNOPSIS
+-.nf
+-.PP
+-.B "typedef struct { char *dptr; int dsize; } datum;"
+-.PP
+-.B dbminit(file)
+-.B char *file;
+-.PP
+-.B datum fetch(key)
+-.B datum key;
+-.PP
+-.B store(key, content)
+-.B datum key, content;
+-.PP
+-.B delete(key)
+-.B datum key;
+-.PP
+-.B datum firstkey();
+-.PP
+-.B datum nextkey(key);
+-.B datum key;
+-.SH DESCRIPTION
+-These functions maintain
+-key/content pairs in a data base.
+-The functions will handle very large
+-(a billion blocks)
+-databases and will access a keyed item
+-in one or two filesystem accesses.
+-The functions are obtained with the loader option
+-.BR \-ldbm .
+-.PP
+-.IR Key s
+-and
+-.IR content s
+-are
+-described by the
+-.I datum
+-typedef.
+-A
+-.I datum
+-specifies a string of
+-.I dsize
+-bytes pointed to by
+-.I dptr.
+-Arbitrary binary data, as well as normal
+-ASCII strings, are allowed.
+-The data base is stored in two files.
+-One file is a directory containing a bit map
+-and has `.dir' as its suffix.
+-The second file contains all data and
+-has `.pag' as its suffix.
+-.PP
+-Before a database can be accessed,
+-it must be opened by
+-.I dbminit.
+-At the time of this call,
+-the files
+-.IB file .dir
+-and
+-.IB file .pag
+-must exist.
+-(An empty database is created by
+-creating zero-length
+-`.dir' and `.pag' files.)
+-.PP
+-Once open,
+-the data stored under a key is
+-accessed by
+-.I fetch
+-and data is placed under a key
+-by
+-.IR store .
+-A key (and its associated contents)
+-is deleted by
+-.IR delete .
+-A linear pass through all keys in a database
+-may be made,
+-in an (apparently) random order,
+-by use of
+-.I firstkey
+-and
+-.IR nextkey .
+-.I Firstkey
+-will return the first key
+-in the database.
+-With any key
+-.I nextkey
+-will return the next key in the database.
+-This code will traverse the data base:
+-.PP
+-      for(key=firstkey(); key.dptr!=NULL; key=nextkey(key))
+-.SH DIAGNOSTICS
+-All functions that return an
+-.I int
+-indicate errors with negative values.
+-A zero return indicates ok.
+-Routines that return a
+-.I datum
+-indicate errors with a null (0)
+-.I dptr.
+-.SH BUGS
+-The
+-`.pag'
+-file will contain holes so
+-that its apparent size is about
+-four times its actual content.
+-Older UNIX systems may create real
+-file blocks for these holes when touched.
+-These files cannot be copied
+-by normal means (cp, cat, tp, tar, ar)
+-without filling in the holes.
+-.PP
+-.I Dptr
+-pointers returned
+-by these subroutines
+-point into static storage
+-that is changed by subsequent calls.
+-.PP
+-The sum of the sizes of
+-a
+-key/content pair must not exceed
+-the internal block size
+-(currently 512 bytes).
+-Moreover all key/content pairs that hash
+-together must fit on a single block.
+-.I Store
+-will return an error in the event that
+-a disk block fills with inseparable data.
+-.PP
+-.I Delete
+-does not physically reclaim file space,
+-although it does make it available for reuse.
+-.PP
+-The order of keys presented by
+-.I firstkey
+-and
+-.I nextkey
+-depends on a hashing function, not on anything
+-interesting.
+//GO.SYSIN DD dbm.3x
+echo ecvt.3
+sed 's/.//' >ecvt.3 <<'//GO.SYSIN DD ecvt.3'
+-.TH ECVT 3 
+-.SH NAME
+-ecvt, fcvt, gcvt \- output conversion
+-.SH SYNOPSIS
+-.B char *ecvt(value, ndigit, decpt, sign)
+-.br
+-.B double value;
+-.br
+-.B int ndigit, *decpt, *sign;
+-.PP
+-.B char *fcvt(value, ndigit, decpt, sign)
+-.br
+-.B double value;
+-.br
+-.B int ndigit, *decpt, *sign;
+-.PP
+-.B char *gcvt(value, ndigit, buf)
+-.br
+-.B double value;
+-.br
+-.B char *buf;
+-.SH DESCRIPTION
+-.I Ecvt
+-converts the 
+-.I value
+-to a null-terminated string of
+-.I ndigit
+-ASCII digits
+-and returns a pointer thereto.
+-The position of the decimal point relative to the
+-beginning of the string is stored indirectly
+-through
+-.IR decpt ""
+-(negative means to the left of the
+-returned digits).
+-If the sign of the result is negative,
+-the word pointed to by
+-.IR sign ""
+-is non-zero, otherwise
+-it is zero.
+-The low-order digit is rounded.
+-.PP
+-.IR Fcvt " is identical to " "ecvt\fR, except that the correct digit"
+-has been rounded for Fortran F-format output of the number
+-of digits specified by
+-.IR \(*_ndigits .
+-.PP
+-.I Gcvt
+-converts the
+-.I value
+-to a null-terminated ASCII string in
+-.I buf
+-and returns a pointer to 
+-.I buf.
+-It attempts to produce
+-.I ndigit
+-significant digits in Fortran F format if
+-possible, otherwise E format, ready for
+-printing.
+-Trailing zeros may be suppressed.
+-.SH "SEE ALSO"
+-printf(3)
+-.SH BUGS
+-The return values point to static data
+-whose content is overwritten by each call.
+//GO.SYSIN DD ecvt.3
+echo end.3
+sed 's/.//' >end.3 <<'//GO.SYSIN DD end.3'
+-.TH END 3 
+-.SH NAME
+-end, etext, edata \- last locations in program
+-.SH SYNOPSIS
+-.B extern end;
+-.br
+-.B extern etext;
+-.br
+-.B extern edata;
+-.SH DESCRIPTION
+-These names refer neither to routines
+-nor to locations with interesting contents.
+-The address of
+-.I etext
+-is the first address above the program text,
+-.I edata
+-above the initialized data region, and
+-.I end
+-above the uninitialized data region.
+-.PP
+-When execution begins, the program break
+-coincides with
+-.I end,
+-but many functions reset the program break, among them
+-the routines of
+-.IR brk (2),
+-.IR malloc (3), 
+-standard input/output
+-.RI ( stdio (3)),
+-the profile
+-.RB ( \-p )
+-option of 
+-.IR cc (1),
+-etc.
+-The current value of the program break
+-is reliably returned by `sbrk(0)',
+-see
+-.IR brk (2).
+-.SH "SEE ALSO"
+-brk(2), malloc(3)
+//GO.SYSIN DD end.3
+echo exp.3m
+sed 's/.//' >exp.3m <<'//GO.SYSIN DD exp.3m'
+-.TH EXP 3M 
+-.SH NAME
+-exp, log, log10, pow, sqrt \- exponential, logarithm, power, square root
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double exp(x)
+-.br
+-.B double x;
+-.PP
+-.B double log(x)
+-.br
+-.B double x;
+-.PP
+-.B double log10(x)
+-.br
+-.B double x;
+-.PP
+-.B double pow(x, y)
+-.br
+-.B double x, y;
+-.PP
+-.B double sqrt(x)
+-.br
+-.B double x;
+-.SH DESCRIPTION
+-.I Exp
+-returns the exponential function of 
+-.I x.
+-.PP
+-.I Log
+-returns the natural logarithm of 
+-.IR x ;
+-.I log10
+-returns the base 10 logarithm.
+-.PP
+-.I Pow
+-returns
+-.I  x\u\s8y\s10\d.
+-.PP
+-.I Sqrt
+-returns the square root of 
+-.I x.
+-.SH SEE ALSO
+-hypot(3),
+-sinh(3),
+-intro(2)
+-.SH DIAGNOSTICS
+-.I Exp
+-and
+-.I pow
+-return a huge value when the correct value would
+-overflow;
+-.I errno
+-is set to ERANGE.
+-.I Pow
+-returns 0 and sets
+-.I errno
+-to
+-EDOM when the second argument is negative and non-integral and
+-when
+-both arguments are 0.
+-.PP
+-.I Log
+-returns 0 when
+-.I x
+-is zero or negative;
+-.I errno
+-is set to EDOM.
+-.PP
+-.I Sqrt
+-returns 0 when 
+-.I x
+-is negative;
+-.I errno
+-is set to EDOM.
+//GO.SYSIN DD exp.3m
+echo fclose.3s
+sed 's/.//' >fclose.3s <<'//GO.SYSIN DD fclose.3s'
+-.TH FCLOSE 3S 
+-.SH NAME
+-fclose, fflush \- close or flush a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B fclose(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B fflush(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Fclose
+-causes any buffers for the named
+-.I stream
+-to be emptied, and the file to be closed.
+-Buffers allocated by the standard input/output system
+-are freed.
+-.PP
+-.I Fclose
+-is performed automatically upon
+-calling
+-.IR  exit (2).
+-.PP
+-.I Fflush
+-causes any buffered data for the named output
+-.I stream
+-to be written to that file.
+-The stream remains open.
+-.SH "SEE ALSO"
+-close(2),
+-fopen(3),
+-setbuf(3)
+-.SH DIAGNOSTICS
+-These routines return
+-.SM
+-.B EOF
+-if
+-.I stream
+-is not associated with an output file, or
+-if buffered data cannot be transferred to that file.
+//GO.SYSIN DD fclose.3s
+echo ferror.3s
+sed 's/.//' >ferror.3s <<'//GO.SYSIN DD ferror.3s'
+-.TH FERROR 3S 
+-.SH NAME
+-feof, ferror, clearerr, fileno \- stream status inquiries
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B feof(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B ferror(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream
+-.PP
+-.B clearerr(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream
+-.PP
+-.B fileno(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Feof
+-returns non-zero when end of file is read on the named input
+-.I stream,
+-otherwise zero.
+-.PP
+-.I Ferror
+-returns non-zero when an error has occurred reading or writing
+-the named
+-.I stream,
+-otherwise zero.
+-Unless cleared by
+-.I clearerr,
+-the error indication lasts until
+-the stream is closed.
+-.PP
+-.I Clrerr
+-resets the error indication on the named
+-.I stream.
+-.PP
+-.I Fileno
+-returns the integer file descriptor
+-associated with the
+-.I stream,
+-see
+-.IR  open (2).
+-.PP
+-These functions
+-are implemented as macros;
+-they cannot be redeclared.
+-.SH "SEE ALSO"
+-fopen(3), open(2)
+//GO.SYSIN DD ferror.3s
+echo floor.3m
+sed 's/.//' >floor.3m <<'//GO.SYSIN DD floor.3m'
+-.TH FLOOR 3M 
+-.SH NAME
+-fabs, floor, ceil \- absolute value, floor, ceiling functions
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double floor(x)
+-.br
+-.B double x;
+-.PP
+-.B double ceil(x)
+-.br
+-.B double x;
+-.PP
+-.B double fabs(x)
+-.br
+-.B double(x);
+-.SH DESCRIPTION
+-.I Fabs
+-returns the absolute value
+-.RI | \|x\| |.
+-.PP
+-.I Floor
+-returns the
+-largest integer
+-not greater than
+-.IR x .
+-.PP
+-.I Ceil
+-returns the
+-smallest integer
+-not less than
+-.IR x .
+-.SH SEE ALSO
+-abs(3)
+//GO.SYSIN DD floor.3m
+echo fopen.3s
+sed 's/.//' >fopen.3s <<'//GO.SYSIN DD fopen.3s'
+-.TH FOPEN 3S 
+-.SH NAME
+-fopen, freopen, fdopen \- open a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.SM
+-.B FILE
+-.B *fopen(filename, type)
+-.br
+-.B char *filename, *type;
+-.PP
+-.SM
+-.B FILE
+-.B *freopen(filename, type, stream)
+-.br
+-.B char *filename, *type;
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.SM
+-.B FILE
+-.B *fdopen(fildes, type)
+-.br
+-.B char *type;
+-.SH DESCRIPTION
+-.I Fopen
+-opens the file named by
+-.I filename
+-and associates a stream with it.
+-.I Fopen
+-returns a pointer to be used to identify
+-the stream in subsequent operations.
+-.PP
+-.I Type
+-is a character string having one of the following values:
+-.TP 5
+-"r"
+-open for reading
+-.ns
+-.TP 5
+-"w"
+-create for writing
+-.ns
+-.TP 5
+-"a"
+-append: open for writing at end
+-of file, or create for writing
+-.PP
+-.I Freopen
+-substitutes the named file in place
+-of the open
+-.IR stream .
+-It returns the original value of
+-.IR stream .
+-The original stream is closed.
+-.PP
+-.I Freopen
+-is typically used to attach the preopened
+-constant names,
+-.B stdin, stdout, stderr,
+-to specified files.
+-.PP
+-.I Fdopen
+-associates a stream with a file descriptor obtained from
+-.I open, dup, creat,
+-or
+-.IR pipe (2).
+-The
+-.I type
+-of the stream must agree with the mode of the open file.
+-.SH "SEE ALSO"
+-open(2),
+-fclose(3)
+-.SH DIAGNOSTICS
+-.I Fopen
+-and 
+-.I freopen
+-return the pointer
+-.SM
+-.B NULL
+-if
+-.I filename
+-cannot be accessed.
+-.SH BUGS
+-.I Fdopen
+-is not portable to systems other than UNIX.
+//GO.SYSIN DD fopen.3s
+echo fread.3s
+sed 's/.//' >fread.3s <<'//GO.SYSIN DD fread.3s'
+-.TH FREAD 3S 
+-.SH NAME
+-fread, fwrite \- buffered binary input/output
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B fread(ptr, sizeof(*ptr), nitems, stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B fwrite(ptr, sizeof(*ptr), nitems, stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Fread
+-reads, into a block beginning at
+-.I ptr,
+-.I nitems
+-of data of the type of
+-.I *ptr
+-from the named input
+-.IR stream .
+-It returns the number of items actually read.
+-.PP
+-.I Fwrite
+-appends at most
+-.I nitems
+-of data of the type of
+-.I *ptr
+-beginning at
+-.I ptr
+-to the named output
+-.IR stream .
+-It returns the number of items actually written.
+-.SH "SEE ALSO"
+-read(2), write(2),
+-fopen(3),
+-getc(3), putc(3),
+-gets(3), puts(3),
+-printf(3), scanf(3)
+-.SH DIAGNOSTICS
+-.I Fread
+-and
+-.I fwrite
+-return
+-0
+-upon end of file or error.
+//GO.SYSIN DD fread.3s
+echo frexp.3
+sed 's/.//' >frexp.3 <<'//GO.SYSIN DD frexp.3'
+-.TH FREXP 3
+-.SH NAME
+-frexp, ldexp, modf \- split into mantissa and exponent
+-.SH SYNOPSIS
+-.B double frexp(value, eptr)
+-.br
+-.B double value;
+-.br
+-.B int *eptr;
+-.PP
+-.B double ldexp(value, exp)
+-.br
+-.B double value;
+-.PP
+-.B double modf(value, iptr)
+-.br
+-.B double value, *iptr;
+-.SH DESCRIPTION
+-.I Frexp
+-returns the mantissa of a double 
+-.I value
+-as a double quantity,
+-.I x,
+-of magnitude less than 1
+-and stores an integer 
+-.I n
+-such that
+-.I value
+-=
+-.IR x *2** n
+-indirectly through 
+-.I eptr.
+-.PP
+-.I Ldexp
+-returns the quantity
+-.IR value *2** exp.
+-.PP
+-.I Modf
+-returns the positive fractional part of
+-.I value
+-and stores the integer part indirectly
+-through 
+-.I iptr.
+//GO.SYSIN DD frexp.3
+echo fseek.3s
+sed 's/.//' >fseek.3s <<'//GO.SYSIN DD fseek.3s'
+-.TH FSEEK 3S 
+-.SH NAME
+-fseek, ftell, rewind \- reposition a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B fseek(stream, offset, ptrname)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.br
+-.B long offset;
+-.PP
+-.B long ftell(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B rewind(stream)
+-.SH DESCRIPTION
+-.I Fseek
+-sets the position of the next input or output
+-operation on the
+-.IR stream .
+-The new position is at the signed distance
+-.I offset
+-bytes
+-from the beginning, the current position, or the end of the file,
+-according as 
+-.I ptrname
+-has the value 0, 1, or 2.
+-.PP
+-.I Fseek
+-undoes any effects of
+-.IR  ungetc (3).
+-.PP
+-.I Ftell
+-returns the current value of the offset relative to the beginning
+-of the file associated with the named
+-.IR stream .
+-It is measured in bytes on UNIX;
+-on some other systems it is a magic cookie,
+-and the only foolproof way to obtain an 
+-.I offset
+-for
+-.IR fseek .
+-.PP
+-.I Rewind(stream)
+-is equivalent to
+-.I "fseek(stream, 0L, 0)."
+-.SH "SEE ALSO"
+-lseek(2),
+-fopen(3)
+-.SH DIAGNOSTICS
+-.I Fseek
+-returns \-1 for improper seeks.
+//GO.SYSIN DD fseek.3s
+echo getc.3s
+sed 's/.//' >getc.3s <<'//GO.SYSIN DD getc.3s'
+-.TH GETC 3S 
+-.SH NAME
+-getc, getchar, fgetc, getw \- get character or word from stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B int getc(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B int getchar()
+-.PP 
+-.B int fgetc(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B int getw(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Getc
+-returns the next character from the named input
+-.IR stream .
+-.PP
+-.I Getchar()
+-is identical to 
+-.IR getc(stdin) .
+-.PP
+-.I Fgetc
+-behaves like 
+-.I getc,
+-but is a genuine function, not a macro;
+-it may be used to save object text.
+-.PP
+-.I Getw
+-returns the next
+-word from the named input
+-.IR stream .
+-It returns the constant
+-.SM
+-.B EOF
+-upon end of file or error, but since that is a good
+-integer value,
+-.I feof
+-and
+-.IR  ferror (3)
+-should be used to check the success of
+-.IR getw .
+-.I Getw
+-assumes no special alignment in the file.
+-.SH "SEE ALSO"
+-fopen(3), putc(3),
+-gets(3), scanf(3),
+-fread(3),
+-ungetc(3)
+-.SH DIAGNOSTICS
+-These functions return the integer constant
+-.SM
+-.B EOF
+-at end of file or upon read error.
+-.PP
+-A stop with message,
+-`Reading bad file', means an attempt has been made to
+-read from a stream that has not been opened for
+-reading by
+-.IR fopen .
+-.SH BUGS
+-The end-of-file return from
+-.I getchar
+-is incompatible with that in UNIX editions 1-6.
+-.PP
+-Because it is implemented as a macro,
+-.I getc
+-treats a
+-.I stream
+-argument with side effects incorrectly.
+-In particular,
+-`getc(*f++);'
+-doesn't work sensibly.
+//GO.SYSIN DD getc.3s
+echo getenv.3
+sed 's/.//' >getenv.3 <<'//GO.SYSIN DD getenv.3'
+-.TH GETENV 3
+-.SH NAME
+-getenv \- value for environment name
+-.SH SYNOPSIS
+-.B char *getenv(name)
+-.br
+-.B char *name;
+-.SH DESCRIPTION
+-.I Getenv
+-.a
+-searches the environment list
+-(see
+-.IR environ (5))
+-for a string of the form
+-.IB name = value
+-and returns
+-.I value
+-if such a string is present, otherwise 0 (NULL).
+-.SH SEE ALSO
+-environ(5), exec(2)
+//GO.SYSIN DD getenv.3
+echo getgrent.3
+sed 's/.//' >getgrent.3 <<'//GO.SYSIN DD getgrent.3'
+-.TH GETGRENT 3 
+-.SH NAME
+-getgrent, getgrgid, getgrnam, setgrent, endgrent \- get group file entry
+-.SH SYNOPSIS
+-.B #include <grp.h>
+-.PP
+-.B struct group *getgrent();
+-.PP
+-.B struct group *getgrgid(gid) int gid;
+-.PP
+-.B struct group *getgrnam(name) char *name;
+-.PP
+-.B int setgrent();
+-.PP
+-.B int endgrent();
+-.SH DESCRIPTION
+-.I Getgrent,
+-.I getgrgid
+-and
+-.I getgrnam
+-each return pointers
+-to an object
+-with the following structure
+-containing the broken-out
+-fields of a line in the group file.
+-.RS
+-.PP
+-.nf
+-.so /usr/include/grp.h
+-.fi
+-.RE
+-.PP
+-The members of this structure are:
+-.TP
+-gr_name
+-The name of the group.
+-.br
+-.ns
+-.TP
+-gr_passwd
+-The encrypted password of the group.
+-.br
+-.ns
+-.TP
+-gr_gid
+-The numerical group-ID.
+-.br
+-.ns
+-.TP
+-gr_mem
+-Null-terminated vector
+-of pointers to the individual
+-member names.
+-.PP
+-.I Getgrent
+-simply reads the next
+-line while
+-.I getgrgid
+-and
+-.I getgrnam
+-search until a matching
+-.I gid
+-or
+-.I name
+-is found
+-(or until EOF is encountered).
+-Each routine picks up
+-where the others leave off
+-so successive calls may be used
+-to search the entire file.
+-.PP
+-A call to
+-.I setgrent
+-has the effect of rewinding
+-the group file
+-to allow
+-repeated searches.
+-.I Endgrent
+-may be called to
+-close the group file
+-when processing is complete.
+-.SH FILES
+-/etc/group
+-.SH "SEE ALSO"
+-getlogin(3), getpwent(3), group(5)
+-.SH DIAGNOSTICS
+-A null pointer
+-(0) is returned on EOF or error.
+-.SH BUGS
+-All information
+-is contained in a static area
+-so it must be copied if it is
+-to be saved.
+//GO.SYSIN DD getgrent.3
+echo getlogin.3
+sed 's/.//' >getlogin.3 <<'//GO.SYSIN DD getlogin.3'
+-.TH GETLOGIN 3 
+-.SH NAME
+-getlogin \- get login name
+-.SH SYNOPSIS
+-.B char *getlogin();
+-.SH DESCRIPTION
+-.I Getlogin
+-returns a pointer to
+-the login name
+-as found in
+-.IR /etc/utmp .
+-It may be used
+-in conjunction
+-with
+-.I getpwnam
+-to locate the correct
+-password file entry
+-when the same userid
+-is shared by several
+-login names.
+-.PP
+-If
+-.I getlogin
+-is called within a process
+-that is not attached to a
+-typewriter, it returns NULL.
+-The correct procedure
+-for determining the login name
+-is to first call
+-.I getlogin
+-and if it fails,
+-to call
+-.IR getpwuid .
+-.SH FILES
+-/etc/utmp
+-.SH "SEE ALSO"
+-getpwent(3), getgrent(3), utmp(5)
+-.SH DIAGNOSTICS
+-Returns NULL (0) if name not found.
+-.SH BUGS
+-The return values point to static data
+-whose content is overwritten by each call.
+//GO.SYSIN DD getlogin.3
+echo getpass.3
+sed 's/.//' >getpass.3 <<'//GO.SYSIN DD getpass.3'
+-.TH GETPASS 3 
+-.SH NAME
+-getpass \- read a password
+-.SH SYNOPSIS
+-.B char *getpass(prompt)
+-.br
+-.B char *prompt;
+-.SH DESCRIPTION
+-.I Getpass
+-reads a password from the file
+-.IR /dev/tty ,
+-or if that cannot be opened, from the standard input,
+-after prompting with the null-terminated string
+-.I prompt
+-and disabling echoing.
+-A pointer is returned to a null-terminated string
+-of at most 8 characters.
+-.SH FILES
+-/dev/tty
+-.SH "SEE ALSO"
+-crypt(3)
+-.SH BUGS
+-The return value points to static data
+-whose content is overwritten by each call.
+//GO.SYSIN DD getpass.3
+echo getpw.3
+sed 's/.//' >getpw.3 <<'//GO.SYSIN DD getpw.3'
+-.TH GETPW 3  deprecated
+-.SH NAME
+-getpw \- get name from UID
+-.SH SYNOPSIS
+-.B getpw(uid, buf)
+-.br
+-.B char *buf;
+-.SH DESCRIPTION
+-.I Getpw
+-searches the password file for
+-the (numerical)
+-.IR uid ", and fills in " "buf"
+-with the corresponding line;
+-it returns non-zero if
+-.IR uid ""
+-could not
+-be found.
+-The line is null-terminated.
+-.SH FILES
+-/etc/passwd
+-.SH "SEE ALSO"
+-getpwent(3),
+-passwd(5)
+-.SH DIAGNOSTICS
+-Non-zero
+-return on error.
+//GO.SYSIN DD getpw.3
+echo getpwent.3
+sed 's/.//' >getpwent.3 <<'//GO.SYSIN DD getpwent.3'
+-.TH GETPWENT 3 
+-.SH NAME
+-getpwent, getpwuid, getpwnam, setpwent, endpwent
+-\- get password file entry
+-.SH SYNOPSIS
+-.B #include <pwd.h>
+-.PP
+-.B struct passwd *getpwent();
+-.PP
+-.B struct passwd *getpwuid(uid) int uid;
+-.PP
+-.B struct passwd *getpwnam(name) char *name;
+-.PP
+-.B int setpwent();
+-.PP
+-.B int endpwent();
+-.SH DESCRIPTION
+-.I Getpwent,
+-.I getpwuid
+-and
+-.I getpwnam
+-each return a pointer to an object with the
+-following structure
+-containing the broken-out
+-fields of a line in the password file.
+-.RS
+-.PP
+-.nf
+-.so /usr/include/pwd.h
+-.ft R
+-.ad
+-.fi
+-.RE
+-.PP
+-The fields
+-.I pw_quota
+-and
+-.I pw_comment
+-are unused; the others have meanings described in
+-.IR passwd (5).
+-.PP
+-.I Getpwent
+-reads the next
+-line (opening the file if necessary);
+-.I setpwent
+-rewinds the file;
+-.I endpwent
+-closes it.
+-.PP
+-.I Getpwuid
+-and
+-.I getpwnam
+-search from the beginning until a matching
+-.I uid
+-or
+-.I name
+-is found
+-(or until EOF is encountered).
+-.SH FILES
+-/etc/passwd
+-.SH "SEE ALSO"
+-getlogin(3), getgrent(3), passwd(5)
+-.SH DIAGNOSTICS
+-Null pointer
+-(0) returned on EOF or error.
+-.SH BUGS
+-All information
+-is contained in a static area
+-so it must be copied if it is
+-to be saved.
+-.br
+//GO.SYSIN DD getpwent.3
+echo gets.3s
+sed 's/.//' >gets.3s <<'//GO.SYSIN DD gets.3s'
+-.TH GETS 3S 
+-.SH NAME
+-gets, fgets \- get a string from a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B char *gets(s)
+-.br
+-.B char *s;
+-.PP
+-.B char *fgets(s, n, stream)
+-.br
+-.B char *s;
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Gets
+-reads a string into
+-.I s
+-from the standard input stream
+-.B stdin.
+-The string is terminated by a newline
+-character, which is replaced in
+-.I s
+-by a null character.
+-.I Gets
+-returns its argument.
+-.PP
+-.I Fgets
+-reads 
+-.IR n \-1
+-characters, or up to a newline
+-character, whichever comes first,
+-from the
+-.I stream
+-into the string
+-.IR s .
+-The last character read into
+-.I s
+-is followed by a null character.
+-.I Fgets
+-returns its first argument.
+-.SH "SEE ALSO"
+-puts(3),
+-getc(3), scanf(3), fread(3),
+-ferror(3)
+-.SH DIAGNOSTICS
+-.I Gets
+-and
+-.I fgets
+-return the constant pointer 
+-.SM
+-.B NULL
+-upon end of file or error.
+-.SH BUGS
+-.I Gets
+-deletes a newline,
+-.I fgets
+-keeps it,
+-all in the name of backward compatibility.
+//GO.SYSIN DD gets.3s
+echo hypot.3m
+sed 's/.//' >hypot.3m <<'//GO.SYSIN DD hypot.3m'
+-.TH HYPOT 3M 
+-.SH NAME
+-hypot, cabs \- euclidean distance
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double hypot(x, y)
+-.br
+-.B double x, y;
+-.PP
+-.B double cabs(z)
+-.br
+-.B struct { double x, y;} z;
+-.SH DESCRIPTION
+-.I Hypot
+-and
+-.I cabs
+-return
+-.PP
+-.IP "" 15n
+-sqrt(x*x + y*y),
+-.LP
+-taking precautions against unwarranted overflows.
+-.SH SEE ALSO
+-exp(3) for
+-.I sqrt
+//GO.SYSIN DD hypot.3m
+echo intro.3
+sed 's/.//' >intro.3 <<'//GO.SYSIN DD intro.3'
+-.TH INTRO 3
+-.SH NAME
+-intro \- introduction to library functions
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B #include <math.h>
+-.SH DESCRIPTION
+-This section describes functions that may be found
+-in various libraries, other than those functions
+-that directly invoke UNIX system primitives,
+-which are described in section 2.
+-Functions are divided into various libraries distinguished
+-by the section number at the top of the page:
+-.TP 6n
+-(3)
+-These functions, together with those of section 2 and those
+-marked (3S), constitute library
+-.I libc,
+-which is automatically loaded by the C compiler
+-.IR cc (1)
+-and the Fortran compiler
+-.IR f77 (1).
+-The link editor
+-.IR ld (1)
+-searches this library under the `\-lc' option.
+-Declarations for some of these functions may be obtained
+-from include files indicated on the appropriate pages.
+-.TP
+-(3M)
+-These functions constitute the math library,
+-.I libm.
+-They are automatically loaded as needed by the Fortran compiler
+-.IR f77 (1).
+-The link editor searches this library under the `\-lm' option.
+-Declarations for these functions may be obtained from
+-the include file <math.h>.
+-.TP 
+-(3S)
+-These functions constitute the
+-`standard I/O package',
+-see
+-.IR stdio (3).
+-These functions are in the library
+-.I libc
+-already mentioned.
+-Declarations for these functions may be obtained from
+-the include file <stdio.h>.
+-.TP
+-(3X)
+-Various
+-specialized libraries have not been given distinctive
+-captions.
+-The files in which these libraries are found are named
+-on the appropriate pages.
+-.SH FILES
+-/lib/libc.a
+-.br
+-/lib/libm.a, /usr/lib/libm.a (one or the other)
+-.SH SEE ALSO
+-stdio(3),
+-nm(1), ld(1), cc(1), f77(1), intro(2)
+-.SH DIAGNOSTICS
+-Functions in the math library (3M) may return
+-conventional values when the function is undefined for the
+-given arguments or when the value is not representable.
+-In these cases the external variable
+-.I errno
+-(see
+-.IR intro (2))
+-is set to the value EDOM
+-or ERANGE.
+-The values of EDOM and ERANGE are defined in
+-the include file
+-.I <math.h>.
+-.SH ASSEMBLER
+-In assembly language these functions may be accessed
+-by simulating the C calling sequence.
+-For example,
+-.IR ecvt (3)
+-might be called this way:
+-.IP ""
+-.globl        _ecvt
+-.nf
+-setd
+-mov   $sign,\-(sp)
+-mov   $decpt,\-(sp)
+-mov   ndigit,\-(sp)
+-movf  value,\-(sp)
+-jsr   pc,_ecvt
+-add   $14.,sp
+-.fi
+//GO.SYSIN DD intro.3
+echo j0.3m
+sed 's/.//' >j0.3m <<'//GO.SYSIN DD j0.3m'
+-.TH J0 3M 
+-.SH NAME
+-j0, j1, jn, y0, y1, yn \- bessel functions
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double j0(x)
+-.br
+-.B double x;
+-.PP
+-.B double j1(x)
+-.br
+-.B double x;
+-.PP
+-.B double jn(n, x);
+-.br
+-.B double x;
+-.PP
+-.B double y0(x)
+-.br
+-.B double x;
+-.PP
+-.B double y1(x)
+-.br
+-.B double x;
+-.PP
+-.B double yn(n, x)
+-.br
+-.B double x;
+-.SH DESCRIPTION
+-These functions calculate Bessel functions of the first
+-and second kinds for real arguments and integer orders.
+-.SH DIAGNOSTICS
+-Negative arguments cause
+-.I y0, y1,
+-and
+-.I yn
+-to return a huge negative value
+-and set
+-.I errno
+-to EDOM.
+//GO.SYSIN DD j0.3m
+echo l3tol.3
+sed 's/.//' >l3tol.3 <<'//GO.SYSIN DD l3tol.3'
+-.TH L3TOL 3 
+-.SH NAME
+-l3tol, ltol3 \- convert between 3-byte integers and long integers
+-.SH SYNOPSIS
+-.B l3tol(lp, cp, n)
+-.br
+-.B long *lp;
+-.br
+-.B char *cp;
+-.PP
+-.B ltol3(cp, lp, n)
+-.br
+-.B char *cp;
+-.br
+-.B long *lp;
+-.SH DESCRIPTION
+-.I L3tol
+-converts a list of
+-.I n
+-three-byte integers packed into a character string
+-pointed to by 
+-.I cp
+-into a list of long integers pointed to by
+-.IR lp .
+-.PP
+-.I Ltol3
+-performs the reverse conversion from long integers
+-.RI ( lp )
+-to three-byte integers
+-.RI ( cp ).
+-.PP
+-These functions are useful for file-system maintenance;
+-disk addresses are three bytes long.
+-.SH SEE ALSO
+-filsys(5)
+//GO.SYSIN DD l3tol.3
+echo malloc.3
+sed 's/.//' >malloc.3 <<'//GO.SYSIN DD malloc.3'
+-.TH MALLOC 3 
+-.SH NAME
+-malloc, free, realloc, calloc \- main memory allocator
+-.SH SYNOPSIS
+-.B char *malloc(size)
+-.br
+-.B unsigned size;
+-.PP
+-.B free(ptr)
+-.br
+-.B char *ptr;
+-.PP
+-.B char *realloc(ptr, size)
+-.br
+-.B char *ptr;
+-.br
+-.B unsigned size;
+-.PP
+-.B char *calloc(nelem, elsize)
+-.br
+-.B unsigned nelem, elsize;
+-.SH DESCRIPTION
+-.I Malloc
+-and
+-.I free
+-provide a simple general-purpose memory allocation package.
+-.I Malloc
+-returns a pointer to a block of at least
+-.I size
+-bytes beginning on a word boundary.
+-.PP
+-The argument to
+-.I free
+-is a pointer to a block previously allocated by
+-.IR malloc ;
+-this space is made available for further allocation,
+-but its contents are left undisturbed.
+-.PP
+-Needless to say, grave disorder will result if the space
+-assigned by
+-.I malloc
+-is overrun or if some random number is handed to
+-.IR free .
+-.PP
+-.I Malloc
+-allocates the first big enough contiguous reach of
+-free space
+-found in a circular search from the last 
+-block allocated or freed,
+-coalescing adjacent free blocks as it searches.
+-It calls
+-.I sbrk
+-(see
+-.IR break (2))
+-to get more memory from the system when there is no
+-suitable space already free.
+-.PP
+-.I Realloc
+-changes the size of the block pointed to by
+-.I ptr
+-to
+-.I size
+-bytes and returns a pointer to the (possibly moved)
+-block.
+-The contents will be unchanged up to the
+-lesser of the new and old sizes.
+-.PP
+-.I Realloc
+-also works if
+-.I ptr
+-points to a block freed since the last call of
+-.I malloc, realloc
+-or
+-.IR calloc ;
+-thus sequences of
+-.I free, malloc
+-and
+-.I realloc
+-can exploit the search strategy of
+-.I malloc
+-to do storage compaction.
+-.PP
+-.I Calloc
+-allocates space for
+-an array of
+-.I nelem
+-elements of size
+-.I elsize.
+-The space is initialized to zeros.
+-.PP
+-Each of the allocation routines returns a pointer
+-to space suitably aligned (after possible pointer coercion)
+-for storage of any type of object.
+-.SH DIAGNOSTICS
+-.I Malloc, realloc
+-and
+-.I calloc
+-return a null pointer (0) if there is no available memory
+-or if the arena has been detectably corrupted by storing outside the bounds
+-of a block.
+-.I Malloc
+-may be recompiled to check the arena very stringently
+-on every transaction;
+-see the source code.
+-.SH BUGS
+-When
+-.I realloc
+-returns 0,
+-the block
+-pointed to by
+-.I ptr
+-may be destroyed.
+//GO.SYSIN DD malloc.3
+echo mktemp.3
+sed 's/.//' >mktemp.3 <<'//GO.SYSIN DD mktemp.3'
+-.TH MKTEMP 3 
+-.SH NAME
+-mktemp \- make a unique file name
+-.SH SYNOPSIS
+-.B char *mktemp(template)
+-.br
+-.B char *template;
+-.SH DESCRIPTION
+-.I Mktemp
+-replaces
+-.I template
+-by a unique file name, and returns the
+-address of the template.
+-The template should look like a file name with six trailing
+-X's, which will be replaced with the
+-current process id and a unique letter.
+-.SH "SEE ALSO"
+-getpid(2)
+//GO.SYSIN DD mktemp.3
+echo monitor.3
+sed 's/.//' >monitor.3 <<'//GO.SYSIN DD monitor.3'
+-.TH MONITOR 3 
+-.SH NAME
+-monitor \- prepare execution profile
+-.SH SYNOPSIS
+-.B monitor(lowpc, highpc, buffer, bufsize, nfunc)
+-.br
+-.B
+-int (*lowpc)( ), (*highpc)( );
+-.br
+-.B short buffer[ ];
+-.SH DESCRIPTION
+-An executable program created by
+-`cc \-p' automatically includes calls for
+-.I monitor
+-with default parameters;
+-.I monitor
+-needn't be called explicitly
+-except to gain fine control over profiling.
+-.PP
+-.I Monitor
+-is an interface to
+-.IR profil (2).
+-.I Lowpc
+-and
+-.I highpc
+-are the addresses of two functions;
+-.I buffer
+-is the address of a (user supplied)
+-array of
+-.I bufsize
+-short integers.
+-.I Monitor
+-arranges to record a histogram of
+-periodically sampled values of the program counter,
+-and of counts of calls
+-of certain functions, in the buffer.
+-The lowest address sampled
+-is that of
+-.I lowpc
+-and the highest is
+-just below
+-.IR highpc .
+-At most
+-.I nfunc
+-call counts can be kept; only calls of functions
+-compiled with the profiling option
+-.B \-p
+-of
+-.IR cc (1)
+-are recorded.
+-For the results to be significant,
+-especially where there are small, heavily
+-used routines,
+-it is suggested that the buffer be no more
+-than a few times smaller than the range
+-of locations sampled.
+-.PP
+-To profile the entire program,
+-it is sufficient to use
+-.PP
+-      extern etext();
+-.br
+-      ...
+-.br
+-      monitor((int)2, etext, buf, bufsize, nfunc);
+-.PP
+-.I Etext
+-lies just above all the
+-program text, see
+-.IR end (3).
+-.PP
+-To stop execution monitoring and write the results
+-on the file
+-.I mon.out,
+-use
+-.PP
+-      monitor(0);
+-.LP
+-then
+-.IR prof (1)
+-can be used
+-to examine the results.
+-.SH FILES
+-mon.out
+-.SH "SEE ALSO"
+-prof(1), profil(2), cc(1)
+//GO.SYSIN DD monitor.3
+echo mp.3x
+sed 's/.//' >mp.3x <<'//GO.SYSIN DD mp.3x'
+-.TH MP 3X
+-.SH NAME
+-itom, madd, msub, mult, mdiv, min, mout,
+-pow, gcd, rpow \- multiple precision integer arithmetic
+-.SH SYNOPSIS
+-.nf
+-.B "typedef struct { int len; short *val; } mint;"
+-.PP
+-.PP
+-.B madd(a, b, c)
+-.B msub(a, b, c)
+-.B mult(a, b, c)
+-.B mdiv(a, b, q, r)
+-.B min(a)
+-.B mout(a)
+-.B pow(a, b, m, c)
+-.B gcd(a, b, c)
+-.B rpow(a, b, c)
+-.B msqrt(a, b, r)
+-.B mint *a, *b, *c, *m, "*q, *r;"
+-.PP
+-.B
+-.B sdiv(a, n, q, r)
+-.B mint *a, *q;
+-.B short *r;
+-.PP
+-.B mint *itom(n)
+-.SH DESCRIPTION
+-These routines perform arithmetic on integers of
+-arbitrary length.
+-The integers are stored using the defined type
+-.I mint.
+-Pointers to
+-a
+-.I mint
+-should be initialized using the function
+-.IR itom ,
+-which sets the initial value to
+-.IR n .
+-After that space is managed automatically by the routines.
+-.PP
+-.IR madd , " msub" , " mult" ,
+-assign to their third arguments the sum, difference, and
+-product, respectively, of their first two arguments.
+-.I mdiv
+-assigns the quotient and remainder, respectively,
+-to its third and fourth arguments.
+-.I sdiv
+-is like
+-.I mdiv
+-except that the divisor is an ordinary integer.
+-.I msqrt
+-produces the square root and remainder of its first argument.
+-.I rpow
+-calculates
+-.I a
+-raised to the power
+-.IR b ,
+-while
+-.I pow
+-calculates this reduced modulo
+-.IR m .
+-.IR min " and" mout
+-do decimal input and output.
+-.PP
+-The functions are obtained with the
+-loader option
+-.IR -lmp .
+-.SH DIAGNOSTICS
+-Illegal operations and running out of memory
+-produce messages and core images.
+//GO.SYSIN DD mp.3x
+echo nlist.3
+sed 's/.//' >nlist.3 <<'//GO.SYSIN DD nlist.3'
+-.TH NLIST 3 
+-.SH NAME
+-nlist \- get entries from name list
+-.SH SYNOPSIS
+-.B #include <a.out.h>
+-.br
+-.B nlist(filename, nl)
+-.br
+-.B char *filename;
+-.DT
+-.nf
+-.ft 3
+-struct nlist nl[ ];
+-.fi
+-.SH DESCRIPTION
+-.I Nlist
+-examines the name list in
+-the given executable output file
+-and selectively extracts a
+-list of values.
+-The name list consists of
+-an array of structures containing names,
+-types and values.
+-The list is terminated with a null name.
+-Each name is looked up in the name list of
+-the file.
+-If the name is found, the type and value of the
+-name are inserted in the next two fields.
+-If the name is not found, both entries are set to 0.
+-See
+-.IR a.out (5)
+-for the structure declaration.
+-.PP
+-This subroutine is useful for
+-examining the system name list kept in
+-the file
+-.BR /unix .
+-In this way programs can obtain system addresses
+-that are up to date.
+-.SH "SEE ALSO"
+-a.out(5)
+-.SH DIAGNOSTICS
+-All
+-type entries are set to 0 if the file cannot be found
+-or if it is not a valid namelist.
+//GO.SYSIN DD nlist.3
+echo perror.3
+sed 's/.//' >perror.3 <<'//GO.SYSIN DD perror.3'
+-.TH PERROR 3 
+-.SH NAME
+-perror, sys_errlist, sys_nerr \- system error messages
+-.SH SYNOPSIS
+-.B perror(s)
+-.br
+-.B char *s;
+-.PP
+-.B int sys_nerr;
+-.br
+-.B char *sys_errlist[];
+-.SH DESCRIPTION
+-.I Perror
+-produces a short error message
+-on the standard error file
+-describing the last error encountered during a call
+-to the system from a C program.
+-First the argument string
+-.I s
+-is printed, then a colon, then the message and a new-line.
+-Most usefully, the argument string is the name
+-of the program which incurred the error.
+-The error number is taken from the external variable
+-.I errno
+-(see
+-.IR intro (2)),
+-which is set when errors occur but not cleared when
+-non-erroneous calls are made.
+-.PP
+-To simplify variant formatting
+-of messages, the vector of message strings
+-.I sys_errlist
+-is provided;
+-.I errno
+-can be used as an index in this table to get the
+-message string without the newline.
+-.I Sys_nerr
+-is the number of messages provided for in the table;
+-it should be checked because new
+-error codes may be added to the system before
+-they are added to the table.
+-.SH "SEE ALSO"
+-intro(2)
+//GO.SYSIN DD perror.3
+echo pkopen.3
+sed 's/.//' >pkopen.3 <<'//GO.SYSIN DD pkopen.3'
+-.TH PKOPEN 3 deprecated
+-.SH NAME
+-pkopen, pkclose, pkread, pkwrite, pkfail \- packet driver simulator
+-.SH SYNOPSIS
+-.B char *pkopen(fd)
+-.PP
+-.B pkclose(ptr)
+-.br
+-.B char *ptr;
+-.PP
+-.B pkread(ptr, buffer, count)
+-.br
+-.B char *ptr, *buffer;
+-.PP
+-.B pkwrite(ptr, buffer, count)
+-.br
+-.B char *ptr, *buffer;
+-.PP
+-.B pkfail()
+-.SH DESCRIPTION
+-These routines are a user-level implementation of the 
+-full-duplex
+-end-to-end communication protocol described in
+-.IR pk (4).
+-If
+-.I fd
+-is a file descriptor open for reading and writing,
+-.I pkopen
+-carries out the initial synchronization and returns an identifying
+-pointer.
+-The pointer
+-is used as the first parameter to
+-.I pkread,
+-.I pkwrite,
+-and
+-.I pkclose.
+-.PP
+-.I Pkread, pkwrite
+-and
+-.I pkclose
+-behave analogously to
+-.I read, write
+-and
+-.IR close (2).
+-However, a write of zero bytes
+-is meaningful and will produce a corresponding
+-read of zero bytes.
+-.SH SEE ALSO
+-pk(4), pkon(2)
+-.SH DIAGNOSTICS
+-.I Pkfail
+-is called upon persistent breakdown of communication.
+-.I Pkfail
+-must be supplied by the user.
+-.PP
+-.I Pkopen
+-returns a null (0) pointer if packet protocol
+-can not be established.
+-.PP
+-.I Pkread
+-returns \-1 on end of file,
+-0 in correspondence with a 0-length write.
+-.SH BUGS
+-This simulation of
+-.IR pk (4)
+-leaves something to be desired
+-in needing special read and write routines, and in
+-not being inheritable across calls of
+-.IR exec (2).
+-Its prime use is on systems that lack
+-.I pk.
+-.br
+-These functions use
+-.IR alarm (2);
+-simultaneous use of
+-.I alarm
+-for other puposes may cause trouble.
+//GO.SYSIN DD pkopen.3
+echo plot.3x
+sed 's/.//' >plot.3x <<'//GO.SYSIN DD plot.3x'
+-.TH PLOT 3X 
+-.SH NAME
+-plot: openpl et al. \- graphics interface
+-.SH SYNOPSIS
+-.B openpl( )
+-.PP
+-.B erase( )
+-.PP
+-.B label(s)
+-.B char s[ ];
+-.PP
+-.B line(x1, y1, x2, y2)
+-.PP
+-.B circle(x, y, r)
+-.PP
+-.B arc(x, y, x0, y0, x1, y1)
+-.PP
+-.B move(x, y)
+-.PP
+-.B cont(x, y)
+-.PP
+-.B point(x, y)
+-.PP
+-.B linemod(s)
+-.B char s[ ];
+-.PP
+-.B space(x0, y0, x1, y1)
+-.PP
+-.B closepl( )
+-.fi
+-.PP
+-.ft R
+-.SH DESCRIPTION
+-These subroutines
+-generate
+-graphic output in a relatively
+-device-independent manner.
+-See
+-.IR  plot (5)
+-for a description
+-of their effect.
+-.I Openpl
+-must be used before any of the others to open the
+-device for writing.
+-.I Closepl
+-flushes the output.
+-.PP
+-String arguments to
+-.I label
+-and
+-.I linemod
+-are null-terminated, and do not contain newlines.
+-.PP
+-Various flavors of these functions exist for different
+-output devices. 
+-They are obtained by the following
+-.IR ld (1)
+-options:
+-.TP 8n
+-.B \-lplot
+-device-independent
+-graphics stream on standard
+-output for 
+-.IR plot (1)
+-filters
+-.br
+-.ns
+-.TP
+-.B \-l300
+-GSI 300 terminal
+-.br
+-.ns
+-.TP
+-.B \-l300s
+-GSI 300S terminal
+-.br
+-.ns
+-.TP
+-.B \-l450
+-DASI 450 terminal
+-.br
+-.ns
+-.TP
+-.B \-l4014
+-Tektronix 4014 terminal
+-.SH "SEE ALSO"
+-plot(5), plot(1), graph(1)
+//GO.SYSIN DD plot.3x
+echo popen.3s
+sed 's/.//' >popen.3s <<'//GO.SYSIN DD popen.3s'
+-.TH POPEN 3S
+-.SH NAME
+-popen, pclose \- initiate I/O to/from a process
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.SM
+-.B FILE
+-.B *popen(command, type)
+-.br
+-.B char *command, *type;
+-.PP
+-.B pclose(stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-The arguments to 
+-.I popen
+-are pointers to null-terminated strings
+-containing respectively a shell command line and an I/O
+-mode, either "r" for reading or "w" for
+-writing.
+-It creates a pipe between
+-the calling process and
+-the command to be executed.
+-The value returned 
+-is a stream pointer that
+-can be used (as appropriate) to write to the standard input
+-of the command or read from its standard output.
+-.PP
+-A stream opened by
+-.I popen
+-should be closed by
+-.I pclose,
+-which waits for the associated process to terminate
+-and returns the exit status of the command.
+-.PP
+-Because open files are shared, a type "r" command
+-may be used as an input filter,
+-and a type "w" as an output filter.
+-.SH "SEE ALSO"
+-pipe(2),
+-fopen(3),
+-fclose(3),
+-system(3),
+-wait(2)
+-.SH DIAGNOSTICS
+-.I Popen
+-returns a null pointer
+-if files or processes cannot be created, or the Shell 
+-cannot be accessed.
+-.PP
+-.I Pclose
+-returns \-1 if
+-.I stream
+-is not associated with a `popened' command.
+-.SH BUGS
+-Buffered reading before opening an input filter
+-may leave the standard input of that filter mispositioned.
+-Similar problems with an output filter may be
+-forestalled by careful buffer flushing, e.g. with
+-.I fflush,
+-see
+-.IR fclose (3).
+//GO.SYSIN DD popen.3s
+echo printf.3s
+sed 's/.//' >printf.3s <<'//GO.SYSIN DD printf.3s'
+-.TH PRINTF 3S 
+-.SH NAME
+-printf, fprintf, sprintf \- formatted output conversion
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B printf(format
+-.RB [ ,
+-arg ] ...
+-.B )
+-.br
+-.B char *format;
+-.PP
+-.B fprintf(stream, format
+-.RB [ ,
+-arg ] ...
+-.B )
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.br
+-.B char *format;
+-.PP
+-.B sprintf(s, format
+-.RB [ ,
+-arg ] ...
+-.B )
+-.br
+-.B char *s, format;
+-.SH DESCRIPTION
+-.I Printf
+-places output on the standard output stream
+-.IR stdout .
+-.I Fprintf
+-places output on the named output
+-.IR stream .
+-.I Sprintf
+-places `output' in the string
+-.I s,
+-followed by the character `\\0'.
+-.PP
+-Each of these functions 
+-converts, formats, and prints its arguments after the first
+-under control of the first argument.
+-The first argument is a character string
+-which contains
+-two types of objects:
+-plain characters, which are simply copied to the
+-output stream,
+-and conversion specifications,
+-each of which causes conversion and printing
+-of the next successive
+-.I arg
+-.IR printf .
+-.PP
+-Each conversion specification is introduced by
+-the character
+-.BR % .
+-Following the
+-.BR % ,
+-there may be
+-.TP
+-\-
+-an optional minus sign `\-' which specifies
+-.I "left adjustment"
+-of the converted value
+-in the
+-indicated field;
+-.TP
+-\-
+-an optional digit string specifying a
+-.I "field width;"
+-if the converted value has fewer characters
+-than the field width
+-it will be blank-padded on the left (or right,
+-if the left-adjustment indicator has been
+-given) to make up the field width;
+-if the field width begins with a zero,
+-zero-padding will be done instead of blank-padding;
+-.TP
+-\-
+-an optional period
+-.RB ` . '
+-which serves to
+-separate the field width from the
+-next digit string;
+-.TP
+-\-
+-an optional digit string
+-specifying a
+-.I precision
+-which specifies
+-the number of digits to appear after the
+-decimal point, for e- and f-conversion,
+-or the maximum number of characters
+-to be printed from a string;
+-.TP
+-\-
+-the character
+-.B l
+-specifying that a following
+-.BR d ,
+-.BR o ,
+-.BR x ,
+-or
+-.B u
+-corresponds to a long integer
+-.I arg.
+-(A capitalized conversion code accomplishes
+-the same thing.)
+-.TP
+-\-
+-a character which indicates the type of
+-conversion to be applied.
+-.PP
+-A field width or precision may be `*' instead of a digit string.
+-In this case an integer
+-.I arg
+-supplies
+-the field width or precision.
+-.PP
+-The conversion characters
+-and their meanings are
+-.TP
+-.B dox
+-The integer
+-.I arg
+-is converted to decimal, octal, or
+-hexadecimal notation respectively.
+-.TP
+-.B f
+-The float or double
+-.I arg
+-is converted to decimal notation
+-in the style `[\fB\-\fR]ddd.ddd'
+-where the number of d's after the decimal point
+-is equal to the precision specification
+-for the argument.
+-If the precision
+-is missing,
+-6 digits are given;
+-if the precision is explicitly 0, no digits and
+-no decimal point are printed.
+-.TP
+-.B e
+-The float or double
+-.I arg
+-is converted in the style
+-`[\fB\-\fR]d\fB.\fRddd\fBe\fR\(+-dd'
+-where there is one digit before the decimal point and
+-the number after is equal to the
+-precision specification for the argument;
+-when the precision is missing,
+-6 digits are produced.
+-.TP
+-.B g
+-The float or double
+-.I arg
+-is printed in style
+-.BR d ,
+-in style
+-.BR f ,
+-or in
+-style
+-.BR e ,
+-whichever gives full precision in minimum space.
+-.TP
+-.B c
+-The character
+-.I arg
+-is printed.
+-Null characters are ignored.
+-.TP
+-.B s
+-.I Arg
+-is taken to be a string (character pointer)
+-and characters from the string are printed until
+-a null character or until
+-the number of characters indicated by the precision
+-specification is reached;
+-however if the precision is 0 or missing
+-all characters up to a null are printed.
+-.TP
+-.B u
+-The unsigned integer
+-.I arg
+-is converted to decimal
+-and printed (the result will be in the
+-range 0 to 65535).
+-.TP
+-.B %
+-Print a `%'; no argument is converted.
+-.PP
+-In no case does a non-existent or small field width
+-cause truncation of a field;
+-padding takes place only if the specified field
+-width exceeds the actual width.
+-Characters generated by
+-.I printf
+-are printed by 
+-.IR putc (3).
+-.PP
+-.B Examples
+-.br
+-To print a date and time in the form `Sunday, July 3, 10:02',
+-where
+-.I weekday
+-and
+-.I month
+-are pointers to null-terminated strings:
+-.RS
+-.HP
+-.nh
+-printf("%s, %s %d, %02d:%02d", weekday, month, day, hour, min);
+-.RE
+-.hy
+-.PP
+-To print
+-.if n pi
+-.if t \(*p
+-to 5 decimals:
+-.IP
+-printf("pi = %.5f", 4*atan(1.0));
+-.SH "SEE ALSO"
+-putc(3),
+-scanf(3),
+-ecvt(3)
+-.SH BUGS
+-Very wide fields (>128 characters) fail.
+//GO.SYSIN DD printf.3s
+echo putc.3s
+sed 's/.//' >putc.3s <<'//GO.SYSIN DD putc.3s'
+-.TH PUTC 3S 
+-.SH NAME
+-putc, putchar, fputc, putw \- put character or word on a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B int putc(c, stream)
+-.br
+-.B char c;
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B putchar(c)
+-.PP
+-.B fputc(c, stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.PP
+-.B putw(w, stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Putc
+-appends the character
+-.I c
+-to the named output
+-.IR stream .
+-It returns the character written.
+-.PP
+-.I Putchar(c)
+-is defined as 
+-.I "putc(c, stdout)."
+-.PP
+-.I Fputc
+-behaves like 
+-.I putc,
+-but is a genuine function rather than a macro.
+-It may be used to save on object text.
+-.PP
+-.I Putw
+-appends word 
+-(i.e.
+-.BR int )
+-.I w
+-to the output
+-.IR stream .
+-It returns the word written.
+-.I Putw
+-neither assumes nor causes special alignment in the file.
+-.PP
+-The standard stream
+-.I stdout
+-is normally buffered if and only if the
+-output does not refer to a terminal;
+-this default may be changed by
+-.IR setbuf (3).
+-The standard stream
+-.I stderr
+-is by default unbuffered unconditionally,
+-but use of
+-.I freopen
+-(see
+-.IR fopen (3))
+-will cause it to become buffered;
+-.IR setbuf ,
+-again, will set the state to whatever is desired.
+-When an output stream is unbuffered information appears on the
+-destination file or terminal as soon as written;
+-when it is buffered many characters are saved up and written as a block.
+-.I Fflush
+-(see 
+-.IR fclose (3))
+-may be used to force the block out early.
+-.SH "SEE ALSO"
+-fopen(3), fclose(3), getc(3),
+-puts(3), printf(3),
+-fread(3)
+-.SH DIAGNOSTICS
+-These functions return the constant
+-.SM
+-.B EOF
+-upon error.
+-Since this is a good integer,
+-.IR  ferror (3)
+-should be used to detect 
+-.I putw
+-errors.
+-.SH BUGS
+-Because it is implemented as a macro,
+-.I putc
+-treats a
+-.I stream
+-argument with side effects improperly.
+-In particular
+-`putc(c, *f++);'
+-doesn't work sensibly.
+//GO.SYSIN DD putc.3s
+echo puts.3s
+sed 's/.//' >puts.3s <<'//GO.SYSIN DD puts.3s'
+-.TH PUTS 3S 
+-.SH NAME
+-puts, fputs \- put a string on a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B puts(s)
+-.br
+-.B char *s;
+-.PP
+-.B fputs(s, stream)
+-.br
+-.B char *s;
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Puts
+-copies the null-terminated string
+-.I s
+-to the standard output stream
+-.I stdout
+-and appends a
+-newline character.
+-.PP
+-.I Fputs
+-copies the null-terminated string
+-.I s
+-to the named output
+-.IR stream .
+-.PP
+-Neither routine copies the terminal null character.
+-.SH "SEE ALSO"
+-fopen(3), gets(3),
+-putc(3), printf(3),
+-ferror(3)
+-.br
+-fread(3) for
+-.I fwrite
+-.SH BUGS
+-.I Puts
+-appends a newline,
+-.I fputs
+-does not, all in the name of backward compatibility.
+//GO.SYSIN DD puts.3s
+echo qsort.3
+sed 's/.//' >qsort.3 <<'//GO.SYSIN DD qsort.3'
+-.TH QSORT 3 
+-.SH NAME
+-qsort \- quicker sort
+-.SH SYNOPSIS
+-.B qsort(base, nel, width, compar)
+-.br
+-.B char *base;
+-.br
+-.B int (*compar)( );
+-.SH DESCRIPTION
+-.I Qsort
+-is an implementation
+-of the quicker-sort algorithm.
+-The first argument is a pointer to the base of the data;
+-the second is the number of elements;
+-the third is the width of an element
+-in bytes;
+-the last is the name of the comparison routine
+-to be called with two arguments which are pointers
+-to the elements being compared.
+-The routine must return
+-an integer less than, equal to, or greater than 0
+-according as the first argument is to be considered
+-less than, equal to, or greater than the second.
+-.SH "SEE ALSO"
+-sort(1)
+//GO.SYSIN DD qsort.3
+echo rand.3
+sed 's/.//' >rand.3 <<'//GO.SYSIN DD rand.3'
+-.TH RAND 3 
+-.SH NAME
+-rand, srand \- random number generator
+-.SH SYNOPSIS
+-.B srand(seed)
+-.br
+-.B int seed;
+-.PP
+-.B rand( )
+-.SH DESCRIPTION
+-.I Rand
+-uses a multiplicative congruential
+-random number generator
+-with period 2\u\s732\s0\d
+-to return successive pseudo-random
+-numbers in the range from 0 to 2\u\s715\s10\d\-1.
+-.PP
+-The generator is reinitialized by calling
+-.I srand
+-with 1 as argument.
+-It can be set to a random starting point by calling
+-.I srand
+-with whatever you like as argument.
+//GO.SYSIN DD rand.3
+echo scanf.3s
+sed 's/.//' >scanf.3s <<'//GO.SYSIN DD scanf.3s'
+-.TH SCANF 3S 
+-.SH NAME
+-scanf, fscanf, sscanf \- formatted input conversion
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B scanf(format
+-[ , pointer ] . . .
+-.B )
+-.br
+-.B char *format;
+-.PP
+-.B fscanf(stream, format
+-[ , pointer ] . . .
+-.B )
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.br
+-.B char *format;
+-.PP
+-.B sscanf(s, format
+-[ , pointer ] . . .
+-.B )
+-.br
+-.B char *s, *format;
+-.SH DESCRIPTION
+-.I Scanf
+-reads from the standard input stream
+-.IR stdin .
+-.I Fscanf
+-reads from the named input
+-.IR stream .
+-.I Sscanf
+-reads from the character string
+-.IR s .
+-Each function reads characters, interprets
+-them according to a format, and stores the results in its arguments.
+-Each expects as arguments
+-a control string
+-.I format,
+-described below,
+-and a set of
+-.I pointer
+-arguments
+-indicating where the converted input should be stored.
+-.PP
+-The
+-control string
+-usually contains
+-conversion specifications, which are used to direct interpretation
+-of input sequences.
+-The control string may contain:
+-.TP 4
+-1.
+-Blanks, tabs or newlines,
+-which match optional white space in the input.
+-.TP 4
+-2.
+-An ordinary character (not %) which must match
+-the next character of the input stream.
+-.TP 4
+-3.
+-Conversion specifications, consisting of the
+-character
+-.BR % ,
+-an optional assignment suppressing character
+-.BR * ,
+-an optional numerical maximum field width, and a conversion
+-character.
+-.PP
+-A conversion specification directs the conversion of the
+-next input field; the result
+-is placed in the variable pointed to by the corresponding argument,
+-unless assignment suppression was
+-indicated by
+-.BR * .
+-An input field is defined as a string of non-space characters;
+-it extends to the next inappropriate character or until the field
+-width, if specified, is exhausted.
+-.PP
+-The conversion character indicates the interpretation of the
+-input field; the corresponding pointer argument must
+-usually be of a restricted type.
+-The following conversion characters are legal:
+-.TP 4
+-.B  %
+-a single `%' is expected
+-in the input at this point;
+-no assignment is done.
+-.TP 4
+-.B  d
+-a decimal integer is expected;
+-the corresponding argument should be an integer pointer.
+-.TP 4
+-.B  o
+-an octal integer is expected;
+-the corresponding argument should be a integer pointer.
+-.TP 4
+-.B  x
+-a hexadecimal integer is expected;
+-the corresponding argument should be an integer pointer.
+-.ti -0.2i
+-.TP 4
+-.B  s
+-a character string is expected;
+-the corresponding argument should be a character pointer
+-pointing to an array of characters large enough to accept the
+-string and a terminating `\e0', which will be added.
+-The input field is terminated by a space character
+-or a newline.
+-.TP 4
+-.B  c
+-a character is expected; the
+-corresponding argument should be a character pointer.
+-The normal skip over space characters is suppressed
+-in this case;
+-to read the next non-space character, try
+-`%1s'.
+-If a field width is given, the corresponding argument
+-should refer to a character array, and the
+-indicated number of characters is read.
+-.TP 4
+-\z\fBe\v'1'f\v'-1'\fR
+-a
+-floating point number is expected;
+-the next field is converted accordingly and stored through the
+-corresponding argument, which should be a pointer to a
+-.IR float .
+-The input format for
+-floating point numbers is
+-an optionally signed
+-string of digits
+-possibly containing a decimal point, followed by an optional
+-exponent field consisting of an E or e followed by an optionally signed integer.
+-.TP 4
+-.B  [
+-indicates a string not to be delimited by space characters.
+-The left bracket is followed by a set of characters and a right
+-bracket; the characters between the brackets define a set
+-of characters making up the string.
+-If the first character
+-is not circumflex (\|^\|), the input field
+-is all characters until the first character not in the set between
+-the brackets; if the first character
+-after the left bracket is ^, the input field is all characters
+-until the first character which is in the remaining set of characters
+-between the brackets.
+-The corresponding argument must point to a character array.
+-.PP
+-The conversion characters
+-.BR d ,
+-.B o
+-and
+-.B x
+-may be capitalized or preceeded by
+-.B l
+-to indicate that a pointer to
+-.B long
+-rather than to
+-.B int
+-is in the argument list.
+-Similarly, the conversion characters
+-.B e
+-or
+-.B f
+-may be capitalized or
+-preceded by
+-.B l
+-to indicate a pointer to 
+-.B double
+-rather than to 
+-.BR float .
+-The conversion characters
+-.BR d ,
+-.B o
+-and
+-.B x
+-may be preceeded by
+-.B h
+-to indicate a pointer to
+-.B short
+-rather than to
+-.BR int .
+-.PP
+-The
+-.I scanf
+-functions return the number of successfully matched and assigned input
+-items.
+-This can be used to decide how many input items were found.
+-The constant
+-.SM
+-.B EOF
+-is returned upon end of input; note that this is different
+-from 0, which means that no conversion was done;
+-if conversion was intended, it was frustrated by an
+-inappropriate character in the input.
+-.PP
+-For example, the call
+-.IP "" 10
+-int i; float x; char name[50];
+-.br
+-scanf( "%d%f%s", &i, &x, name);
+-.PP
+-with the input line
+-.IP
+-25   54.32E\(mi1  thompson
+-.PP
+-will assign to
+-.I i
+-the value
+-25,
+-.I x
+-the value 5.432, and
+-.I name
+-will contain
+-.IR `thompson\e0' .
+-Or,
+-.IP
+-int i; float x; char name[50];
+-.br
+-scanf("%2d%f%*d%[1234567890]", &i, &x, name);
+-.PP
+-with input
+-.IP
+-56789 0123 56a72
+-.PP
+-will assign 56 to
+-.I i,
+-789.0 to
+-.I x,
+-skip `0123',
+-and place the string `56\e0' in
+-.IR name .
+-The next call to
+-.I getchar
+-will return `a'.
+-.SH "SEE ALSO"
+-atof(3),
+-getc(3), printf(3)
+-.SH DIAGNOSTICS
+-The 
+-.I scanf
+-functions return
+-.SM
+-.B EOF
+-on end of input,
+-and a short count for missing or illegal data items.
+-.SH BUGS
+-The success of literal matches and suppressed
+-assignments is not directly
+-determinable.
+//GO.SYSIN DD scanf.3s
+echo setbuf.3s
+sed 's/.//' >setbuf.3s <<'//GO.SYSIN DD setbuf.3s'
+-.TH SETBUF 3S 
+-.SH NAME
+-setbuf \- assign buffering to a stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B setbuf(stream, buf)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.br
+-.B char *buf;
+-.SH DESCRIPTION
+-.I Setbuf
+-is used after a stream has been opened but before it
+-is read or written.
+-It causes the character array
+-.I buf
+-to be used instead of an automatically allocated buffer.
+-If
+-.I buf
+-is the constant pointer
+-.SM
+-.B NULL,
+-input/output will be completely unbuffered.
+-.PP
+-A manifest constant 
+-.SM
+-.B BUFSIZ
+-tells how big an array is needed:
+-.PP
+-.in +10
+-char buf[BUFSIZ];
+-.PP
+-A buffer is normally obtained from
+-.IR  malloc (3)
+-upon the first
+-.I getc
+-or
+-.IR  putc (3)
+-on the file,
+-except that output streams directed to terminals,
+-and the standard error stream
+-.I stderr
+-are normally not buffered.
+-.SH "SEE ALSO"
+-fopen(3), getc(3), putc(3), malloc(3)
+//GO.SYSIN DD setbuf.3s
+echo setjmp.3
+sed 's/.//' >setjmp.3 <<'//GO.SYSIN DD setjmp.3'
+-.TH SETJMP 3
+-.SH NAME
+-setjmp, longjmp \- non-local goto
+-.SH SYNOPSIS
+-.B #include <setjmp.h>
+-.PP
+-.B setjmp(env)
+-.br
+-.B jmp_buf env;
+-.PP
+-.B longjmp(env, val)
+-.br
+-.B jmp_buf env;
+-.SH DESCRIPTION
+-These routines are useful for dealing with errors 
+-and interrupts encountered in
+-a low-level subroutine of a program.
+-.PP
+-.I Setjmp 
+-saves its stack environment in
+-.I env
+-for later use by
+-.I longjmp.
+-It returns value 0.
+-.PP
+-.I Longjmp
+-restores the environment saved by the last call of
+-.IR setjmp .
+-It then returns in such a way that execution
+-continues as if the call of 
+-.I setjmp
+-had just returned the value
+-.I val
+-to the function that invoked
+-.I setjmp,
+-which must not itself have returned in the interim.
+-All accessible data have values as of the time
+-.I longjmp
+-was called.
+-.SH "SEE ALSO"
+-signal(2)
+//GO.SYSIN DD setjmp.3
+echo sin.3m
+sed 's/.//' >sin.3m <<'//GO.SYSIN DD sin.3m'
+-.TH SIN 3M 
+-.SH NAME
+-sin, cos, tan, asin, acos, atan, atan2 \- trigonometric functions
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double sin(x)
+-.br
+-.B double x;
+-.PP
+-.B double cos(x)
+-.br
+-.B double x;
+-.PP
+-.B double asin(x)
+-.br
+-.B double x;
+-.PP
+-.B double acos(x)
+-.br
+-.B double x;
+-.PP
+-.B double atan(x)
+-.br
+-.B double x;
+-.PP
+-.B double atan2(x, y)
+-.br
+-.B double x, y;
+-.SH DESCRIPTION
+-.I Sin, cos
+-and
+-.I tan
+-return trigonometric functions of radian arguments.
+-The magnitude of the argument should be checked
+-by the caller to make sure the result is meaningful.
+-.PP
+-.I Asin
+-returns the arc sin in the range \-\(*p/2 to \(*p/2.
+-.PP
+-.I Acos
+-returns the arc cosine in the range
+-0 to \(*p.
+-.PP
+-.I Atan
+-returns the arc tangent of
+-.I x
+-in the range \-\(*p/2 to \(*p/2.
+-.PP
+-.I Atan2
+-returns the arc tangent of
+-.I x/y
+-in the range \-\(*p to \(*p.
+-.SH DIAGNOSTICS
+-Arguments of magnitude greater than 1
+-cause
+-.I asin
+-and
+-.I acos
+-to return value 0;
+-.I errno
+-is set to EDOM.
+-The value of
+-.I tan
+-at its singular points is a huge number, and
+-.I errno
+-is set to ERANGE.
+-.SH BUGS
+-The value of
+-.I tan
+-for arguments greater than about 2**31 is garbage.
+//GO.SYSIN DD sin.3m
+echo sinh.3m
+sed 's/.//' >sinh.3m <<'//GO.SYSIN DD sinh.3m'
+-.TH SINH 3M
+-.SH NAME
+-sinh, cosh, tanh \- hyperbolic functions
+-.SH SYNOPSIS
+-.B #include <math.h>
+-.PP
+-.B double sinh(x)
+-.br
+-.B double x;
+-.PP
+-.B double cosh(x)
+-.br
+-.B double x;
+-.PP
+-.B double tanh(x)
+-.br
+-.B double x;
+-.SH DESCRIPTION
+-These functions compute the designated hyperbolic functions
+-for real arguments.
+-.SH DIAGNOSTICS
+-.I Sinh
+-and
+-.I cosh
+-return a huge value of appropriate sign
+-when the correct value would overflow.
+//GO.SYSIN DD sinh.3m
+echo sleep.3
+sed 's/.//' >sleep.3 <<'//GO.SYSIN DD sleep.3'
+-.TH SLEEP 3 
+-.SH NAME
+-sleep \- suspend execution for interval
+-.SH SYNOPSIS
+-.B sleep(seconds)
+-.br
+-.B unsigned seconds;
+-.SH DESCRIPTION
+-The current process is suspended from execution for the number
+-of seconds specified by the argument.
+-The actual suspension time may be up to 1 second less than
+-that requested, because scheduled wakeups occur at fixed 1-second intervals,
+-and an arbitrary amount longer because of other activity
+-in the system.
+-.PP
+-The routine is implemented by setting an alarm clock signal
+-and pausing until it occurs.
+-The previous state of this signal is saved and restored.
+-If the sleep time exceeds the time to the alarm signal,
+-the process sleeps only until the signal would have occurred, and the
+-signal is sent 1 second later.
+-.SH "SEE ALSO"
+-alarm(2), pause(2)
+//GO.SYSIN DD sleep.3
+echo stdio.3s
+sed 's/.//' >stdio.3s <<'//GO.SYSIN DD stdio.3s'
+-.TH STDIO 3S 
+-.SH NAME
+-stdio \- standard buffered input/output package
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.SM
+-.B FILE
+-.B *stdin;
+-.br
+-.SM
+-.B FILE
+-.B *stdout;
+-.br
+-.SM
+-.B FILE
+-.B *stderr;
+-.SH DESCRIPTION
+-The functions described in Sections 3S constitute an efficient
+-user-level buffering scheme.
+-The in-line macros
+-.I getc
+-and
+-.IR  putc (3)
+-handle characters quickly.
+-The higher level routines
+-.I "gets, fgets, scanf, fscanf, fread,"
+-.I "puts, fputs, printf, fprintf, fwrite"
+-all use
+-.I getc
+-and
+-.I putc;
+-they can be freely intermixed.
+-.PP
+-A file with associated buffering is called a
+-.I stream,
+-and is declared to be a pointer to a defined type
+-.SM
+-.B FILE.
+-.IR  Fopen (3)
+-creates certain descriptive data for a stream
+-and returns a pointer to designate the stream in all
+-further transactions.
+-There are three normally open streams with constant
+-pointers declared in
+-the include file and associated with the standard open files:
+-.TP 10n
+-.BR stdin
+-standard input file
+-.br
+-.ns
+-.TP
+-.B stdout
+-standard output file
+-.br
+-.ns
+-.TP
+-.BR stderr
+-standard error file
+-.PP
+-A constant `pointer'
+-.SM
+-.B NULL
+-(0)
+-designates no stream at all.
+-.PP
+-An integer constant
+-.SM
+-.B EOF
+-(\-1) is returned
+-upon end of file or error by integer functions that
+-deal with streams.
+-.PP
+-Any routine that uses the standard input/output package
+-must include the header file <stdio.h> of pertinent
+-macro definitions.
+-The functions and constants mentioned in sections labeled 3S
+-are declared in the include file
+-and need no further declaration.
+-The constants, and the following `functions' are
+-implemented as macros; redeclaration of these names
+-is perilous:
+-.I getc,
+-.I getchar,
+-.I putc,
+-.I putchar,
+-.I feof,
+-.I ferror,
+-.IR fileno .
+-.SH "SEE ALSO"
+-open(2), close(2), read(2), write(2)
+-.SH DIAGNOSTICS
+-The value
+-.SM
+-.B EOF
+-is returned uniformly to indicate that a
+-.SM
+-.B FILE
+-pointer has not been initialized with
+-.I fopen,
+-input (output) has been attempted on an output (input) stream,
+-or a
+-.SM
+-.B FILE
+-pointer designates corrupt or otherwise unintelligible
+-.SM
+-.B FILE
+-data.
+//GO.SYSIN DD stdio.3s
+echo string.3
+sed 's/.//' >string.3 <<'//GO.SYSIN DD string.3'
+-.TH STRING 3 
+-.SH NAME
+-strcat, strncat, strcmp, strncmp, strcpy, strncpy, strlen, index, rindex \- string operations
+-.SH SYNOPSIS
+-.B char *strcat(s1, s2)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B char *strncat(s1, s2, n)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B strcmp(s1, s2)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B strncmp(s1, s2, n)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B char *strcpy(s1, s2)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B char *strncpy(s1, s2, n)
+-.br
+-.B char *s1, *s2;
+-.PP
+-.B strlen(s)
+-.br
+-.B char *s;
+-.PP
+-.B char *index(s, c)
+-.br
+-.B char *s, c;
+-.PP
+-.B char *rindex(s, c)
+-.br
+-.B char *s;
+-.SH DESCRIPTION
+-These functions operate on null-terminated strings.
+-They do not check for overflow of any receiving string.
+-.PP
+-.I Strcat
+-appends a copy of string
+-.I s2
+-to the end of string
+-.IR s1 .
+-.I Strncat
+-copies at most
+-.I n
+-characters.
+-Both return a pointer to the null-terminated result.
+-.PP
+-.I Strcmp
+-compares its arguments and returns an integer
+-greater than, equal to, or less than 0,
+-according as
+-.I s1
+-is lexicographically greater than, equal to, or
+-less than
+-.IR s2 .
+-.I Strncmp
+-makes the same comparison but looks at at most
+-.I n
+-characters.
+-.PP
+-.I Strcpy
+-copies string
+-.I s2
+-to
+-.I s1,
+-stopping after the null character has been moved.
+-.I Strncpy
+-copies exactly
+-.I n
+-characters,
+-truncating or null-padding
+-.I s2;
+-the target may not be null-terminated if the length
+-of
+-.I s2
+-is
+-.I n
+-or more.
+-Both return
+-.IR s1 .
+-.PP
+-.I Strlen
+-returns the number of non-null characters in
+-.IR s .
+-.PP
+-.I Index
+-.RI ( rindex )
+-returns a pointer to the first (last)
+-occurrence of character 
+-.I c
+-in string
+-.I s,
+-or zero if
+-.I c
+-does not occur in  the string.
+-.SH BUGS
+-.I Strcmp 
+-uses native character comparison, which is signed
+-on PDP11's, unsigned on other machines.
+//GO.SYSIN DD string.3
+echo swab.3
+sed 's/.//' >swab.3 <<'//GO.SYSIN DD swab.3'
+-.TH SWAB 3 
+-.SH NAME
+-swab \- swap bytes
+-.SH SYNOPSIS
+-.B swab(from, to, nbytes)
+-.br
+-.B char *from, *to;
+-.SH DESCRIPTION
+-.I Swab
+-copies
+-.I nbytes
+-bytes pointed to by
+-.I from
+-to the position pointed to by
+-.I to,
+-exchanging adjacent even and odd bytes.
+-It is useful for carrying binary data between
+-PDP11's and other machines.
+-.I Nbytes
+-should be even.
+//GO.SYSIN DD swab.3
+echo system.3
+sed 's/.//' >system.3 <<'//GO.SYSIN DD system.3'
+-.TH SYSTEM 3
+-.SH NAME
+-system \- issue a shell command 
+-.SH SYNOPSIS
+-.B system(string)
+-.br
+-.B char *string;
+-.SH DESCRIPTION
+-.I System
+-causes the
+-.I string
+-to be given to
+-.IR  sh (1)
+-as input as if the string had been typed as a command
+-at a terminal.
+-The current process waits until the shell has
+-completed, then returns the exit status of the shell.
+-.SH "SEE ALSO"
+-popen(3),
+-exec(2), wait(2)
+-.SH DIAGNOSTICS
+-Exit status 127 indicates the shell couldn't be executed.
+//GO.SYSIN DD system.3
+echo ttyname.3
+sed 's/.//' >ttyname.3 <<'//GO.SYSIN DD ttyname.3'
+-.TH TTYNAME 3 
+-.SH NAME
+-ttyname, isatty, ttyslot \- find name of a terminal
+-.SH SYNOPSIS
+-.B char *ttyname(fildes)
+-.PP
+-.B isatty(fildes)
+-.PP
+-.B ttyslot()
+-.SH DESCRIPTION
+-.I Ttyname
+-returns a pointer to the null-terminated path name
+-of the terminal device associated with file descriptor
+-.IR fildes .
+-.PP
+-.I Isatty
+-returns 1 if
+-.I fildes
+-is associated with a terminal device, 0 otherwise.
+-.PP
+-.I Ttyslot
+-returns the number of the entry in the
+-.IR ttys (5)
+-file for the control terminal of the
+-current process.
+-.SH FILES
+-/dev/*
+-.br
+-/etc/ttys
+-.SH SEE ALSO
+-ioctl(2), ttys(5)
+-.SH DIAGNOSTICS
+-.I Ttyname
+-returns a null pointer (0) if
+-.I fildes
+-does not describe a terminal device in directory `/dev'.
+-.PP
+-.I Ttyslot
+-returns 0 if `/etc/ttys' is inaccessible or if
+-it cannot determine the control terminal.
+-.SH BUGS
+-The return value points to static data
+-whose content is overwritten by each call.
+//GO.SYSIN DD ttyname.3
+echo ungetc.3s
+sed 's/.//' >ungetc.3s <<'//GO.SYSIN DD ungetc.3s'
+-.TH UNGETC 3S 
+-.SH NAME
+-ungetc \- push character back into input stream
+-.SH SYNOPSIS
+-.B #include <stdio.h>
+-.PP
+-.B ungetc(c, stream)
+-.br
+-.SM
+-.B FILE
+-.B *stream;
+-.SH DESCRIPTION
+-.I Ungetc
+-pushes the character
+-.I c
+-back on an input stream.
+-That character will be returned by the next
+-.I getc
+-call on that stream.
+-.I Ungetc 
+-returns 
+-.IR c .
+-.PP
+-One character of pushback is guaranteed provided
+-something has been read from the stream and the stream is
+-actually buffered.
+-Attempts to push EOF are rejected.
+-.PP
+-.IR  Fseek (3)
+-erases all memory of pushed back characters.
+-.SH "SEE ALSO"
+-getc(3), setbuf(3), fseek(3)
+-.SH DIAGNOSTICS
+-.I Ungetc
+-returns
+-.SM
+-.B EOF
+-if it can't push a character back.
+//GO.SYSIN DD ungetc.3s
diff --git a/doc/7thEdMan/vol1/man4.bun b/doc/7thEdMan/vol1/man4.bun
new file mode 100644 (file)
index 0000000..1ee5455
--- /dev/null
@@ -0,0 +1,1306 @@
+# To unbundle, run this file
+echo cat.4
+sed 's/.//' >cat.4 <<'//GO.SYSIN DD cat.4'
+-.TH CAT 4 
+-.SH NAME
+-cat \- phototypesetter interface
+-.SH DESCRIPTION
+-.I Cat
+-provides the interface to a Graphic Systems C/A/T
+-phototypesetter.
+-Bytes written on the file specify font, size, and other control
+-information as well as the characters to be flashed.
+-The coding will not be described here.
+-.PP
+-Only one process may have
+-this file open at a time.
+-It is write-only.
+-.SH FILES
+-/dev/cat
+-.SH "SEE ALSO"
+-troff(1)
+-.br
+-Phototypesetter interface specification
+//GO.SYSIN DD cat.4
+echo dn.4
+sed 's/.//' >dn.4 <<'//GO.SYSIN DD dn.4'
+-.TH DN 4 
+-.SH NAME
+-dn \- DN-11 ACU interface
+-.SH DESCRIPTION
+-The
+-.I dn?
+-files
+-are write-only.
+-The permissible codes are:
+-.TP
+-0-9
+-dial 0-9
+-.br
+-.ns
+-.TP
+-.B :
+-dial *
+-.br
+-.ns
+-.TP
+-.B ;
+-dial #
+-.br
+-.ns
+-.TP
+-\-
+-4 second delay for second dial tone
+-.br
+-.ns
+-.TP
+-<
+-end-of-number
+-.PP
+-The entire telephone number must be
+-presented in a single
+-.I write
+-system call.
+-.PP
+-It is recommended that an end-of-number
+-code be given even though not all
+-ACU's actually require it.
+-.DT
+-.SH FILES
+-/dev/dn0      connected to 801 with dp0
+-.br
+-/dev/dn1      not currently connected
+-.br
+-/dev/dn2      not currently connected
+-.SH "SEE ALSO"
+-dp(4)
+//GO.SYSIN DD dn.4
+echo du.4
+sed 's/.//' >du.4 <<'//GO.SYSIN DD du.4'
+-.TH DU 4 
+-.SH NAME
+-du, dp \- DU-11 201 data-phone interface
+-.SH DESCRIPTION
+-The
+-.I dp0
+-file
+-is a 201 data-phone interface.
+-.I Read
+-and
+-.I write
+-calls
+-to dp0
+-are limited to a maximum of 512 bytes.
+-Each write call is sent as a single record.
+-Seven bits from each byte
+-are written along with an eighth odd parity
+-bit.
+-The sync must be user supplied.
+-Each read call returns characters received from a
+-single record.
+-Seven bits are returned unaltered; the eighth bit
+-is set if the byte was not received in odd parity.
+-A 10 second time out is set and a zero-byte
+-record is returned if nothing is received in that time.
+-.SH FILES
+-/dev/dp0
+-.SH "SEE ALSO"
+-dn(4)
+-.SH BUGS
+-The name
+-.I dp0
+-is a historical dreg.
+//GO.SYSIN DD du.4
+echo hp.4
+sed 's/.//' >hp.4 <<'//GO.SYSIN DD hp.4'
+-.TH HP 4 
+-.SH NAME
+-hp \- RH-11/RP04, RP05, RP06 moving-head disk
+-.SH DESCRIPTION
+-The octal representation of the minor device number is encoded
+-.IR idp ,
+-where
+-.I i
+-is an interleave flag,
+-.I d
+-is a physical drive number,
+-and
+-.I p
+-is a pseudodrive (subsection) within a physical unit.
+-If
+-.I i
+-is 0,
+-the origins and sizes of the pseudodisks on each drive,
+-counted in cylinders of 418 512-byte blocks, are:
+-.nf
+-.PP
+-      disk    start   length
+-      0       0       23
+-      1       23      21
+-      2       0       0
+-      3       0       0
+-      4       44      386
+-      5       430     385
+-      6       44      367
+-      7       44      771
+-.fi
+-.PP
+-If
+-.I i
+-is 1, the minor device consists of the specified 
+-pseudodisk on drives numbered 0 through the designated
+-drive number.
+-Successively numbered blocks are distributed
+-across the drives in rotation.
+-.PP
+-Systems distributed for these devices
+-use disk 0 for the root, disk 1 for swapping, and
+-disk 4 (RP04/5) or disk 7 (RP06) for a mounted
+-user file system.
+-.PP
+-The
+-block
+-files
+-access the disk via the system's normal
+-buffering mechanism
+-and may be read and written without regard to
+-physical disk records.
+-.PP
+-A `raw' interface
+-provides for direct transmission between the disk
+-and the user's read or write buffer.
+-A single read or write call results in exactly one I/O operation
+-and therefore raw I/O is considerably more efficient when
+-many words are transmitted.
+-The names of the raw files
+-conventionally
+-begin with
+-an extra `r.'
+-In raw I/O the buffer must begin on a word boundary,
+-and raw I/O to an interleaved device is likely to have
+-disappointing results.
+-.SH FILES
+-/dev/rp?, /dev/rrp?
+-.SH SEE ALSO
+-rp(4)
+-.SH BUGS
+-In raw I/O
+-.I read
+-and
+-.IR write (2)
+-truncate file offsets to 512-byte block boundaries,
+-and
+-.I write
+-scribbles on the tail of incomplete blocks.
+-Thus,
+-in programs that are likely to access raw devices,
+-.I read, write
+-and
+-.IR lseek (2)
+-should always deal in 512-byte multiples.
+-.PP
+-Raw device drivers don't work on interleaved devices.
+//GO.SYSIN DD hp.4
+echo hs.4
+sed 's/.//' >hs.4 <<'//GO.SYSIN DD hs.4'
+-.TH HS 4 
+-.SH NAME
+-hs \- RH11/RS03-RS04 fixed-head disk file
+-.SH DESCRIPTION
+-The files
+-.I "hs0 ... hs7"
+-refer to
+-RJS03 disk drives 0 through 7.
+-The files
+-.I "hs8 ... hs15"
+-refer to
+-RJS04 disk drives 0 through 7.
+-The RJS03 drives are each 1024 blocks long and
+-the RJS04 drives are 2048 blocks long.
+-.PP
+-The
+-.I hs
+-files
+-access the disk via the system's normal
+-buffering mechanism
+-and may be read and written without regard to
+-physical disk records.
+-There is also a `raw' inteface
+-which provides for direct transmission between the disk
+-and the user's read or write buffer.
+-A single read or write call results in exactly one I/O operation
+-and therefore raw I/O is considerably more efficient when
+-many words are transmitted.
+-The names of the raw HS files begin with
+-.IR rhs .
+-The same minor device considerations
+-hold for the raw interface as for the normal interface.
+-.PP
+-In raw I/O the buffer must begin on a word boundary,
+-and counts should be a multiple of 512 bytes
+-(a disk block).
+-Likewise
+-.I lseek
+-calls should specify a multiple of 512 bytes.
+-.SH FILES
+-/dev/hs?, /dev/rhs?
+//GO.SYSIN DD hs.4
+echo ht.4
+sed 's/.//' >ht.4 <<'//GO.SYSIN DD ht.4'
+-.TH HT 4 
+-.SH NAME
+-ht \- RH-11/TU-16 magtape interface
+-.SH DESCRIPTION
+-The files
+-.I mt0, mt1, ...
+-refer to the DEC RH/TM/TU16 magtape.
+-When opened for reading or writing,
+-the tape is not rewound.
+-When closed, it is rewound (unless the 0200 bit is on, see below).
+-If the tape was open for writing, a double end-of-file is written.
+-If the tape is not to be rewound the 
+-tape is backspaced to just between the two
+-tapemarks.
+-.PP
+-A standard tape consists of a
+-series of 512 byte records terminated by a double
+-end-of-file.
+-To the extent possible, the system makes
+-it possible, if inefficient, to treat
+-the tape like any other file.
+-Seeks have their usual meaning and it is possible
+-to read or write a byte at a time.
+-Writing in very small units is inadvisable,
+-however, because it tends to create monstrous record
+-gaps.
+-.PP
+-The last octal digit of the minor device
+-number selects the drive.
+-The middle digit selects a controller.
+-The initial digit is even to select 800 BPI,
+-odd to select 1600 BPI.
+-If the 0200 bit is on (initial digit 2 or 3), the tape is not rewound
+-on close.
+-Note that the
+-minor device number has no necessary connection
+-with the file name, and in fact
+-.IR tp (1)
+-turns the short name
+-.I x
+-into
+-.RI `/dev/mt x '.
+-.PP
+-The
+-.I mt
+-files discussed above are useful
+-when it is desired to access the tape in a way
+-compatible with ordinary files.
+-When foreign tapes are to be dealt with, and especially
+-when long records are to be read or written, the
+-`raw' interface is appropriate.
+-The associated files may be named
+-.I "rmt0, ..., rmt7,"
+-but the same minor-device considerations
+-as for the regular files still apply.
+-.PP
+-Each
+-.I read
+-or
+-.I write
+-call reads or writes the next record on the tape.
+-In the write case the record has the same length as the
+-buffer given.
+-During a read, the record size is passed
+-back as the number of bytes read, provided it is no greater
+-than the buffer size;
+-if the record is long, an error is indicated.
+-In raw tape I/O, the buffer must begin on a word boundary
+-and the count must be even.
+-Seeks are ignored.
+-A zero count is returned when a tape mark is read;
+-another read will fetch the first record of the
+-next tape file.
+-.SH FILES
+-/dev/mt?,
+-/dev/rmt?
+-.SH "SEE ALSO"
+-tp(1)
+-.SH BUGS
+-The magtape system is supposed to be able
+-to take 64 drives.
+-Such addressing has never been tried.
+-.PP
+-Taking a drive off line, or running off the end of tape,
+-while writing have been known to hang the system.
+-.PP
+-If any non-data error is encountered, it refuses to do anything
+-more until closed.
+-In raw I/O, there should be a way
+-to perform forward and backward record and file spacing and
+-to write an EOF mark explicitly.
+//GO.SYSIN DD ht.4
+echo mem.4
+sed 's/.//' >mem.4 <<'//GO.SYSIN DD mem.4'
+-.TH MEM 4 
+-.SH NAME
+-mem, kmem  \-  core memory
+-.SH DESCRIPTION
+-.I Mem
+-is a special file that is an image of the core memory
+-of the computer.
+-It may be used, for example, to examine,
+-and even to patch the system.
+-.I Kmem
+-is the same as 
+-.I mem
+-except that kernel virtual memory
+-rather than physical memory is accessed.
+-.PP
+-Byte addresses
+-are interpreted as memory addresses.
+-References to non-existent locations return errors.
+-.PP
+-Examining and patching device registers is likely
+-to lead to unexpected results when read-only or write-only
+-bits are present.
+-.PP
+-On PDP11's, the I/O page
+-begins at location 0160000 of
+-.I kmem
+-and per-process data for the current process
+-begins at 0140000.
+-.SH FILES
+-/dev/mem,
+-/dev/kmem
+-.SH BUGS
+-On PDP11's, memory files are accessed one byte
+-at a time, an inapproriate method for some
+-device registers.
+//GO.SYSIN DD mem.4
+echo null.4
+sed 's/.//' >null.4 <<'//GO.SYSIN DD null.4'
+-.TH NULL 4 
+-.SH NAME
+-null \- data sink
+-.SH DESCRIPTION
+-Data written on 
+-a null special file
+-is discarded.
+-.PP
+-Reads from 
+-a null special file
+-always return 0 bytes.
+-.SH FILES
+-/dev/null
+//GO.SYSIN DD null.4
+echo pk.4
+sed 's/.//' >pk.4 <<'//GO.SYSIN DD pk.4'
+-.TH PK 4   local
+-.SH NAME
+-pk \- packet driver
+-.SH DESCRIPTION
+-The packet driver
+-implements a full-duplex end-to-end flow control strategy
+-for machine-to-machine communication.
+-Packet driver protocol is established by
+-calling
+-.IR pkon (2)
+-with a character device file descriptor and
+-a desired packet size in bytes.
+-The packet size must be a power of 2,
+-.RI 32\(<= size \(<=4096.
+-The file descriptor
+-must represent an 8-bit data path.
+-This is normally obtained by  setting
+-the device in raw mode
+-(see
+-.IR ioctl (2)).
+-.PP
+-The actual packet size, which may be smaller than
+-the desired packet size, is arrived at by
+-negotiation with the packet driver
+-at the remote end of the data link.
+-.PP
+-The packet driver maintains two
+-data areas
+-for incoming and outgoing packets.
+-The output area is needed to implement retransmission
+-on errors,
+-and
+-arriving packets are queued in the input area.
+-Data arriving for a file not open for reading is discarded.
+-Initially the size of both areas is set
+-to two packets.
+-.PP
+-It is not necessary that reads and writes
+-be multiples of the packet size although
+-there is less system overhead if they are.
+-Read operations return the maximum amount of data
+-available from the input area up to the 
+-number of bytes specified in the system call.
+-The buffer sizes in write operations
+-are not normally transmitted across the link.
+-However, writes of zero length are treated specially
+-and are reflected at the remote end as a
+-zero-length read.
+-This facilitates marking the serial byte stream,
+-usually for delimiting files.
+-.PP
+-When one side of a packet driver link is shut down by 
+-.IR close (2) or
+-.I pkoff
+-(see
+-.IR pkon (2)),
+-.IR read (2)
+-on the other side will return 0, and
+-.I write
+-on the other side
+-will raise a SIGPIPE signal.
+-.SH "SEE ALSO"
+-pkon(2), pkopen(3)
+//GO.SYSIN DD pk.4
+echo rf.4
+sed 's/.//' >rf.4 <<'//GO.SYSIN DD rf.4'
+-.TH RF 4 
+-.SH NAME
+-rf \- RF11/RS11 fixed-head disk file
+-.SH DESCRIPTION
+-This file refers to the
+-concatenation of all RS-11 disks.
+-.PP
+-Each disk contains 1024 256-word blocks.
+-The length of the combined RF file is
+-1024\(mu(minor+1) blocks.
+-That is minor device zero
+-is taken to be
+-1024 blocks long;
+-minor device one is 2048,
+-etc.
+-.PP
+-The
+-.I rf0
+-file
+-accesses the disk via the system's normal
+-buffering mechanism
+-and may be read and written without regard to
+-physical disk records.
+-There is also a `raw' interface
+-which provides for direct transmission between the disk
+-and the user's read or write buffer.
+-A single read or write call results in exactly one I/O operation
+-and therefore raw I/O is considerably more efficient when
+-many words are transmitted.
+-The name of the raw RF file is
+-.IR rrf0 .
+-The same minor device considerations
+-hold for the raw interface as for the normal interface.
+-.PP
+-In raw I/O the buffer must begin on a word boundary,
+-and counts should be a multiple of 512 bytes
+-(a disk block).
+-Likewise
+-.I seek
+-calls should specify a multiple of 512 bytes.
+-.SH FILES
+-/dev/rf0, /dev/rrf0
+-.SH BUGS
+-The 512-byte restrictions on the raw device are not
+-physically necessary,
+-but are still imposed.
+//GO.SYSIN DD rf.4
+echo rk.4
+sed 's/.//' >rk.4 <<'//GO.SYSIN DD rk.4'
+-.TH RK 4 
+-.SH NAME
+-rk  \-  RK-11/RK03 or RK05 disk
+-.SH DESCRIPTION
+-.I Rk?
+-refers to an entire disk as a single sequentially-addressed
+-file.
+-Its 256-word blocks are numbered 0 to 4871.
+-Minor device numbers are drive numbers on one controller.
+-.PP
+-The
+-.I rk
+-files
+-discussed above access the disk via the system's normal
+-buffering mechanism
+-and may be read and written without regard to
+-physical disk records.
+-There is also a `raw' interface
+-which provides for direct transmission between the disk
+-and the user's read or write buffer.
+-A single read or write call results in exactly one I/O operation
+-and therefore raw I/O is considerably more efficient when
+-many words are transmitted.
+-The names of the raw RK files
+-begin with
+-.I rrk
+-and end with a number which selects the same disk
+-as the corresponding
+-.I rk
+-file.
+-.PP
+-In raw I/O the buffer must begin on a word boundary,
+-and counts should be a multiple of 512 bytes
+-(a disk block).
+-Likewise
+-.I seek
+-calls should specify a multiple of 512 bytes.
+-.SH FILES
+-/dev/rk?, /dev/rrk?
+-.SH BUGS
+-In raw I/O
+-.I read
+-and
+-.IR write (2)
+-truncate file offsets to 512-byte block boundaries,
+-and
+-.I write
+-scribbles on the tail of incomplete blocks.
+-Thus,
+-in programs that are likely to access raw devices,
+-.I read, write
+-and
+-.IR lseek (2)
+-should always deal in 512-byte multiples.
+//GO.SYSIN DD rk.4
+echo rp.4
+sed 's/.//' >rp.4 <<'//GO.SYSIN DD rp.4'
+-.TH RP 4 
+-.SH NAME
+-rp \- RP-11/RP03 moving-head disk
+-.SH DESCRIPTION
+-The files
+-.I "rp0 ... rp7"
+-refer to sections of RP disk drive 0.
+-The files
+-.I "rp8 ... rp15"
+-refer to drive 1 etc.
+-This allows a large disk to be broken up
+-into more manageable pieces.
+-.PP
+-The origin and size of the pseudo-disks on each drive are
+-as follows:
+-.PP
+-.br
+-      disk    start   length
+-.br
+-      0       0       81000
+-.br
+-      1       0       5000
+-.br
+-      2       5000    2000
+-.br
+-      3       7000    74000
+-.br
+-      4-7     unassigned
+-.PP
+-Thus rp0 covers the whole drive,
+-while rp1, rp2, rp3 can serve usefully as a root, swap, and
+-mounted user file system respectively.
+-.PP
+-The
+-.I rp
+-files
+-access the disk via the system's normal
+-buffering mechanism
+-and may be read and written without regard to
+-physical disk records.
+-There is also a `raw' interface
+-which provides for direct transmission between the disk
+-and the user's read or write buffer.
+-A single read or write call results in exactly one I/O operation
+-and therefore raw I/O is considerably more efficient when
+-many words are transmitted.
+-The names of the raw RP files
+-begin with
+-.I rrp
+-and end with a number which selects the same disk
+-section as the corresponding
+-.I rp
+-file.
+-.PP
+-In raw I/O the buffer must begin on a word boundary.
+-.SH FILES
+-/dev/rp?, /dev/rrp?
+-.SH SEE ALSO
+-hp(4)
+-.SH BUGS
+-In raw I/O
+-.I read
+-and
+-.IR write (2)
+-truncate file offsets to 512-byte block boundaries,
+-and
+-.I write
+-scribbles on the tail of incomplete blocks.
+-Thus,
+-in programs that are likely to access raw devices,
+-.I read, write
+-and
+-.IR lseek (2)
+-should always deal in 512-byte multiples.
+//GO.SYSIN DD rp.4
+echo tc.4
+sed 's/.//' >tc.4 <<'//GO.SYSIN DD tc.4'
+-.TH TC 4 
+-.SH NAME
+-tc \- TC-11/TU56 DECtape
+-.SH DESCRIPTION
+-The files
+-.I "tap0 ... tap7"
+-refer to the
+-TC-11/TU56 DECtape drives 0 to 7.
+-.PP
+-The 256-word blocks on a standard DECtape are numbered 0 to 577.
+-.SH FILES
+-/dev/tap?
+-.SH "SEE ALSO"
+-tp(1)
+//GO.SYSIN DD tc.4
+echo tm.4
+sed 's/.//' >tm.4 <<'//GO.SYSIN DD tm.4'
+-.TH TM 4 
+-.SH NAME
+-tm \- TM-11/TU-10 magtape interface
+-.SH DESCRIPTION
+-The files
+-.I "mt0, ..., mt7"
+-refer to the DEC TU10/TM11 magtape.
+-When closed it can be rewound or not, see below.
+-If it was open for writing, two end-of-files are written.
+-If the tape is not to be rewound
+-it is positioned with the head between the two
+-tapemarks.
+-.PP
+-If the 0200 bit is on in the minor device number the
+-tape is not rewound when closed.
+-.PP
+-A standard tape consists of a
+-series of 512 byte records terminated by an
+-end-of-file.
+-To the extent possible, the system makes
+-it possible, if inefficient, to treat
+-the tape like any other file.
+-Seeks have their usual meaning and it is possible
+-to read or write a byte at a time.
+-Writing in very small units is inadvisable,
+-however, because it tends to create monstrous record
+-gaps.
+-.PP
+-The
+-.I mt
+-files discussed above are useful
+-when it is desired to access the tape in a way
+-compatible with ordinary files.
+-When foreign tapes are to be dealt with, and especially
+-when long records are to be read or written, the
+-`raw' interface is appropriate.
+-The associated files are named
+-.I "rmt0, ..., rmt7."
+-Each
+-.I read
+-or
+-.I write
+-call reads or writes the next record on the tape.
+-In the write case the record has the same length as the
+-buffer given.
+-During a read, the record size is passed
+-back as the number of bytes read, provided it is no greater
+-than the buffer size;
+-if the record is long, an error is indicated.
+-In raw tape I/O, the buffer must begin on a word boundary
+-and the count must be even.
+-Seeks are ignored.
+-A zero byte count is returned when a tape mark is read,
+-but another read will fetch the first record of the
+-new tape file.
+-.SH FILES
+-/dev/mt?,
+-/dev/rmt?
+-.SH "SEE ALSO"
+-tp(1)
+-.SH BUGS
+-If any non-data error is encountered, it refuses to do anything
+-more until closed.
+-In raw I/O, there should be a way
+-to perform forward and backward record and file spacing and
+-to write an EOF mark.
+//GO.SYSIN DD tm.4
+echo tty.4
+sed 's/.//' >tty.4 <<'//GO.SYSIN DD tty.4'
+-.TH TTY 4 
+-.SH NAME
+-tty \- general terminal interface
+-.SH DESCRIPTION
+-This section describes
+-both a particular special file,
+-and the general nature of the terminal interface.
+-.PP
+-The file
+-.I /dev/tty
+-is, in each process, a synonym
+-for the control terminal associated with that process.
+-It is useful for programs that wish to
+-be sure of writing messages on the terminal
+-no matter how output has been redirected.
+-It can also be used for programs that demand a file name
+-for output, when typed output is desired
+-and it is tiresome to find out which terminal
+-is currently in use.
+-.PP
+-As for terminals in general: all of the low-speed asynchronous
+-communications ports use the
+-same general interface, no matter what
+-hardware is involved.
+-The remainder of this section discusses
+-the common features of the interface.
+-.PP
+-When a terminal file is opened, it causes
+-the process to wait until a connection is established.
+-In practice user's programs seldom open these
+-files; they are opened by
+-.I init
+-and become a user's
+-input and output file.
+-The very first terminal file open in a process becomes
+-the
+-.I "control terminal"
+-for that process.
+-The control terminal plays a special
+-role in handling quit or interrupt signals, as discussed
+-below.
+-The control terminal is inherited by a child process during a
+-.IR fork ,
+-even if the control terminal is closed.
+-The set of processes that thus share a control terminal
+-is called a
+-.I process
+-.IR group ;
+-all members of a process group receive certain signals
+-together, see DEL below and
+-.IR kill (2).
+-.PP
+-A terminal associated with one of these files ordinarily
+-operates in full-duplex mode.
+-Characters may be typed at any time,
+-even while output is occurring, and are only lost when the
+-system's character input buffers become completely
+-choked, which is rare,
+-or when the user has accumulated the maximum allowed number of
+-input characters that have not yet been read by some program.
+-Currently this limit is 256 characters.
+-When the input limit is reached all the
+-saved characters are thrown away without notice.
+-.PP
+-Normally, terminal input is processed in units of lines.
+-This means that a program attempting
+-to read will be suspended until an entire line has been
+-typed.
+-Also, no matter how many characters are requested
+-in the read call, at most one line will be returned.
+-It is not however necessary to read a whole line at
+-once; any number of characters may be
+-requested in a read, even one, without losing information.
+-There are special modes, discussed below,
+-that permit the program to read each character as typed
+-without waiting for a full line.
+-.PP
+-During input, erase and kill processing is normally
+-done.
+-By default, the character `#' erases the
+-last character typed, except that it will not erase
+-beyond the beginning of a line or an EOT.
+-By default, the character `@' kills the entire
+-line up to the point where it was typed, but not beyond an EOT.
+-Both these
+-characters operate on a keystroke basis independently
+-of any backspacing or tabbing that may have been done.
+-Either `@' or `#' may be entered literally by preceding
+-it by `\\';
+-the erase or kill character remains, but the
+-`\\' disappears.
+-These two characters may be changed to others.
+-.PP
+-When desired,
+-all upper-case letters are mapped into
+-the corresponding lower-case letter.
+-The upper-case letter may be generated by preceding
+-it by `\\'.
+-In addition, the following escape sequences can be generated
+-on output and accepted on input:
+-.PP
+-.nf
+-for   use
+-\`    \e\'
+-|     \\!
+-~     \e^
+-{     \e(
+-}     \e)
+-.fi
+-.PP
+-Certain ASCII control characters have special meaning.
+-These characters are not passed to a reading program
+-except in raw mode where they lose their special character.
+-Also, it is possible to change these characters from the default;
+-see below.
+-.TP
+-EOT
+-(Control-D) may be used to generate an end of file
+-from a terminal.
+-When an EOT is received, all the characters
+-waiting to be read are immediately passed to
+-the program, without waiting for a new-line,
+-and the EOT is discarded.
+-Thus if there are no characters waiting, which
+-is to say the EOT occurred at the beginning of a line,
+-zero characters will be passed back, and this is
+-the standard end-of-file indication.
+-.TP
+-DEL
+-(Rubout)
+-is not passed to a program but generates
+-an
+-.I interrupt
+-signal
+-which is sent to all processes with the associated control terminal.
+-Normally each such process is forced to terminate,
+-but arrangements may be made either to
+-ignore the signal or to receive a
+-trap to an agreed-upon location.
+-See
+-.IR signal (2).
+-.TP
+-FS
+-(Control-\\ or control-shift-L)
+-generates the
+-.I quit
+-signal.
+-Its treatment is identical to the interrupt signal
+-except that unless a receiving process has
+-made other arrangements it will not only be terminated
+-but a core image file will be generated.
+-.TP
+-DC3
+-(Control-S) delays all printing on the terminal
+-until something is typed in.
+-.TP
+-DC1
+-(Control-Q) restarts  printing after DC3 without generating
+-any input to a program.
+-.PP
+-When the carrier signal from the dataset drops (usually
+-because the user has hung up his terminal)
+-a
+-.I hangup
+-signal is sent to all processes with the terminal
+-as control terminal.
+-Unless other arrangements have been made,
+-this signal causes the processes to terminate.
+-If the hangup signal is ignored, any read
+-returns with an end-of-file indication.
+-Thus programs that read a terminal and test for
+-end-of-file on their input
+-can terminate appropriately when
+-hung up on.
+-.PP
+-When one or more
+-characters are written, they are actually transmitted
+-to the terminal as soon as previously-written characters
+-have finished typing.
+-Input characters are echoed by putting them in the output queue
+-as they arrive.
+-When a process produces characters more rapidly than they can be typed,
+-it will be suspended when its output queue exceeds some limit.
+-When the queue has drained down to some threshold
+-the program is resumed.
+-Even parity is always generated on output.
+-The EOT character is not transmitted
+-(except in raw mode)
+-to prevent terminals
+-that respond to it from hanging up.
+-.PP
+-Several
+-.IR ioctl (2)
+-calls apply to terminals.
+-Most of them use the following structure,
+-defined in
+-.IR <sgtty.h> :
+-.PP
+-.nf
+-.ft 3
+-struct sgttyb {
+-      char    sg_ispeed;
+-      char    sg_ospeed;
+-      char    sg_erase;
+-      char    sg_kill;
+-      int     sg_flags;
+-};
+-.ft R
+-.fi
+-.PP
+-The
+-.I sg_ispeed 
+-and 
+-.I sg_ospeed
+-fields describe the input and output speeds of the
+-device according to the following table,
+-which corresponds to the DEC DH-11 interface.
+-If other hardware is used,
+-impossible speed changes are ignored.
+-Symbolic values in the table are as defined in
+-.IR <sgtty.h> .
+-.PP
+-.nf
+-.ta \w'B9600   'u +5n
+-B0    0       (hang up dataphone)
+-B50   1       50 baud
+-B75   2       75 baud
+-B110  3       110 baud
+-B134  4       134.5 baud
+-B150  5       150 baud
+-B200  6       200 baud
+-B300  7       300 baud
+-B600  8       600 baud
+-B1200 9       1200 baud
+-B1800 10      1800 baud
+-B2400 11      2400 baud
+-B4800 12      4800 baud
+-B9600 13      9600 baud
+-EXTA  14      External A
+-EXTB  15      External B
+-.fi
+-.DT
+-.PP
+-In the current configuration,
+-only 110, 150, 300 and 1200 baud are really supported on dial-up lines.
+-Code conversion and line control required for
+-IBM 2741's (134.5 baud)
+-must be implemented by the user's
+-program.
+-The half-duplex line discipline
+-required for the 202 dataset (1200 baud)
+-is not supplied; full-duplex 212 datasets work fine.
+-.PP
+-The
+-.I sg_erase
+-and
+-.I sg_kill
+-fields of the argument structure
+-specify the erase and kill characters respectively.
+-(Defaults are # and @.)
+-.PP
+-The
+-.I sg_flags
+-field of the argument structure
+-contains several bits that determine the
+-system's treatment of the terminal:
+-.PP
+-.ta \w'ALLDELAY 'u +\w'0100000 'u
+-.nf
+-ALLDELAY      0177400 Delay algorithm selection
+-BSDELAY       0100000 Select backspace delays (not implemented):
+-BS0   0
+-BS1   0100000
+-VTDELAY       0040000 Select form-feed and vertical-tab delays:
+-FF0   0
+-FF1   0100000
+-CRDELAY       0030000 Select carriage-return delays:
+-CR0   0
+-CR1   0010000
+-CR2   0020000
+-CR3   0030000
+-TBDELAY       0006000 Select tab delays:
+-TAB0  0
+-TAB1  0001000
+-TAB2  0004000
+-XTABS 0006000
+-NLDELAY       0001400 Select new-line delays:
+-NL0   0
+-NL1   0000400
+-NL2   0001000
+-NL3   0001400
+-EVENP 0000200 Even parity allowed on input (most terminals)
+-ODDP  0000100 Odd parity allowed on input
+-RAW   0000040 Raw mode: wake up on all characters, 8-bit interface
+-CRMOD 0000020 Map CR into LF; echo LF or CR as CR-LF
+-ECHO  0000010 Echo (full duplex)
+-LCASE 0000004 Map upper case to lower on input
+-CBREAK        0000002 Return each character as soon as typed
+-TANDEM        0000001 Automatic flow control
+-.DT
+-.fi
+-.PP
+-The delay bits specify how long
+-transmission stops to allow for mechanical or other movement
+-when certain characters are sent to the terminal.
+-In all cases a value of 0 indicates no delay.
+-.PP
+-Backspace delays are currently ignored but might
+-be used for Terminet 300's.
+-.PP
+-If a form-feed/vertical tab delay is specified,
+-it lasts for about 2 seconds.
+-.PP
+-Carriage-return delay type 1 lasts about .08 seconds
+-and is suitable for the Terminet 300.
+-Delay type 2 lasts about .16 seconds and is suitable
+-for the VT05 and the TI 700.
+-Delay type 3 is unimplemented and is 0.
+-.PP
+-New-line delay type 1 is dependent on the current column
+-and is tuned for Teletype model 37's.
+-Type 2 is useful for the VT05 and is about .10 seconds.
+-Type 3 is unimplemented and is 0.
+-.PP
+-Tab delay type 1 is dependent on the amount of movement
+-and is tuned to the Teletype model
+-37.
+-Type 3, called XTABS,
+-is not a delay at all but causes tabs to be replaced
+-by the appropriate number of spaces on output.
+-.PP
+-Characters with the wrong parity, as determined by bits 200 and
+-100, are ignored.
+-.PP
+-In raw mode, every character is passed immediately
+-to the program without waiting until a full line has been typed.
+-No erase or kill processing is done;
+-the end-of-file indicator (EOT), the interrupt character
+-(DEL) and the quit character (FS) are not treated specially.
+-There are no delays and no echoing, and no replacement of
+-one character for another;
+-characters are a full 8 bits for both input and output
+-(parity is up to the program).
+-.PP
+-Mode 020 causes input carriage returns to be turned into
+-new-lines;
+-input of either CR or LF causes LF-CR both to
+-be echoed
+-(for terminals with a new-line function).
+-.PP
+-CBREAK is a sort of half-cooked (rare?) mode.
+-Programs can read each character as soon as typed, instead
+-of waiting for a full line,
+-but quit and interrupt work, and output delays, case-translation,
+-CRMOD, XTABS, ECHO, and parity work normally.
+-On the other hand there is no erase or kill,
+-and no special treatment of \e or EOT.
+-.PP
+-TANDEM mode causes the system to produce
+-a stop character (default DC3) whenever the input
+-queue is in danger of overflowing, and a start character
+-(default DC1)
+-when the input queue has drained sufficiently.
+-It is useful for flow control when the `terminal'
+-is actually another machine that obeys the conventions.
+-.PP
+-Several
+-.I ioctl
+-calls have the form:
+-.PP
+-.B #include <sgtty.h>
+-.PP
+-.B ioctl(fildes, code, arg)
+-.br
+-.B struct sgttyb *arg;
+-.PP
+-The applicable codes are:
+-.TP
+-TIOCGETP
+-Fetch the parameters associated with the terminal, and store
+-in the pointed-to structure.
+-.TP
+-TIOCSETP
+-Set the parameters according to the pointed-to structure.
+-The interface delays until output is quiescent,
+-then throws away any unread characters,
+-before changing the modes.
+-.TP
+-TIOCSETN
+-Set the parameters but do not delay or flush input.
+-Switching out of RAW or CBREAK mode
+-may cause some garbage input.
+-.PP
+-With the following codes the
+-.I arg
+-is ignored.
+-.TP
+-TIOCEXCL
+-Set ``exclusive-use'' mode:
+-no further opens are permitted until the file has been closed.
+-.TP
+-TIOCNXCL
+-Turn off ``exclusive-use'' mode.
+-.TP
+-TIOCHPCL
+-When the file is closed for the last time,
+-hang up the terminal.
+-This is useful when the line is associated
+-with an ACU used to place outgoing calls.
+-.TP
+-TIOCFLUSH
+-All characters waiting in input or output queues are flushed.
+-.PP
+-The following codes affect characters that are special
+-to the terminal interface.
+-The argument is a pointer to the following structure,
+-defined in
+-.IR <sgtty.h> :
+-.PP
+-.nf
+-.ft 3
+-struct tchars {
+-      char    t_intrc;                /* interrupt */
+-      char    t_quitc;                /* quit */
+-      char    t_startc;       /* start output */
+-      char    t_stopc;        /* stop output */
+-      char    t_eofc;         /* end-of-file */
+-      char    t_brkc;         /* input delimiter (like nl) */
+-};
+-.fi
+-.ft R
+-.PP
+-The default values for these characters are
+-DEL, FS, DC1, DC3, EOT, and \-1.
+-A character value of \-1
+-eliminates the effect of that character.
+-The
+-.I t_brkc
+-character, by default \-1,
+-acts like a new-line in that it terminates a `line,'
+-is echoed, and is passed to the program.
+-The `stop' and `start' characters may be the same,
+-to produce a toggle effect.
+-It is probably counterproductive to make
+-other special characters (including erase an kill)
+-identical.
+-.PP
+-The calls are:
+-.TP
+-TIOCSETC
+-Change the various special characters to those given in the structure.
+-.TP
+-TIOCSETP
+-Set the special characters to those given in the structure.
+-.SH FILES
+-/dev/tty
+-.br
+-/dev/tty*
+-.br
+-/dev/console
+-.SH SEE ALSO
+-getty(8), stty (1), signal(2), ioctl(2)
+-.SH BUGS
+-Half-duplex terminals are not supported.
+-.PP
+-The terminal handler has clearly entered the
+-race for ever-greater complexity and generality.
+-It's still not complex and general enough for
+-TENEX fans.
+//GO.SYSIN DD tty.4
+echo vp.4
+sed 's/.//' >vp.4 <<'//GO.SYSIN DD vp.4'
+-.TH VP 4 
+-.SH NAME
+-vp \- Versatec printer-plotter
+-.SH DESCRIPTION
+-.I Vp0
+-is the interface to a Versatec D1200A printer-plotter
+-with a Versatec C-PDP11(DMA) controller.
+-Ordinarily bytes written on it are interpreted as ASCII characters
+-and printed.
+-As a printer, it writes 64 lines of 132 characters each on
+-11 by 8.5 inch paper.
+-Only some of the ASCII control characters are interpreted.
+-.TP
+-NL
+-performs the usual new-line function, i.e.
+-spaces up the paper and resets to the left margin.
+-It is ignored however following a CR which ends a non-empty line.
+-.TP
+-CR
+-is ignored if the current line is empty but is otherwise
+-like NL.
+-.TP
+-FF
+-resets to the left margin and then to the top of the next page.
+-.TP
+-EOT
+-resets to the left margin, advances 8 inches, and then performs a FF.
+-.PP
+-The
+-.IR  ioctl (2)
+-system call may be used to change the mode of the device.
+-Only the first word of the 3-word argument structure is used.
+-The bits mean:
+-.TP
+-0400
+-Enter simultaneous print/plot mode.
+-.br
+-.ns
+-.TP
+-0200
+-Enter plot mode.
+-.br
+-.ns
+-.TP
+-0100
+-Enter print mode (default on open).
+-.br
+-.ns
+-.TP
+-040
+-Send remote terminate.
+-.br
+-.ns
+-.TP
+-020
+-Send remote form-feed.
+-.br
+-.ns
+-.TP
+-010
+-Send remote EOT.
+-.br
+-.ns
+-.TP
+-04
+-Send remote clear.
+-.br
+-.ns
+-.TP
+-02
+-Send remote reset.
+-.PP
+-On open a reset, clear, and form-feed are performed automatically.
+-Notice that the mode bits are not encoded, so that it is required
+-that exactly one be set.
+-.PP
+-In plot mode each byte is interpreted as 8 bits
+-of which the high-order is plotted to the left;
+-a `1' leaves a visible dot.
+-A full line of dots is produced by 264 bytes;
+-lines are terminated only by count or by a remote terminate function.
+-There are 200 dots per inch both vertically and horizontally.
+-.PP
+-When simultaneous print-plot mode is entered
+-exactly one line of characters, terminated by NL, CR, or
+-the remote terminate function,
+-should be written.
+-Then the device enters plot mode and
+-at least 20 lines of plotting bytes should be sent.
+-As the line of characters (which is 20 dots high)
+-is printed, the plotting bytes overlay the characters.
+-Notice that it is impossible to print characters on baselines
+-that differ by fewer than 20 dot-lines.
+-.PP
+-In print mode lines may be terminated either with
+-an appropriate ASCII character or by using the remote
+-terminate function.
+-.SH FILES
+-/dev/vp0
+-.SH "SEE ALSO"
+-opr(1)
+//GO.SYSIN DD vp.4
diff --git a/doc/7thEdMan/vol1/man5.bun b/doc/7thEdMan/vol1/man5.bun
new file mode 100644 (file)
index 0000000..faa7c4a
--- /dev/null
@@ -0,0 +1,1455 @@
+# To unbundle, run this file
+echo a.out.5
+sed 's/.//' >a.out.5 <<'//GO.SYSIN DD a.out.5'
+-.TH A.OUT 5 
+-.SH NAME
+-a.out \- assembler and link editor output
+-.SH SYNOPSIS
+-.B #include <a.out.h>
+-.SH DESCRIPTION
+-.I A.out
+-is the output file of the assembler
+-.IR as (1)
+-and the link editor
+-.IR ld (1).
+-Both programs make
+-.I a.out
+-executable if there were no
+-errors and no unresolved external references.
+-Layout information as given in the include file for the PDP11 is:
+-.PP
+-.nf
+-.ta 8n +9n +11n
+-.PP
+-.so /usr/include/a.out.h
+-.fi
+-.PP
+-The file has four sections:
+-a header, the program and data text,
+-relocation information, and a symbol table
+-(in that order).
+-The last two may be empty
+-if the program was loaded
+-with the `\-s' option
+-of
+-.I ld
+-or if the symbols and relocation have been
+-removed by
+-.IR strip (1).
+-.PP
+-In the header the sizes of each section are given in bytes, but are even.
+-The size of the header is not included in any of the other sizes.
+-.PP
+-When an
+-.I a.out
+-file is loaded into core for execution, three logical segments are
+-set up: the text segment, the data segment
+-(with uninitialized data, which starts off as all 0, following
+-initialized),
+-and a stack.
+-The text segment begins at 0
+-in the core image; the header is not loaded.
+-If the magic number in the header is 0407(8), it indicates that the text
+-segment is not to be write-protected and shared,
+-so the data segment is immediately contiguous
+-with the text segment.
+-If the magic number is 0410,
+-the data segment begins at the first 0 mod 8K byte
+-boundary following the text segment,
+-and the text segment is not writable by the program;
+-if other processes are executing the same file,
+-they will share the text segment.
+-If the magic number is 411,
+-the text segment is again pure, write-protected, and shared,
+-and moreover instruction and data space are separated;
+-the text and data segment both begin at location 0.
+-If the magic number is 0405, the text segment
+-is overlaid on an existing (0411 or 0405) text segment
+-and the existing data segment is preserved.
+-.PP
+-The stack will occupy the highest possible locations
+-in the core image: from 0177776(8) and growing downwards.
+-The stack is automatically extended as required.
+-The data segment is only extended as requested by
+-.IR brk (2).
+-.PP
+-The start of the text segment in the file is 020(8);
+-the start of the data segment is 020+S\s6\dt\u\s10 (the size of the text)
+-the start of the relocation information is
+-020+S\s6\dt\u\s10+S\s6\dd\u\s10;
+-the start of the symbol table is
+-020+2(S\s6\dt\u\s10+S\s6\dd\u\s10)
+-if the
+-relocation information is present,
+-020+S\s6\dt\u\s10+S\s6\dd\u\s10
+-if not.
+-.PP
+-The layout of a symbol table entry and the principal flag values
+-that distinguish symbol types are given in the include file.
+-Other flag values may occur if an assembly language program
+-defines machine instructions.
+-.PP
+-If a symbol's type is undefined external,
+-and the value field is non-zero,
+-the symbol is interpreted by the loader
+-.I ld
+-as
+-the name of a common region
+-whose size is indicated by the value of the
+-symbol.
+-.PP
+-The value of a word in the text or data portions which is not
+-a reference to an undefined external symbol
+-is exactly that value which will appear in core
+-when the file is executed.
+-If a word in the text or data portion
+-involves a reference to an undefined external symbol,
+-as indicated by the relocation information
+-for that word,
+-then the value of the word as stored in the file
+-is an offset from the associated external symbol.
+-When the file is processed by the
+-link editor and the external symbol becomes
+-defined, the value of the symbol will
+-be added into the word in the file.
+-.PP
+-If relocation
+-information is present, it amounts to one word per
+-word of program text or initialized data.
+-There is no relocation information if the `relocation info stripped'
+-flag in the header is on.
+-.PP
+-Bits 3-1 of a relocation word indicate the segment referred
+-to by the text or data word associated with the relocation
+-word:
+-.TP
+-000
+-absolute number
+-.br
+-.ns
+-.TP
+-002
+-reference to text segment
+-.br
+-.ns
+-.TP
+-004
+-reference to initialized data
+-.br
+-.ns
+-.TP
+-006
+-reference to uninitialized data (bss)
+-.br
+-.ns
+-.TP
+-010
+-reference to undefined external symbol
+-.PP
+-Bit 0 of the relocation word indicates, if 1,
+-that the
+-reference is relative to the pc (e.g. `clr x');
+-if 0,
+-that
+-the reference is to the actual symbol (e.g.,
+-`clr *$x').
+-.PP
+-The remainder of the relocation word (bits 15-4)
+-contains a symbol number in the case of external
+-references, and is unused otherwise.
+-The first symbol is numbered 0, the second 1, etc.
+-.SH "SEE ALSO"
+-as(1), ld(1), nm(1)
+//GO.SYSIN DD a.out.5
+echo acct.5
+sed 's/.//' >acct.5 <<'//GO.SYSIN DD acct.5'
+-.TH ACCT 5
+-.SH NAME
+-acct \- execution accounting file
+-.SH SYNOPSIS
+-.B #include <sys/acct.h>
+-.SH DESCRIPTION
+-.IR Acct (2)
+-causes entries to be made into an accounting file
+-for each process that terminates.
+-The accounting file is a sequence of entries whose layout,
+-as defined by the include file
+-is:
+-.PP
+-.nf
+-.ta \w'typedef 'u +\w'comp_t  'u +\w'ac_comm[10]; 'u
+-.so /usr/include/sys/acct.h
+-.fi
+-.PP
+-If the process does an
+-.IR exec (2),
+-the first 10 characters of the filename appear in
+-.I ac_comm.
+-The accounting flag contains bits indicating whether
+-.IR exec (2)
+-was ever accomplished, and whether the
+-process ever had super-user privileges.
+-.SH SEE ALSO
+-acct(2), sa(1)
+//GO.SYSIN DD acct.5
+echo ar.5
+sed 's/.//' >ar.5 <<'//GO.SYSIN DD ar.5'
+-.TH AR 5 
+-.SH NAME
+-ar \- archive (library) file format
+-.SH SYNOPSIS
+-.B #include <ar.h>
+-.SH DESCRIPTION
+-The archive command
+-.I ar
+-is used to combine several files into
+-one.
+-Archives are used mainly as libraries to be searched
+-by the link-editor
+-.I ld.
+-.PP
+-A file produced by
+-.I ar
+-has a magic number at the start,
+-followed by the constituent files, each preceded by a file header.
+-The magic number and header layout as described in the
+-include file are:
+-.RS
+-.PP
+-.nf
+-.ta \w'#define 'u +\w'ARMAG 'u
+-.so /usr/include/ar.h
+-.fi
+-.RE
+-.LP
+-The name is a null-terminated string; the date is in the
+-form of
+-.IR time (2);
+-the user ID and group ID are numbers; the mode is a bit pattern
+-per
+-.IR chmod (2);
+-the size is counted in bytes.
+-.PP
+-Each file begins on a word boundary;
+-a null byte is inserted between files if necessary.
+-Nevertheless the size given reflects the
+-actual size of the file exclusive of padding.
+-.PP
+-Notice there is no provision for empty areas in an archive
+-file.
+-.SH "SEE ALSO"
+-ar(1), ld(1), nm(1)
+-.SH BUGS
+-Coding user and group IDs as characters is a botch.
+//GO.SYSIN DD ar.5
+echo core.5
+sed 's/.//' >core.5 <<'//GO.SYSIN DD core.5'
+-.TH CORE 5 
+-.SH NAME
+-core \- format of core image file
+-.SH DESCRIPTION
+-UNIX
+-writes out a core image of a terminated
+-process when any of various errors occur.
+-See
+-.IR signal (2)
+-for the list of reasons;
+-the most common are memory violations, illegal
+-instructions, bus errors, and user-generated
+-quit signals.
+-The core image is called `core' and is written in the process's
+-working directory (provided it can be; normal
+-access controls apply).
+-.PP
+-The first 1024 bytes of the core image
+-are a copy of the system's per-user
+-data for the process, including the registers
+-as they were at the time of the fault;
+-see the system listings for the format of this area.
+-The
+-remainder represents the actual contents of
+-the user's core area when the core image
+-was written.
+-If the text segment
+-is write-protected and shared,
+-it is not dumped; otherwise the entire
+-address space is dumped.
+-.PP
+-In general the debugger
+-.IR adb (1)
+-is sufficient to deal with core images.
+-.SH "SEE ALSO"
+-adb(1), signal(2)
+//GO.SYSIN DD core.5
+echo dir.5
+sed 's/.//' >dir.5 <<'//GO.SYSIN DD dir.5'
+-.TH DIR 5 
+-.SH NAME
+-dir \- format of directories
+-.SH SYNOPSIS
+-.B #include <sys/dir.h>
+-.SH DESCRIPTION
+-A directory
+-behaves exactly like an ordinary file, save that no
+-user may write into a directory.
+-The fact that a file is a directory is indicated by
+-a bit in the flag word of its i-node entry
+-see,
+-.IR filsys (5).
+-The structure of a directory entry as given in the
+-include file is:
+-.RS
+-.ta 8n +6n
+-.PP
+-.nf
+-.so /usr/include/sys/dir.h
+-.fi
+-.RE
+-.PP
+-By convention, the first two entries in each directory
+-are for `\fB.\fR' and `\fB..\fR'.  The first is an entry for the
+-directory itself.  The second is for the parent
+-directory.
+-The meaning of `\fB..\fR' is modified for the root directory
+-of the master file system and for the root directories of removable
+-file systems.
+-In the first case, there is no parent, and in the second,
+-the system does not permit off-device references.
+-Therefore in both cases `\fB..\fR' has the
+-same meaning as `\fB.\fR'.
+-.SH "SEE ALSO"
+-filsys(5)
+//GO.SYSIN DD dir.5
+echo dump.5
+sed 's/.//' >dump.5 <<'//GO.SYSIN DD dump.5'
+-.TH DUMP 5 
+-.SH NAME
+-dump, ddate \- incremental dump format
+-.SH SYNOPSIS
+-.B #include <sys/types.h>
+-.br
+-.B #include <sys/ino.h>
+-.br
+-.B # include <dumprestor.h>
+-.SH DESCRIPTION
+-Tapes used by
+-.I dump
+-and
+-.IR restor (1)
+-contain:
+-.nf
+-.IP ""
+-a header record
+-two groups of bit map records
+-a group of records describing directories
+-a group of records describing files
+-.fi
+-.PP
+-The format of the header record and of the first
+-record of each description as given in the
+-include file
+-.I <dumprestor.h>
+-is:
+-.PP
+-.nf
+-.ta .5i \w'#define\ TS_INODE\ 'u
+-.so /usr/include/dumprestor.h
+-.fi
+-.PP
+-.I NTREC
+-is the number of 512 byte records in a physical
+-tape block.
+-.I MLEN
+-is the number of bits in a bit map word.
+-.I MSIZ 
+-is the number of bit map words.
+-.PP
+-The
+-.I TS_
+-entries are used in the
+-.I c_type
+-field to indicate what sort of header
+-this is.
+-The types and their meanings are as follows:
+-.TP \w'CHECKSUM\|'u
+-TS_TAPE
+-Tape volume label
+-.PD 0
+-.TP
+-TS_INODE
+-A file or directory follows.
+-The
+-.I c_dinode
+-field is a copy of the disk inode and contains
+-bits telling what sort of file this is.
+-.TP
+-TS_BITS
+-A bit map follows.
+-This bit map has a one bit
+-for each inode that was dumped.
+-.TP
+-TS_ADDR
+-A subrecord of a file description.
+-See
+-.I c_addr
+-below.
+-.TP
+-TS_END
+-End of tape record.
+-.TP
+-TS_CLRI
+-A bit map follows.
+-This bit map contains a zero bit for
+-all inodes that were empty on the file system when dumped.
+-.TP
+-MAGIC
+-All header records have this number in
+-.I c_magic.
+-.TP
+-CHECKSUM
+-Header records checksum to this value.
+-.PD
+-.PP
+-The fields of the header structure are as follows:
+-.TP \w'TS_INODE\ 'u
+-c_type
+-The type of the header.
+-.PD 0
+-.TP
+-c_date
+-The date the dump was taken.
+-.TP
+-c_ddate
+-The date the file system was dumped from.
+-.TP
+-c_volume
+-The current volume number of the dump.
+-.TP
+-c_tapea
+-The current number of this (512-byte) record.
+-.TP
+-c_inumber
+-The number of the inode being dumped if this
+-is of type
+-.I TS_INODE.
+-.TP
+-c_magic
+-This contains the value
+-.I MAGIC
+-above, truncated as needed.
+-.TP
+-c_checksum
+-This contains whatever value is needed to
+-make the record sum to 
+-.I CHECKSUM.
+-.TP
+-c_dinode
+-This is a copy of the inode as it appears on the
+-file system; see
+-.IR filsys (5).
+-.TP
+-c_count
+-The count of characters in
+-.I c_addr.
+-.TP
+-c_addr
+-An array of characters describing the blocks of the
+-dumped file.
+-A character is zero if the block associated with that character was not
+-present on the file system, otherwise the character is non-zero.
+-If the block was not present on the file system, no block was dumped;
+-the block will be restored as a hole in the file.
+-If there is not sufficient space in this record to describe
+-all of the blocks in a file,
+-.I TS_ADDR
+-records will be scattered through the file, each one
+-picking up where the last left off.
+-.PD
+-.PP
+-Each volume except the last ends with a tapemark (read as an end
+-of file).
+-The last volume ends with a
+-.I TS_END
+-record and then the tapemark.
+-.PP
+-The structure
+-.I idates
+-describes an entry of the file
+-.I /etc/ddate
+-where dump history is kept.
+-The fields of the structure are:
+-.TP \w'TS_INODE\ 'u
+-id_name
+-The dumped filesystem is
+-.RI `/dev/ id_nam'.
+-.PD 0
+-.TP
+-id_incno
+-The level number of the dump tape;
+-see
+-.IR dump (1).
+-.TP
+-id_ddate
+-The date of the incremental dump in system format
+-see
+-.IR types (5).
+-.PD
+-.SH FILES
+-/etc/ddate
+-.SH "SEE ALSO"
+-dump(1), dumpdir(1), restor(1), filsys(5), types(5)
+//GO.SYSIN DD dump.5
+echo environ.5
+sed 's/.//' >environ.5 <<'//GO.SYSIN DD environ.5'
+-.TH ENVIRON 5
+-.SH NAME
+-environ \- user environment
+-.SH SYNOPSIS
+-.B extern char **environ;
+-.SH DESCRIPTION
+-An array of strings called the `environment' is
+-made available by
+-.IR exec (2)
+-when a process begins.
+-By convention these strings have the form
+-`name=value'.
+-The following names are used by various commands:
+-.TP
+-PATH
+-The sequence of directory prefixes that
+-.I sh, time,
+-.IR nice (1),
+-etc.,
+-apply in searching for a file known by an incomplete path name.
+-The prefixes are separated by `:'.
+-.IR Login (1)
+-sets PATH=:/bin:/usr/bin.
+-.TP
+-HOME
+-A user's login directory, set by
+-.IR login (1)
+-from the password file
+-.IR passwd (5).
+-.TP
+-TERM
+-The kind of terminal for which output is to be prepared.
+-This information is used by commands, such as
+-.I nroff
+-or
+-.IR plot (1),
+-which may exploit special terminal capabilities.
+-See
+-.IR term (7)
+-for a list of terminal types.
+-.PP
+-Further names may be placed in the environment by
+-the
+-.I export
+-command and `name=value' arguments in
+-.IR sh (1),
+-or by 
+-.IR exec (2).
+-It is unwise to conflict with
+-certain Shell variables that are frequently exported by
+-`.profile' files:
+-MAIL, PS1, PS2, IFS.
+-.SH SEE ALSO
+-exec(2), sh(1), term(7), login(1)
+//GO.SYSIN DD environ.5
+echo filsys.5
+sed 's/.//' >filsys.5 <<'//GO.SYSIN DD filsys.5'
+-.TH FILSYS  5
+-.SH NAME
+-filsys, flblk, ino \- format of file system volume
+-.SH SYNOPSIS
+-.B #include <sys/types.h>
+-.br
+-.B #include <sys/flbk.h>
+-.br
+-.B #include <sys/filsys.h>
+-.br
+-.B #include <sys/ino.h>
+-.SH DESCRIPTION
+-Every
+-file system storage volume
+-(e.g. RF disk, RK disk, RP disk, DECtape reel)
+-has a common format for certain vital information.
+-Every such volume is divided into a certain number
+-of 512-byte blocks.
+-Block 0 is unused and is available to contain
+-a bootstrap program, pack label, or other information.
+-.PP
+-Block 1 is the
+-.I "super block."
+-The layout of the super block as defined by the include file
+-.I <sys/filsys.h>
+-is:
+-.PP
+-.nf
+-.ta \w'struct 'u +\w'daddr_t  'u +\w's_inode[NICINOD]; 'u
+-.so /usr/include/sys/filsys.h
+-.fi
+-.PP
+-.I S_isize
+-is the address of the first block after the i-list,
+-which starts just after the super-block, in block 2.
+-Thus is i-list is
+-.IR s_isize \-2
+-blocks long.
+-.I S_fsize
+-is the address of the first block not potentially
+-available for allocation
+-to a file.
+-These numbers are used by the system to
+-check for bad block addresses;
+-if an `impossible' block address is allocated from the free list
+-or is freed,
+-a diagnostic is written on the on-line console.
+-Moreover, the free array is cleared, so as to prevent further
+-allocation from a presumably corrupted free list.
+-.PP
+-The free list for each volume is maintained as
+-follows.
+-The
+-.I s_free
+-array contains, in
+-.I "s_free[1], ... , s_free[s_nfree\-1],"
+-up to NICFREE free block numbers.
+-NICFREE is a configuration constant.
+-.I S_free[0]
+-is the block address of the head
+-of a chain of blocks constituting the free list.
+-The layout of each block of the free chain as defined
+-in the include file
+-.I <sys/fblk.h>
+-is:
+-.PP
+-.nf
+-.so /usr/include/sys/fblk.h
+-.fi
+-.PP
+-The fields
+-.I df_nfree
+-and
+-.I df_free
+-in a free block are used exactly like
+-.I s_nfree
+-and 
+-.I s_free
+-in the super block.
+-To allocate a block:
+-decrement
+-.I s_nfree,
+-and the new block number is
+-.I s_free[s_nfree].
+-If the new block address is 0,
+-there are no blocks left, so give an error.
+-If
+-.I s_nfree
+-became 0,
+-read the new block into
+-.I s_nfree
+-and 
+-.I s_free.
+-To free a block, check if
+-.I s_nfree
+-is NICFREE; if so,
+-copy
+-.I s_nfree
+-and the
+-.I s_free
+-array into it,
+-write it out, and set
+-.I s_nfree
+-to 0.
+-In any event set
+-.I s_free[s_nfree]
+-to the freed block's address and
+-increment
+-.I s_nfree.
+-.PP
+-.I S_ninode
+-is the number of free i-numbers in the
+-.I s_inode
+-array.
+-To allocate an i-node:
+-if
+-.I s_ninode
+-is greater than 0,
+-decrement it and return
+-.I s_inode[s_ninode].
+-If it was 0, read the i-list
+-and place the numbers of all free inodes
+-(up to NICINOD) into the
+-.I s_inode
+-array,
+-then try again.
+-To free an i-node,
+-provided
+-.I s_ninode
+-is less than NICINODE,
+-place its number into
+-.I s_inode[s_ninode]
+-and increment
+-.I s_ninode.
+-If
+-.I s_ninode
+-is already NICINODE, don't bother to enter the freed i-node into any table.
+-This list of i-nodes is only to speed
+-up the allocation process; the information
+-as to whether the inode is really free
+-or not is maintained in the inode itself.
+-.PP
+-.I S_flock
+-and
+-.I s_ilock
+-are flags maintained in the core
+-copy of the file system
+-while it is mounted
+-and their values on disk are immaterial.
+-The value of
+-.I s_fmod
+-on disk is likewise immaterial;
+-it is used as a flag to indicate that the super-block has
+-changed and should be copied to
+-the disk during the next periodic update of file
+-system information.
+-.I S_ronly
+-is a write-protection indicator; its disk value is also immaterial.
+-.PP
+-.I S_time
+-is the last time the super-block of the file system was changed.
+-During a reboot,
+-.I s_time
+-of the super-block for the root file system
+-is used to set the system's idea of the time.
+-.PP
+-The fields
+-.I s_tfree, s_tinode, s_fname
+-and
+-.I s_fpack
+-are not currently maintained.
+-.PP
+-I-numbers begin at 1, and the storage for i-nodes
+-begins in block 2.
+-.tr |
+-I-nodes are 64 bytes long, so 8 of them fit into a block.
+-I-node 2 is reserved for the root directory of the file
+-system, but no other i-number has a built-in
+-meaning.
+-Each i-node represents one file.
+-The format of an i-node as given in the include file
+-.I <sys/ino.h>
+-is:
+-.PP
+-.nf
+-.ta \w'#define 'u +\w'time_t  'u +\w'di_addr[40]; 'u
+-.so /usr/include/sys/ino.h
+-.fi
+-.PP
+-.I Di_mode
+-tells the kind of file; it
+-is encoded identically to the
+-.I st_mode field of
+-.IR stat (2).
+-.I Di_nlink
+-is the number of directory entries
+-(links) that refer to this i-node.
+-.I Di_uid
+-and
+-.I di_gid
+-are the owner's user and group IDs.
+-.I Size
+-is the number of bytes in the file.
+-.I Di_atime
+-and
+-.I di_mtime
+-are the times of last access and modification
+-of the file contents (read, write or create)
+-(see
+-.IR times (2));
+-.I Di_ctime
+-records the time of last modification
+-to the inode or to the file, and is used
+-to determine whether it should be dumped.
+-.PP
+-Special files are recognized by their modes
+-and not by i-number.
+-A block-type special file is one which
+-can potentially be mounted as a file system;
+-a character-type special file cannot, though it is
+-not necessarily character-oriented.
+-For special files, the 
+-.I di_addr
+-field is occupied by the device code
+-(see
+-.IR types (5)).
+-The device codes
+-of block and character special files overlap.
+-.PP
+-Disk addresses of plain files and directories
+-are kept in the array
+-.I di_addr
+-packed into 3 bytes each.
+-The first 10 addresses specify device blocks directly.
+-The last 3 addresses are singly, doubly, and triply
+-indirect and point to blocks of 128 block pointers.
+-Pointers in indirect blocks have the type
+-.I daddr_t
+-(see
+-.IR types (5)).
+-.PP
+-For block
+-.I b
+-in a file to exist,
+-it
+-is not necessary that all blocks less than
+-.I b
+-exist.
+-A zero block number either in the address words of
+-the i-node or in an indirect block indicates that the
+-corresponding block has never been allocated.
+-Such a missing block reads as if it contained all zero words.
+-.SH "SEE ALSO"
+-icheck(1), dcheck(1), dir(5), mount(1), stat(2), types(5)
+//GO.SYSIN DD filsys.5
+echo group.5
+sed 's/.//' >group.5 <<'//GO.SYSIN DD group.5'
+-.TH GROUP 5 
+-.SH NAME
+-group \- group file
+-.SH DESCRIPTION
+-.I Group
+-contains for each group the
+-following information:
+-.HP 10
+-group name
+-.br
+-.ns
+-.HP 10
+-encrypted password
+-.br
+-.ns
+-.HP 10
+-numerical group ID
+-.br
+-.ns
+-.HP 10
+-a comma separated list of all users allowed in the group
+-.PP
+-This is an ASCII file.
+-The fields are separated
+-by colons;
+-Each group is separated from the next by a new-line.
+-If the password field is null, no password is demanded.
+-.PP
+-This file resides in directory /etc.
+-Because of the encrypted
+-passwords, it can and does have general read
+-permission and can be used, for example,
+-to map numerical group ID's to names.
+-.SH FILES
+-/etc/group
+-.SH "SEE ALSO"
+-newgrp(1), crypt(3), passwd(1), passwd(5)
+//GO.SYSIN DD group.5
+echo mpxio.5
+sed 's/.//' >mpxio.5 <<'//GO.SYSIN DD mpxio.5'
+-.TH MPXIO 5 
+-.SH NAME
+-mpxio \- multiplexed i/o
+-.SH SYNOPSIS
+-.B #include <sys/mx.h>
+-.PP
+-.B #include <sgtty.h>
+-.SH DESCRIPTION
+-Data transfers on
+-mpx files
+-(see
+-.IR mpx (2))
+-are multiplexed by
+-imposing
+-a record structure  on the io stream.
+-Each record represents  data
+-from/to
+-a particular channel or 
+-a control or status message associated with a particular channel.
+-.PP
+-The prototypical data record read from an mpx file is as follows
+-.PP
+-.in +.5i
+-.nf
+-struct input_record {
+-      short   index;
+-      short   count;
+-      short   ccount;
+-      char    data[];
+-};
+-.PP
+-.fi
+-where
+-.I index
+-identifies the channel,
+-and
+-.I count
+-specifies the number of characters in
+-.I data.
+-If
+-.I count
+-is zero,
+-.I ccount
+-gives the size of
+-.I data,
+-and the record is  a control or status message.
+-Although
+-.I count
+-or
+-.I ccount
+-might be odd,
+-the operating system aligns records
+-on short (i.e. 16\-bit) boundaries
+-by skipping bytes when necessary.
+-.PP
+-Data written to an mpx file must be formatted as an array
+-of record structures defined as follows
+-.PP
+-.in +.5i
+-.nf
+-struct output_record {
+-      short   index;
+-      short   count;
+-      short   ccount;
+-      char    *data;
+-};
+-.fi
+-.PP
+-where the data portion of the record is referred
+-to indirectly and the other cells have the same interpretation
+-as in
+-.I input_record.
+-.PP
+-The 
+-control messages listed below may be read from
+-a multiplexed file descriptor.
+-They are presented as two 16-bit integers:
+-the first number is the message code
+-(defined in
+-.IR <sys/mx.h> ),
+-the second is an optional parameter meaningful
+-only with M_WATCH and M_BLK.
+-.PP
+-.in +1i
+-.ti -.5i
+-M_WATCH \- a process `wants to attach' on this channel.
+-The second parameter is the 16-bit 
+-user-id of the process that executed the open.
+-.br
+-.ti -.5i
+-M_CLOSE \- the channel is closed.
+-This message is generated when the last 
+-file descriptor referencing
+-a channel is closed.
+-The
+-.I detach
+-command
+-(see
+-.IR mpx (2)
+-should be used in response to this message.
+-.br
+-.ti -.5i
+-M_EOT \- indicates logical end of file on a channel.
+-If the channel is joined to a typewriter,
+-EOT (control-d)
+-will cause the M_EOT message 
+-under the conditions specified in
+-.IR tty (4)
+-for  end of file.
+-If the channel is attached to a process,
+-M_EOT will be generated whenever the process
+-writes zero bytes on the channel.
+-.br
+-.ti -.5i
+-M_BLK \- if non-blocking mode has been enabled on an
+-mpx file descriptor
+-.I xd
+-by executing
+-.IR "ioctl(xd, MXNBLK, 0)" ,
+-write operations on the  file are truncated in the kernel
+-when internal queues become full.
+-This is done on a per-channel basis:
+-the parameter 
+-is a count of the number of characters
+-not transferred to the channel on which
+-M_BLK is received.
+-.br
+-.ti -.5i
+-M_UBLK \- is generated for a channel
+-after M_BLK when the internal queues have
+-drained below a threshold.
+-.in -1i
+-.PP
+-Two other messages may be generated by the kernel.
+-As with other messages, the first
+-16-bit quantity is the message code.
+-.PP
+-.in +1i
+-.ti -.5i
+-M_OPEN \- is generated in conjunction with 
+-`listener' mode (see
+-.IR mpx (2)).
+-The uid of the calling process follows the message code
+-as with M_WATCH.
+-This is followed by a null-terminated string
+-which is the name of the file being opened.
+-.br
+-.ti -.5i
+-M_IOCTL \- is generated for a channel connected
+-to a process
+-when that process executes the
+-.I "ioctl(fd, cmd, &vec)"
+-call on the channel file descriptor.
+-The M_IOCTL code is followed by
+-the
+-.I cmd
+-argument given to
+-.I ioctl
+-followed by 
+-the contents of the structure
+-.I vec.
+-It is assumed,
+-not needing a better compromise at this time,
+-that the length of
+-.I vec
+-is determined by
+-.I "sizeof (struct sgttyb)"
+-as declared in
+-.IR <sgtty.h> .
+-.in -1i
+-.PP
+-Two control messages are understood by the operating system.
+-M_EOT may be sent through an mpx file to a channel.
+-It is equivalent to propagating a zero-length record
+-through the channel;
+-i.e. the channel is allowed to drain and the process or
+-device at the other end receives a zero-length
+-transfer before data starts flowing through the channel again.
+-M_IOCTL can also be sent through a channel.
+-The format is identical to that described above.
+//GO.SYSIN DD mpxio.5
+echo mtab.5
+sed 's/.//' >mtab.5 <<'//GO.SYSIN DD mtab.5'
+-.TH MTAB 5 
+-.SH NAME
+-mtab \- mounted file system table
+-.SH DESCRIPTION
+-.I Mtab
+-resides in directory
+-.I /etc
+-and contains a table of devices mounted by the
+-.I mount
+-command.
+-.I Umount
+-removes entries.
+-.PP
+-Each entry is 64 bytes long;
+-the first 32 are the null-padded name of the
+-place where the special file is mounted;
+-the second 32 are the null-padded name of the special
+-file.
+-The special file has all its directories
+-stripped away;
+-that is, everything through the last `/' is thrown
+-away.
+-.PP
+-This table is present only so people can look at it.
+-It does not matter to
+-.I mount
+-if there are duplicated entries nor
+-to
+-.I umount
+-if a name cannot be found.
+-.SH FILES
+-/etc/mtab
+-.SH "SEE ALSO"
+-mount(1)
+//GO.SYSIN DD mtab.5
+echo passwd.5
+sed 's/.//' >passwd.5 <<'//GO.SYSIN DD passwd.5'
+-.TH PASSWD 5 
+-.SH NAME
+-passwd \- password file
+-.SH DESCRIPTION
+-.I Passwd
+-contains for each user the
+-following information:
+-.HP 10
+-name (login name, contains no upper case)
+-.br
+-.ns
+-.HP 10
+-encrypted password
+-.br
+-.ns
+-.HP 10
+-numerical user ID
+-.br
+-.ns
+-.HP 10
+-numerical group ID
+-.br
+-.ns
+-.HP 10
+-GCOS job number, box number, optional GCOS user-id
+-.br
+-.ns
+-.HP 10
+-initial working directory
+-.br
+-.ns
+-.HP 10
+-program to use as Shell
+-.PP
+-This is an ASCII file.  Each field within each user's entry
+-is separated from the next by a colon.
+-The GCOS field is used only when communicating with that
+-system, and in other installations can contain
+-any desired information.
+-Each user is separated from the next by a new-line.
+-If the password field is null, no password is demanded;
+-if the Shell field is null, the Shell itself
+-is used.
+-.PP
+-This file resides in directory /etc.
+-Because of the encrypted
+-passwords, it can and does have general read
+-permission and can be used, for example,
+-to map numerical user ID's to names.
+-.SH FILES
+-/etc/passwd
+-.SH "SEE ALSO"
+-getpwent(3), login(1), crypt(3), passwd(1), group(5)
+//GO.SYSIN DD passwd.5
+echo plot.5
+sed 's/.//' >plot.5 <<'//GO.SYSIN DD plot.5'
+-.TH PLOT 5 
+-.SH NAME
+-plot \- graphics interface
+-.SH DESCRIPTION
+-Files of this format are produced by routines
+-described in 
+-.IR  plot (3),
+-and are interpreted for various devices
+-by commands described in
+-.IR  plot (1).
+-A graphics file is a stream of plotting instructions.
+-Each instruction consists of an ASCII letter
+-usually followed by bytes of binary information.
+-The instructions are executed in order.
+-A point is designated by
+-four bytes representing
+-the
+-x and y
+-values;
+-each value
+-is a signed integer.
+-The last designated point in an
+-.B "l, m, n,"
+-or
+-.B p
+-instruction becomes the `current point'
+-for the next instruction.
+-.PP
+-Each of the following descriptions begins with the name
+-of the corresponding routine in
+-.IR  plot (3).
+-.TP 3
+-.B  m
+-move: The next four bytes give a new current point.
+-.TP 3
+-.B  n
+-cont: Draw a line from the current point to
+-the point given by the next four bytes.
+-See
+-.IR  plot (1).
+-.TP 3
+-.B  p
+-point: Plot the point given by the next four bytes.
+-.TP 3
+-.B  l
+-line: Draw a line from the point given by the next
+-four bytes to the point given by the following four bytes.
+-.TP 3
+-.B  t
+-label: Place the following ASCII string so that its
+-first character falls on the current point.
+-The string is terminated by a newline.
+-.TP 3
+-.B  a
+-arc:
+-The first four bytes give the center, the next four give the
+-starting point,
+-and the last four give the end point of a circular arc.
+-The least significant coordinate of the end point is
+-used only to determine the quadrant.
+-The arc is drawn counter-clockwise.
+-.TP 3
+-.B  c
+-circle:
+-The first four bytes give the center of the circle,
+-the next two the radius.
+-.TP 3
+-.B  e
+-erase: Start another frame of output.
+-.TP 3
+-.B  f
+-linemod: Take the following string, up to a newline,
+-as the style for drawing further lines.
+-The styles are
+-`dotted,'
+-`solid,' `longdashed,' `shortdashed,' and `dotdashed.'
+-Effective only in 
+-.I plot 4014
+-and
+-.I plot ver.
+-.TP 3
+-.B  s
+-space: The next four bytes give
+-the lower left corner of the plotting area;
+-the following four give the upper right corner.
+-The plot will be magnified or reduced to fit
+-the device as closely as possible.
+-.IP
+-Space settings that exactly fill the plotting area
+-with unity scaling appear below for
+-devices supported by the filters of
+-.IR  plot (1).
+-The upper limit is just outside the plotting area.
+-In every case the plotting area is taken to be square;
+-points outside may be displayable on
+-devices whose face isn't square.
+-.RS
+-.TP 10n
+-4014
+-space(0, 0, 3120, 3120);
+-.br
+-.ns
+-.TP 
+-ver
+-space(0, 0, 2048, 2048);
+-.br
+-.ns
+-.TP 
+-300, 300s
+-space(0, 0, 4096, 4096);
+-.br
+-.ns
+-.TP 
+-450
+-space(0, 0, 4096, 4096);
+-.RE
+-.SH "SEE ALSO"
+-plot(1), plot(3), graph(1)
+//GO.SYSIN DD plot.5
+echo tp.5
+sed 's/.//' >tp.5 <<'//GO.SYSIN DD tp.5'
+-.TH TP 5 
+-.SH NAME
+-tp \- DEC/mag tape formats
+-.SH DESCRIPTION
+-The
+-command
+-.I tp
+-dumps files to and extracts files from
+-DECtape and magtape.
+-The formats of these tapes are the same except
+-that magtapes have larger directories.
+-.PP
+-Block zero contains a
+-copy of a stand-alone bootstrap program.
+-See
+-.IR bproc (8).
+-.PP
+-Blocks 1 through 24
+-for DECtape (1 through 62 for magtape)
+-contain a directory of the tape.
+-There are 192 (resp. 496) entries in the directory;
+-8 entries per block;
+-64 bytes per entry.
+-Each entry has the following format:
+-.nf
+-.IP ""
+-struct {
+-      char    pathname[32];
+-      int     mode;
+-      char    uid;
+-      char    gid;
+-      char    unused1;
+-      char    size[3];
+-      long    modtime;
+-      int     tapeaddr;
+-      char    unused2[16];
+-      int     checksum;
+-};
+-.fi
+-.PP
+-The path name entry is the path name of the
+-file when put on the tape.
+-If the pathname starts with a zero word,
+-the entry is empty.
+-It is at most 32 bytes long and ends in a null byte.
+-Mode, uid, gid, size and time modified
+-are the same as described under i-nodes 
+-(see file system
+-.IR filsys (5)).
+-The tape address is the tape block number of the start of
+-the contents of the file.
+-Every file
+-starts on a block boundary.
+-The file occupies (size+511)/512 blocks
+-of continuous tape.
+-The checksum entry has a value such that
+-the sum of the 32 words of the directory entry is zero.
+-.PP
+-Blocks above 25 (resp. 63) are available for file storage.
+-.PP
+-A fake entry
+-has a size of zero.
+-.SH "SEE ALSO"
+-filsys(5), tp(1)
+-.SH BUGS
+-The
+-.I pathname, uid, gid,
+-and
+-.I size
+-fields are too small.
+//GO.SYSIN DD tp.5
+echo ttys.5
+sed 's/.//' >ttys.5 <<'//GO.SYSIN DD ttys.5'
+-.TH TTYS 5 
+-.SH NAME
+-ttys \- terminal initialization data
+-.SH DESCRIPTION
+-The
+-.I ttys
+-file is read by the
+-.I init
+-program and specifies
+-which terminal special files are to have
+-a process created for them which will allow people to
+-log in.
+-It contains one line per special file.
+-.PP
+-The first character of a line is either `0' or `1';
+-the former causes the line to be ignored,
+-the latter causes it to be effective.
+-The second character is used as an argument to
+-.IR getty (8),
+-which performs such tasks as baud-rate recognition,
+-reading the login name,
+-and calling
+-.I login.
+-For normal lines,
+-the character is `0';
+-other characters can be used, for example, with hard-wired terminals
+-where speed recognition is unnecessary
+-or which have special characteristics.
+-.RI ( Getty
+-will have to be fixed in such cases.)
+-The remainder of the line is the terminal's entry
+-in the device directory, /dev.
+-.SH FILES
+-/etc/ttys
+-.SH "SEE ALSO"
+-init(8), getty(8), login(1)
+//GO.SYSIN DD ttys.5
+echo types.5
+sed 's/.//' >types.5 <<'//GO.SYSIN DD types.5'
+-.TH TYPES 5
+-.SH NAME
+-types \- primitive system data types
+-.SH SYNOPSIS
+-.B #include <sys/types.h>
+-.SH DESCRIPTION
+-The data types defined in the include file
+-are used in UNIX system code;
+-some data of these types are accessible to user code:
+-.PP
+-.nf
+-.so /usr/include/sys/types.h
+-.fi
+-.PP
+-The form
+-.I daddr_t
+-is used for disk addresses except in an
+-i-node on disk, see
+-.IR filsys (5).
+-Times are encoded in seconds since 00:00:00 GMT, January 1, 1970.
+-The major and minor parts of a device code
+-specify kind and unit number of a device
+-and are installation-dependent.
+-Offsets are measured in bytes from the beginning of a file.
+-The
+-.I label_t
+-variables are used to save the processor state
+-while another process is running.
+-.SH SEE ALSO
+-filsys(5), time(2), lseek(2), adb(1)
+//GO.SYSIN DD types.5
+echo utmp.5
+sed 's/.//' >utmp.5 <<'//GO.SYSIN DD utmp.5'
+-.TH UTMP 5 
+-.SH NAME
+-utmp, wtmp \- login records
+-.SH SYNOPSIS
+-.B #include <utmp.h>
+-.SH DESCRIPTION
+-The
+-.I utmp
+-file allows one to discover information about who is currently
+-using UNIX.
+-The file is a sequence of entries with the following
+-structure declared in the include file:
+-.RS
+-.PP
+-.nf
+-.so /usr/include/utmp.h
+-.fi
+-.RE
+-.PP
+-This structure gives the name of the special file
+-associated with the user's terminal, the user's login name,
+-and the time of the login in the form of
+-.IR time (2).
+-.PP
+-The
+-.I wtmp
+-file records all logins and logouts.
+-Its format is exactly like
+-.I utmp
+-except that
+-a null user name indicates a logout on the associated
+-terminal.
+-Furthermore, the terminal name `~' indicates that the
+-system was rebooted at the indicated time;
+-the adjacent pair of entries with terminal names
+-`\^|\^' and `}' indicate the system-maintained time
+-just before and just after a
+-.I date
+-command has changed the system's idea of the time.
+-.PP
+-.I Wtmp
+-is maintained by
+-.IR login (1)
+-and
+-.IR init (8).
+-Neither of these programs creates the file,
+-so if it is removed record-keeping is turned off.
+-It is summarized by
+-.IR ac (1).
+-.SH FILES
+-/etc/utmp
+-.br
+-/usr/adm/wtmp
+-.SH "SEE ALSO"
+-login(1), init(8), who(1), ac(1)
+//GO.SYSIN DD utmp.5
diff --git a/doc/7thEdMan/vol1/man6.bun b/doc/7thEdMan/vol1/man6.bun
new file mode 100644 (file)
index 0000000..8bff617
--- /dev/null
@@ -0,0 +1,777 @@
+# To unbundle, run this file
+echo arithmetic.6
+sed 's/.//' >arithmetic.6 <<'//GO.SYSIN DD arithmetic.6'
+-.TH ARITHMETIC 6 
+-.SH NAME
+-arithmetic \- provide drill in number facts
+-.SH SYNOPSIS
+-.B /usr/games/arithmetic
+-[
+-.B +\-x/
+-] [ range ]
+-.SH DESCRIPTION
+-.I Arithmetic
+-types out simple arithmetic problems,
+-and waits for an answer to be typed in.
+-If the answer is correct,
+-it types back "Right!",
+-and a new problem.
+-If the answer is wrong,
+-it replies "What?",
+-and waits for another answer.
+-Every twenty problems, it publishes
+-statistics on correctness and the time required
+-to answer.
+-.PP
+-To quit the program,
+-type an interrupt (delete).
+-.PP
+-The first optional argument determines the kind of problem
+-to be generated;
+-.B +\-x/
+-respectively cause
+-addition, subtraction, multiplication, and division
+-problems to be generated.
+-One or more characters can be given;
+-if more than one is given, the different types of
+-problems will be mixed in random order; default is
+-.B +\-
+-.PP
+-.I Range
+-is a decimal number;
+-all addends, subtrahends, differences, multiplicands, divisors,
+-and quotients will be less than or equal to the value of
+-.IR range .
+-Default
+-.I range
+-is 10.
+-.PP
+-At the start, all numbers less than or equal to
+-.I range
+-are equally likely
+-to appear.
+-If the respondent makes a mistake,
+-the numbers in the problem which was missed
+-become more likely to reappear.
+-.PP
+-As a matter of educational philosophy, the program will
+-not give correct answers,
+-since the learner should, in principle,
+-be able to calculate them.
+-Thus the program is intended to provide drill for
+-someone just past the first learning stage,
+-not to teach number facts
+-.I de
+-.IR novo .
+-For almost all users,
+-the relevant statistic should be
+-time per problem, not percent correct.
+//GO.SYSIN DD arithmetic.6
+echo backgammon.6
+sed 's/.//' >backgammon.6 <<'//GO.SYSIN DD backgammon.6'
+-.TH BACKGAMMON 6 
+-.SH NAME
+-backgammon \- the game
+-.SH SYNOPSIS
+-.B /usr/games/backgammon
+-.SH DESCRIPTION
+-This program does what you expect.
+-It will ask whether you need instructions.
+//GO.SYSIN DD backgammon.6
+echo banner.6
+sed 's/.//' >banner.6 <<'//GO.SYSIN DD banner.6'
+-.TH BANNER 6 
+-.SH NAME
+-banner \- make long posters
+-.SH SYNOPSIS
+-.B /usr/games/banner
+-.SH DESCRIPTION
+-.I Banner
+-reads the standard input and
+-prints it sideways in huge built-up letters
+-on the standard output.
+//GO.SYSIN DD banner.6
+echo bcd.6
+sed 's/.//' >bcd.6 <<'//GO.SYSIN DD bcd.6'
+-.TH BCD 6 
+-.SH NAME
+-bcd, ppt \- convert to antique media
+-.SH SYNOPSIS
+-.B /usr/games/bcd
+-text
+-.PP
+-.B /usr/games/ppt
+-.SH DESCRIPTION
+-.I Bcd
+-converts the literal
+-.I text
+-into a form familiar to old-timers.
+-.PP
+-.I Ppt
+-converts the standard input into yet another form.
+-.SH "SEE ALSO"
+-dd(1)
+//GO.SYSIN DD bcd.6
+echo bj.6
+sed 's/.//' >bj.6 <<'//GO.SYSIN DD bj.6'
+-.TH BJ 6 
+-.SH NAME
+-bj \- the game of black jack
+-.SH SYNOPSIS
+-.B /usr/games/bj
+-.SH DESCRIPTION
+-.I Bj
+-is a serious attempt at
+-simulating the dealer
+-in the game of black jack (or twenty-one)
+-as might be found in Reno.
+-The following rules apply:
+-.HP 5
+-The bet is $2 every hand.
+-.IP
+-A player `natural' (black jack) pays $3.
+-A dealer natural loses $2.
+-Both dealer and player naturals
+-is a `push' (no money exchange).
+-.IP
+-If the dealer has an ace up,
+-the player is allowed to make an `insurance'
+-bet against the chance of a dealer natural.
+-If this bet is not taken, play resumes as normal.
+-If the bet is taken, it is a side bet
+-where the player wins $2 if the dealer has
+-a natural and loses $1 if the dealer does not.
+-.IP
+-If the player is dealt two cards
+-of the same value, he is allowed to
+-`double'.
+-He is allowed to play two
+-hands, each with one of these cards.
+-(The bet is doubled also; $2 on each hand.)
+-.IP
+-If a dealt hand
+-has a total of ten or eleven,
+-the player may `double down'.
+-He may double the bet ($2 to $4)
+-and receive exactly one more card on that hand.
+-.IP
+-Under normal play,
+-the player may `hit' (draw a card)
+-as long as his total is not over twenty-one.
+-If the player `busts' (goes over twenty-one),
+-the dealer wins the bet.
+-.IP
+-When the player `stands' (decides not to hit),
+-the dealer hits until he attains
+-a total of seventeen or more.
+-If the dealer busts, the player wins the bet.
+-.IP
+-If both player and dealer stand,
+-the one with the largest total wins.
+-A tie is a push.
+-.PP
+-The machine deals and keeps score.
+-The following questions will be asked at
+-appropriate times.
+-Each question is
+-answered by
+-.B y
+-followed by a new line for `yes',
+-or just new line for `no'.
+-.PP
+-?             (means, `do you want a hit?')
+-.br
+-Insurance?
+-.br
+-Double down?
+-.PP
+-Every time the deck is shuffled,
+-the dealer so states and the `action' (total bet)
+-and `standing' (total won or lost)
+-is printed.
+-To exit, hit the interrupt key (DEL)
+-and the action and standing will be printed.
+//GO.SYSIN DD bj.6
+echo checkers.6
+sed 's/.//' >checkers.6 <<'//GO.SYSIN DD checkers.6'
+-.TH CHECKERS 6
+-.SH NAME
+-checkers \- game
+-.SH SYNOPSIS
+-.B /usr/games/checkers
+-.SH DESCRIPTION
+-.I Checkers
+-uses standard notation for the board:
+-.PP
+-.ce
+-BLACK
+-.nf
+-.TS
+-center, box;
+-r|r|r|r|r|r|r|r.
+-////  1       ////    2       ////    3       ////    4
+-////          ////            ////            ////
+-_
+-5     ////    6       ////    7       ////    8       ////
+-      ////            ////            ////            ////
+-_
+-////  9       ////    10      ////    11      ////    12
+-////          ////            ////            ////
+-_
+-13    ////    14      ////    15      ////    16      ////
+-      ////            ////            ////            ////
+-_
+-////  17      ////    18      ////    19      ////    20
+-////          ////            ////            ////
+-_
+-21    ////    22      ////    23      ////    24      ////
+-      ////            ////            ////            ////
+-_
+-////  25      ////    26      ////    27      ////    28
+-////          ////            ////            ////
+-_
+-29    ////    30      ////    31      ////    32      ////
+-      ////            ////            ////            ////
+-_
+-.TE
+-.ce
+-WHITE
+-.fi
+-.PP
+-Black plays first.
+-The program normally plays white.
+-To specify a move, name the square moved from
+-and the square moved to.
+-For multiple jumps name all the squares touched.
+-.PP
+-.PP
+-Certain commands may be given instead of moves:
+-.TP \w'reverse\ \ 'u
+-reverse
+-Reverse roles; the program takes over your pieces.
+-.TP
+-backup
+-Undo the last move for each player.
+-.TP
+-list
+-Print the record of the game.
+-.TP
+-move
+-Let the program select a move for you.
+-.TP
+-print
+-Print a map of the present position.
+//GO.SYSIN DD checkers.6
+echo chess.6
+sed 's/.//' >chess.6 <<'//GO.SYSIN DD chess.6'
+-.TH CHESS 6 
+-.SH NAME
+-chess \- the game of chess
+-.SH SYNOPSIS
+-.B /usr/games/chess
+-.SH DESCRIPTION
+-.I Chess
+-is a computer program that plays class D chess.
+-Moves may be given either in standard (descriptive) notation
+-or in algebraic notation.
+-The symbol `+' is used to specify check;
+-`o-o' and `o-o-o' specify castling.
+-To play black, type `first';
+-to print the board, type an empty line.
+-.PP
+-Each move is echoed in the appropriate notation followed by
+-the program's reply.
+-.SH FILES
+-/usr/lib/book         opening `book'
+-.SH DIAGNOSTICS
+-The most cryptic diagnostic is `eh?' which
+-means that the input was syntactically incorrect.
+-.SH WARNING
+-Over-use of this program
+-will cause it to go away.
+-.SH BUGS
+-Pawns may be promoted only to queens.
+//GO.SYSIN DD chess.6
+echo ching.6
+sed 's/.//' >ching.6 <<'//GO.SYSIN DD ching.6'
+-.TH CHING 6 
+-.SH NAME
+-ching, fortune \- the book of changes and other cookies
+-.SH SYNOPSIS
+-.B /usr/games/ching
+-[ hexagram ]
+-.PP
+-.B /usr/games/fortune
+-.SH DESCRIPTION
+-The
+-.I "I Ching"
+-or
+-.I "Book of Changes"
+-is an ancient Chinese oracle
+-that has been in use for
+-centuries
+-as a source of wisdom
+-and advice.
+-.PP
+-The text of the
+-.I oracle
+-(as it is sometimes known)
+-consists of sixty-four
+-.I hexagrams,
+-each symbolized
+-by a particular
+-arrangement of
+-six straight
+-(\-\-\-)
+-and broken
+-(\-\ \-)
+-lines.
+-These lines
+-have values ranging
+-from six through nine,
+-with the even
+-values indicating
+-the broken lines.
+-.PP
+-Each hexagram
+-consists of two major sections.
+-The
+-.B  Judgement
+-relates specifically
+-to the matter at hand
+-(E.g.,
+-"It furthers one to have somewhere to go.")
+-while the
+-.B  Image
+-describes
+-the general attributes
+-of the hexagram
+-and how they apply
+-to one's own life
+-("Thus the superior man
+-makes himself strong
+-and untiring.").
+-.PP
+-When any of the lines
+-have the values six or nine,
+-they are moving lines;
+-for each
+-there is an appended
+-judgement which
+-becomes significant.
+-Furthermore, the moving lines
+-are inherently unstable and
+-change into their opposites;
+-a second hexagram
+-(and thus an additional judgement)
+-is formed.
+-.PP
+-Normally, one consults the oracle
+-by fixing the desired question
+-firmly in mind
+-and then casting a set of changes
+-(lines)
+-using yarrow\-stalks
+-or tossed coins.
+-The resulting hexagram
+-will be the answer
+-to the question.
+-.PP
+-Using an algorithm
+-suggested by S. C. Johnson,
+-the Unix
+-.IR oracle " simply reads"
+-a question
+-from the standard input
+-(up to an EOF)
+-and hashes the individual
+-characters
+-in combination with the
+-time of day, process id
+-and any other magic numbers
+-which happen to be lying
+-around the system.
+-The resulting value
+-is used as the seed
+-of a random number generator
+-which drives a simulated
+-coin\-toss divination.
+-The answer is then piped through
+-.BR nroff " for formatting"
+-and will appear on the
+-standard output.
+-.PP
+-For those who wish
+-to remain steadfast
+-in the old traditions,
+-the oracle will also accept
+-the results of a personal
+-divination using,
+-for example,
+-coins.
+-To do this,
+-cast the change
+-and then type the
+-resulting line values
+-as an argument.
+-.PP
+-The impatient modern may prefer to settle for
+-Chinese cookies; try
+-.I fortune.
+-.SH "SEE ALSO"
+-It furthers one to see the great man.
+-.SH DIAGNOSTICS
+-The great prince issues commands,
+-.br
+-Founds states, vests families with fiefs.
+-.br
+-Inferior people should not be employed.
+-.SH BUGS
+-Waiting in the mud
+-.br
+-Brings about the arrival of the enemy.
+-.PP
+-If one is not extremely careful,
+-.br
+-Somebody may come up from behind and strike him.
+-.br
+-Misfortune.
+//GO.SYSIN DD ching.6
+echo cubic.6
+sed 's/.//' >cubic.6 <<'//GO.SYSIN DD cubic.6'
+-.so /usr/man/man6/ttt.6
+//GO.SYSIN DD cubic.6
+echo maze.6
+sed 's/.//' >maze.6 <<'//GO.SYSIN DD maze.6'
+-.TH MAZE 6 
+-.SH NAME
+-maze \- generate a maze problem
+-.SH SYNOPSIS
+-.B /usr/games/maze/
+-.SH DESCRIPTION
+-.I Maze
+-asks a few questions and then
+-prints a maze.
+-.SH BUGS
+-Some mazes (especially small ones)
+-have no solutions.
+//GO.SYSIN DD maze.6
+echo moo.6
+sed 's/.//' >moo.6 <<'//GO.SYSIN DD moo.6'
+-.TH MOO 6 
+-.SH NAME
+-moo \- guessing game
+-.SH SYNOPSIS
+-.B /usr/games/moo
+-.SH DESCRIPTION
+-.I Moo
+-is a guessing game imported from England.
+-The computer picks a number consisting
+-of four distinct decimal digits.
+-The player guesses four distinct digits
+-being scored on each guess.
+-A `cow' is a correct digit in an incorrect position.
+-A `bull' is a correct digit in a correct position.
+-The game continues until the player guesses the number
+-(a score of four bulls).
+//GO.SYSIN DD moo.6
+echo quiz.6
+sed 's/.//' >quiz.6 <<'//GO.SYSIN DD quiz.6'
+-.TH QUIZ 6 
+-.SH NAME
+-quiz \- test your knowledge
+-.SH SYNOPSIS
+-.B /usr/games/quiz
+-[
+-.B \-i
+-file ]
+-[
+-.B \-t
+-] [ category1 category2 ]
+-.SH DESCRIPTION
+-.I Quiz
+-gives associative
+-knowledge tests on various subjects.
+-It asks items chosen from
+-.I category1
+-and expects answers from
+-.IR category2 .
+-If no categories are specified,
+-.I quiz
+-gives instructions
+-and lists the available categories.
+-.PP
+-.I Quiz
+-tells a correct answer whenever you type
+-a bare newline.
+-At the end of input, upon interrupt,
+-or when questions run out,
+-.I quiz
+-reports a score and terminates.
+-.PP
+-The
+-.B \-t
+-flag specifies `tutorial' mode,
+-where missed questions are repeated
+-later, and material is gradually introduced as you learn.
+-.PP
+-The
+-.B \-i
+-flag causes the named file to be substituted for the
+-default index file.
+-The lines of these files have the  syntax:
+-.IP "" 4
+-.nf
+-.ta \w'alternate 'u
+-line  = category newline \(bv category `:' line
+-category      = alternate \(bv category `|' alternate
+-alternate     = empty \(bv alternate primary
+-primary       = character \(bv `[' category `]' \(bv option
+-option        = `{' category `}'
+-.PP
+-.fi
+-The first category on each
+-line of an index file names an information file.
+-The remaining categories specify the order and contents of
+-the data in each line of the
+-information file.
+-Information files have the same syntax.
+-Backslash `\\' is used as with
+-.IR sh (1)
+-to quote syntactically
+-significant characters or to insert transparent
+-newlines into a line.
+-When either a question or its answer is empty,
+-.I quiz
+-will refrain from asking it.
+-.SH FILES
+-/usr/games/quiz.k/*
+-.SH BUGS
+-The construct `a|ab' doesn't work in an information
+-file.
+-Use `a{b}'.
+//GO.SYSIN DD quiz.6
+echo reversi.6
+sed 's/.//' >reversi.6 <<'//GO.SYSIN DD reversi.6'
+-.TH REVERSI 6 
+-.SH NAME
+-reversi \- a game of dramatic reversals
+-.SH SYNOPSIS
+-.B /usr/games/reversi
+-[ [
+-.B \-r
+-]
+-.I file
+-]
+-.SH DESCRIPTION
+-.I Reversi
+-(also known as `friends',
+-`Chinese friends' and `Othello')
+-is played on an 8\(mu8 board
+-using two-sided tokens.
+-Each player takes his turn by placing
+-a token with his side up in an empty square.
+-During the first four turns, players
+-may only place tokens in the four central squares
+-of the board.
+-Subsequently, with each turn, a player
+-.I must
+-capture one or more
+-of his opponent's tokens.
+-He does this by placing
+-one of his tokens such that
+-it and another of his tokens embrace
+-a solid line of his opponent's
+-horizontally, vertically or diagonally.
+-Captured tokens are flipped over
+-and thus can be re-captured.
+-If a player cannot outflank
+-his opponent he forfeits
+-his turn.
+-The play continues until the
+-board is filled or until no more
+-outflanking is possible.
+-.PP
+-In this game,
+-your tokens are asterisks
+-and the machine's are at-signs.
+-You move by typing in the row and column
+-at which you want to place your token
+-as two digits (1-8),
+-optionally separated by blanks or tabs.
+-You can also type
+-.TP
+-.B  c
+-to continue the game after hitting break
+-(this is only necessary if you interrupt the machine
+-while it is deliberating).
+-.TP
+-.BR g " \fIn"
+-to start
+-.I reversi
+-playing against itself
+-for the next
+-.IR n ""
+-moves
+-(or until the break key is hit).
+-.TP
+-.B  n
+-to stop printing the board after each move.
+-.TP
+-.B  o
+-to start it up again.
+-.TP
+-.B  p
+-to print the board regardless.
+-.TP
+-.B  q
+-to quit (without dishonor).
+-.TP
+-.B  s
+-to print the score.
+-.PP
+-.I Reversi
+-also recognizes several commands which are valid only
+-at the start of the game, before any moves have been made.
+-They are
+-.TP
+-.B  f
+-to let the machine go first.
+-.TP
+-.BR h " \fIn"
+-to ask for a handicap
+-of from one to four corner squares.
+-If you're
+-good, you can give the machine
+-a handicap by typing a negative number.
+-.TP
+-.BR l " \fIn"
+-to set the amount of lookahead
+-used by the machine in searching for moves.
+-Zero means none at all. Four is the default.
+-Greater than six means you may fall asleep
+-waiting for the machine to move.
+-.TP
+-.BR t " \fIn"
+-to tell
+-.I reversi
+-that you will only need
+-.IR n ""
+-seconds
+-to consider each move. If you fail to respond in the
+-alloted time, you forfeit your turn.
+-.PP
+-If
+-.I reversi
+-is given a file name as an argument,
+-it will checkpoint the game,
+-move by move, by dumping the board onto
+-.IR file .
+-The
+-.B \-r
+-option will cause
+-.I reversi
+-to restart the game from
+-.I file
+-and continue logging.
+//GO.SYSIN DD reversi.6
+echo ttt.6
+sed 's/.//' >ttt.6 <<'//GO.SYSIN DD ttt.6'
+-.TH TTT 6 
+-.SH NAME
+-ttt, cubic \- tic-tac-toe
+-.SH SYNOPSIS
+-.B /usr/games/ttt
+-.PP
+-.B /usr/games/cubic
+-.SH DESCRIPTION
+-.I Ttt
+-is the X and O game popular in the first grade.
+-This is a learning program that never makes the same
+-mistake twice.
+-.PP
+-Although it learns, it learns slowly.
+-It must lose nearly 80 games to
+-completely know the game.
+-.PP
+-.I Cubic
+-plays three-dimensional tic-tac-toe on a 4\(mu4\(mu4
+-board.
+-Moves are specified as a sequence of three
+-coordinate numbers in the range 1-4.
+-.SH FILES
+-/usr/games/ttt.k      learning file
+//GO.SYSIN DD ttt.6
+echo words.6
+sed 's/.//' >words.6 <<'//GO.SYSIN DD words.6'
+-.TH WORDS 6 
+-.SH NAME
+-hangman, words \- word games
+-.SH SYNOPSIS
+-.B /usr/games/hangman
+-[ dict ]
+-.PP
+-.B /usr/games/words
+-.SH DESCRIPTION
+-.I Hangman
+-chooses a word at least seven letters
+-long from a word list.
+-The user is to guess letters one at a time.
+-.PP
+-The optional argument
+-names an alternate word list.
+-The special name `\-a' gets a particular very large
+-word list.
+-.PP
+-.I Words
+-prints all the uncapitalized words
+-in the word list that can be made from
+-letters in
+-.I string.
+-.SH FILES
+-/usr/dict/words               the regular word list
+-.br
+-/crp/dict/web2                the the \-a word list
+-.SH DIAGNOSTICS
+-After each round,
+-.I hangman
+-reports the average number of guesses per round
+-and the number of rounds.
+-.SH BUGS
+-Hyphenated compounds are run together.
+-.PP
+-UNIX software is distributed without
+-the \-a word list.
+//GO.SYSIN DD words.6
+echo wump.6
+sed 's/.//' >wump.6 <<'//GO.SYSIN DD wump.6'
+-.TH WUMP 6 
+-.SH NAME
+-wump \- the game of hunt-the-wumpus
+-.SH SYNOPSIS
+-.B /usr/games/wump
+-.SH DESCRIPTION
+-.I Wump
+-plays the game of `Hunt the Wumpus.'
+-A Wumpus is a creature that lives in a cave with several rooms
+-connected by tunnels.
+-You wander among the rooms, trying to
+-shoot the Wumpus with an arrow, meanwhile avoiding
+-being eaten by the Wumpus and falling
+-into
+-Bottomless Pits.
+-There are also Super Bats which are likely to pick you up
+-and drop you in some random room.
+-.PP
+-The program asks various questions which you answer
+-one per line;
+-it will give a more detailed description
+-if you want.
+-.PP
+-This program is based on one described in
+-.I "People's Computer Company,"
+-.I 2,
+-2 (November 1973).
+-.SH BUGS
+-It will never replace Space War.
+//GO.SYSIN DD wump.6
diff --git a/doc/7thEdMan/vol1/man7.bun b/doc/7thEdMan/vol1/man7.bun
new file mode 100644 (file)
index 0000000..4e5ea25
--- /dev/null
@@ -0,0 +1,1301 @@
+# To unbundle, run this file
+echo ascii.7
+sed 's/.//' >ascii.7 <<'//GO.SYSIN DD ascii.7'
+-.TH ASCII 7 
+-.SH NAME
+-ascii \- map of ASCII character set
+-.SH SYNOPSIS
+-.B cat /usr/pub/ascii
+-.SH DESCRIPTION
+-.I Ascii
+-is a map of the ASCII character set, to be printed as needed.
+-It contains:
+-.nf
+-
+-.cs R 20
+-|000 nul|001 soh|002 stx|003 etx|004 eot|005 enq|006 ack|007 bel|
+-|010 bs |011 ht |012 nl |013 vt |014 np |015 cr |016 so |017 si |
+-|020 dle|021 dc1|022 dc2|023 dc3|024 dc4|025 nak|026 syn|027 etb|
+-|030 can|031 em |032 sub|033 esc|034 fs |035 gs |036 rs |037 us |
+-|040 sp |041  ! |042  " |043  # |044  $ |045  % |046  & |047  \' |
+-|050  ( |051  ) |052  * |053  + |054  , |055  \- |056  . |057  / |
+-|060  0 |061  1 |062  2 |063  3 |064  4 |065  5 |066  6 |067  7 |
+-|070  8 |071  9 |072  : |073  ; |074  < |075  = |076  > |077  ? |
+-|100  @ |101  A |102  B |103  C |104  D |105  E |106  F |107  G |
+-|110  H |111  I |112  J |113  K |114  L |115  M |116  N |117  O |
+-|120  P |121  Q |122  R |123  S |124  T |125  U |126  V |127  W |
+-|130  X |131  Y |132  Z |133  [ |134  \\ |135  ] |136  ^ |137  _ |
+-|140  \` |141  a |142  b |143  c |144  d |145  e |146  f |147  g |
+-|150  h |151  i |152  j |153  k |154  l |155  m |156  n |157  o |
+-|160  p |161  q |162  r |163  s |164  t |165  u |166  v |167  w |
+-|170  x |171  y |172  z |173  { |174  | |175  } |176  ~ |177 del|
+-
+-.fi
+-.cs R
+-.SH FILES
+-/usr/pub/ascii
+//GO.SYSIN DD ascii.7
+echo eqnchar.7
+sed 's/.//' >eqnchar.7 <<'//GO.SYSIN DD eqnchar.7'
+-.EQ
+-tdefine ciplus % "\o'\(pl\(ci'" %
+-ndefine ciplus % O\b+ %
+-tdefine citimes % "\o'\(mu\(ci'" %
+-ndefine citimes % O\bx %
+-tdefine =wig % "\(eq\h'-\w'\(eq'u-\w'\s-2\(ap'u/2u'\v'-.4m'\s-2\z\(ap\(ap\s+2\v'.4m'\h'\w'\(eq'u-\w'\s-2\(ap'u/2u'" %
+-ndefine =wig % =\b"~" %
+-tdefine bigstar % "\o'\(pl\(mu'" %
+-ndefine bigstar % X\b|\b- %
+-tdefine =dot % "\z\(eq\v'-.6m'\h'.2m'\s+2.\s-2\v'.6m'\h'.1m'" %
+-ndefine =dot % = dot %
+-tdefine orsign % "\s-2\v'-.15m'\z\e\e\h'-.05m'\z\(sl\(sl\v'.15m'\s+2" %
+-ndefine orsign % \e/ %
+-tdefine andsign % "\s-2\v'-.15m'\z\(sl\(sl\h'-.05m'\z\e\e\v'.15m'\s+2" %
+-ndefine andsign % /\e %
+-tdefine =del % "\v'.3m'\z=\v'-.6m'\h'.3m'\s-1\(*D\s+1\v'.3m'" %
+-ndefine =del % = to DELTA %
+-tdefine oppA % "\s-2\v'-.15m'\z\e\e\h'-.05m'\z\(sl\(sl\v'-.15m'\h'-.75m'\z-\z-\h'.2m'\z-\z-\v'.3m'\h'.4m'\s+2" %
+-ndefine oppA % V\b- %
+-tdefine oppE %"\s-3\v'.2m'\z\(em\v'-.5m'\z\(em\v'-.5m'\z\(em\v'.55m'\h'.9m'\z\(br\z\(br\v'.25m'\s+3" %
+-ndefine oppE % E\b/ %
+-tdefine incl % "\s-1\z\(or\h'-.1m'\v'-.45m'\z\(em\v'.7m'\z\(em\v'.2m'\(em\v'-.45m'\s+1" %
+-ndefine incl % C\b_ %
+-tdefine nomem % "\o'\(mo\(sl'" %
+-ndefine nomem % C\b-\b/ %
+-tdefine angstrom % "\fR\zA\v'-.3m'\h'.2m'\(de\v'.3m'\fP\h'.2m'" %
+-ndefine angstrom % A to o %
+-tdefine star %{ roman "\v'.5m'\s+3*\s-3\v'-.5m'"}%
+-ndefine star % * %
+-tdefine || % \(or\(or %
+-tdefine <wig % "\z<\v'.4m'\(ap\v'-.4m'" %
+-ndefine <wig %{ < from "~" }%
+-tdefine >wig % "\z>\v'.4m'\(ap\v'-.4m'" %
+-ndefine >wig %{ > from "~" }%
+-tdefine langle % "\s-3\b'\(sl\e'\s0" %
+-ndefine langle %<%
+-tdefine rangle % "\s-3\b'\e\(sl'\s0" %
+-ndefine rangle %>%
+-tdefine hbar % "\zh\v'-.6m'\h'.05m'\(ru\v'.6m'" %
+-ndefine hbar % h\b\u-\d %
+-ndefine ppd % _\b| %
+-tdefine ppd % "\o'\(ru\s-2\(or\s+2'" %
+-tdefine <-> % "\o'\(<-\(->'" %
+-ndefine <-> % "<-->" %
+-tdefine <=> % "\s-2\z<\v'.05m'\h'.2m'\z=\h'.55m'=\h'-.6m'\v'-.05m'>\s+2" %
+-ndefine <=> % "<=>" %
+-tdefine |< % "\o'<\(or'" %
+-ndefine |< % <\b| %
+-tdefine |> % "\o'>\(or'" %
+-ndefine |> % |\b> %
+-tdefine ang % "\v'-.15m'\z\s-2\(sl\s+2\v'.15m'\(ru" %
+-ndefine ang % /\b_ %
+-tdefine rang % "\z\(or\h'.15m'\(ru" %
+-ndefine rang % L %
+-tdefine 3dot % "\v'-.8m'\z.\v'.5m'\z.\v'.5m'.\v'-.2m'" %
+-ndefine 3dot % .\b\u.\b\u.\d\d %
+-tdefine thf % ".\v'-.5m'.\v'.5m'." %
+-ndefine thf % ..\b\u.\d %
+-tdefine quarter % roman \(14 %
+-ndefine quarter % 1/4 %
+-tdefine 3quarter % roman \(34 %
+-ndefine 3quarter % 3/4 %
+-tdefine degree % \(de %
+-ndefine degree % nothing sup o %
+-tdefine square % \(sq %
+-ndefine square % [] %
+-tdefine circle % \(ci %
+-ndefine circle % O %
+-tdefine blot % "\fB\(sq\fP" %
+-ndefine blot % H\bI\bX %
+-tdefine bullet % \(bu %
+-ndefine bullet % o\bx\be %
+-tdefine -wig % "\(~=" %
+-ndefine -wig % - to "~" %
+-tdefine wig % \(ap %
+-ndefine wig % "~" %
+-tdefine prop % \(pt %
+-ndefine prop % oc %
+-tdefine empty % \(es %
+-ndefine empty % O\b/ %
+-tdefine member % \(mo %
+-ndefine member % C\b- %
+-tdefine cup % \(cu %
+-ndefine cup % U %
+-define cap % \(ca %
+-define subset % \(sb %
+-define supset % \(sp %
+-define !subset % \(ib %
+-define !supset % \(ip %
+-.EN
+-.TH EQNCHAR 7 
+-.SH NAME
+-eqnchar \- special character definitions for eqn
+-.SH SYNOPSIS
+-.B eqn /usr/pub/eqnchar
+-[ files ]
+-.B \(bv troff
+-[ options ]
+-.PP
+-.B neqn /usr/pub/eqnchar
+-[ files ]
+-.B \(bv nroff
+-[ options ]
+-.SH DESCRIPTION
+-.I Eqnchar
+-contains
+-.I troff
+-and
+-.I nroff
+-character definitions for constructing characters that are not
+-available on the Graphic Systems typesetter.
+-These definitions are primarily intended for use with
+-.I eqn
+-and
+-.IR neqn .
+-It contains
+-definitions for the following characters
+-.PP
+-.nf
+-.ta \w'angstrom  'u \n(.lu/3u +\w'angstrom  'u \n(.lu*2u/3u +\w'angstrom  'u
+-.EQ
+-"ciplus"      ciplus  "|\||"  ||      "square"        square
+-.EN
+-.EQ
+-"citimes"     citimes "langle"        langle  "circle"        circle
+-.EN
+-.EQ
+-"wig" wig     "rangle"        rangle  "blot"  blot
+-.EN
+-.EQ
+-"-wig"        -wig    "hbar"  hbar    "bullet"        bullet
+-.EN
+-.EQ
+-">wig"        >wig    "ppd"   ppd     "prop"  prop
+-.EN
+-.EQ
+-"<wig"        <wig    "<->"   <->     "empty" empty
+-.EN
+-.EQ
+-"=wig"        =wig    "<=>"   <=>     "member"        member
+-.EN
+-.EQ
+-"star"        star    "|\|"   |<      "nomem" nomem
+-.EN
+-.EQ
+-"bigstar"     bigstar "|\|>"  |>      "cup"   cup
+-.EN
+-.EQ
+-"=dot"        =dot    "ang"   ang     "cap"   cap
+-.EN
+-.EQ
+-"orsign"      orsign  "rang"  rang    "incl"  incl
+-.EN
+-.EQ
+-"andsign"     andsign "3dot"  3dot    "subset"        subset
+-.EN
+-.EQ
+-"=del"        =del    "thf"   thf     "supset"        supset
+-.EN
+-.EQ
+-"oppA"        oppA    "quarter"       quarter "!subset"       !subset
+-.EN
+-.EQ
+-"oppE"        oppE    "3quarter"      3quarter        "!supset"       !supset
+-.EN
+-.EQ
+-"angstrom"    angstrom        "degree"        degree
+-.EN
+-.SH FILES
+-/usr/pub/eqnchar
+-.SH SEE ALSO
+-troff(1), eqn(1)
+//GO.SYSIN DD eqnchar.7
+echo hier.7
+sed 's/.//' >hier.7 <<'//GO.SYSIN DD hier.7'
+-.TH HIER 7
+-.SH NAME
+-hier \- file system hierarchy
+-.SH DESCRIPTION
+-The following outline gives a quick tour through
+-a representative directory hierarchy.
+-.na
+-.nh
+-.IP /
+-root
+-.PD 0
+-.IP /dev/
+-devices (4)
+-.RS
+-.IP console
+-main console,
+-.IR tty (4)
+-.IP tty*
+-terminals,
+-.IR tty (4)
+-.IP cat
+-phototypesetter
+-.IR cat (4)
+-.IP rp*
+-disks,
+-.I rp,
+-.IR hp (4)
+-.IP rrp*
+-raw disks,
+-.I rp,
+-.IR hp (4)
+-.IP ...
+-.RE
+-.IP /bin/
+-utility programs, cf /usr/bin/ (1)
+-.RS
+-.IP as
+-assembler first pass,
+-cf /usr/lib/as2
+-.IP cc
+-C compiler executive,
+-cf /usr/lib/c[012]
+-.IP ...
+-.RE
+-.IP /lib/
+-object libraries and other stuff, cf /usr/lib/
+-.RS
+-.IP libc.a
+-system calls, standard I/O, etc. (2,3,3S)
+-.IP libm.a
+-math routines (3M)
+-.IP libplot.a
+-plotting routines,
+-.IR plot (3)
+-.IP libF77.a
+-Fortran runtime support
+-.IP libI77.a
+-Fortran I/O
+-.IP ...
+-.IP as2
+-second pass of
+-.IR as (1)
+-.IP c[012]
+-passes of
+-.IR cc (1)
+-.IP ...
+-.RE
+-.IP /etc/
+-essential data and dangerous maintenance utilities
+-.RS
+-.IP passwd
+-password file,
+-.IR passwd (5)
+-.IP group
+-group file,
+-.IR group (5)
+-.IP motd
+-message of the day,
+-.IR login (1)
+-.IP mtab
+-mounted file table,
+-.IR mtab (5)
+-.IP ddate
+-dump history,
+-.IR dump (1)
+-.IP ttys
+-properties of terminals,
+-.IR ttys (5)
+-.IP getty
+-part of
+-.IR login ,
+-.IR getty (8)
+-.IP init
+-the father of all processes,
+-.IR init (8)
+-.IP rc
+-shell program to bring the system up
+-.IP cron
+-the clock daemon,
+-.IR cron (8)
+-.IP mount
+-.IR mount (1)
+-.IP wall
+-.IR wall (1)
+-.IP ...
+-.RE
+-.IP /tmp/
+-temporary files, usually on a fast device, cf /usr/tmp/
+-.RS
+-.IP e*
+-used by
+-.IR ed (1)
+-.IP ctm*
+-used by 
+-.IR cc (1)
+-.IP ...
+-.RE
+-.IP /usr/
+-general-pupose directory, usually a mounted file system
+-.RS
+-.IP adm/
+-administrative information
+-.RS
+-.IP wtmp
+-login history,
+-.IR utmp (5)
+-.IP messages
+-hardware error messages
+-.IP tracct
+-phototypesetter accounting,
+-.IR troff (1)
+-.IP vpacct
+-line printer accounting
+-.IR lpr (1)
+-.RE
+-.RE
+-.IP /usr\t/bin
+-.RS
+-utility programs, to keep /bin/ small
+-.IP tmp/
+-temporaries, to keep /tmp/ small
+-.RS
+-.IP stm*
+-used by
+-.IR sort (1)
+-.IP raster
+-used by
+-.IR plot (1)
+-.RE
+-.IP dict/
+-word lists, etc.
+-.RS
+-.IP words
+-principal word list, used by
+-.IR look (1)
+-.IP spellhist
+-history file for
+-.IR spell (1)
+-.RE
+-.IP games/
+-.RS
+-.IP bj
+-blackjack
+-.IP hangman
+-.IP quiz.k/
+-what
+-.IR quiz (6)
+-knows
+-.RS
+-.IP index
+-category index
+-.IP africa
+-countries and capitals
+-.IP ...
+-.RE
+-.IP ...
+-.RE
+-.IP include/
+-standard #include files
+-.RS
+-.IP a.out.h
+-object file layout,
+-.IR a.out (5)
+-.IP stdio.h
+-standard I/O,
+-.IR stdio (3)
+-.IP math.h
+-(3M)
+-.IP ...
+-.IP sys/
+-system-defined layouts, cf /usr/sys/h
+-.RS
+-.IP acct.h
+-process accounts,
+-.IR acct (5)
+-.IP buf.h
+-internal system buffers
+-.IP ...
+-.RE
+-.RE
+-.IP lib/
+-object libraries and stuff, to keep /lib/ small
+-.RS
+-.IP lint[12]
+-subprocesses for
+-.IR lint (1)
+-.IP llib-lc
+-dummy declarations for /lib/libc.a, used by
+-.IR lint (1)
+-.IP llib-lm
+-dummy declarations for /lib/libc.m
+-.IP atrun
+-scheduler for
+-.IR at (1)
+-.IP struct/
+-passes of
+-.IR struct (1)
+-.IP ...
+-.IP tmac/
+-macros for
+-.IR troff (1)
+-.RS
+-.IP tmac.an
+-macros for
+-.IR man (7)
+-.IP tmac.s
+-macros for
+-.IR ms (7)
+-.IP ...
+-.RE
+-.IP font/
+-fonts for
+-.IR troff (1)
+-.RS
+-.IP R
+-Times Roman
+-.IP B
+-Times Bold
+-.IP ...
+-.RE
+-.IP uucp/
+-programs and data for
+-.IR uucp (1)
+-.RS
+-.IP L.sys
+-remote system names and numbers
+-.IP uucico
+-the real copy program
+-.IP ...
+-.RE
+-.IP suftab
+-table of suffixes for hyphenation, used by
+-.IR troff (1)
+-.IP units
+-conversion tables for
+-.IR units (1)
+-.IP eign
+-list of English words to be ignored by
+-.IR ptx (1)
+-.RE
+-.RE
+-.IP /usr/\tman/
+-.RS
+-volume 1 of this manual,
+-.IR man (1)
+-.RS
+-.IP man0/
+-general
+-.RS
+-.IP intro
+-introduction to volume 1,
+-.IR ms (7)
+-format
+-.IP xx
+-template for manual page
+-.RE
+-.IP man1/
+-chapter 1
+-.RS
+-.IP as.1
+-.IP mount.1m
+-.IP ...
+-.RE
+-.IP cat1/
+-preprinted pages for man1/
+-.RS
+-.IP as.1
+-.IP mount.1m
+-.RE
+-.IP ...
+-.RE
+-.IP spool/
+-delayed execution files
+-.RS
+-.IP at/
+-used by 
+-.IR at (1)
+-.IP lpd/
+-used by
+-.IR lpr (1)
+-.RS
+-.IP lock
+-present when line printer is active
+-.IP cf*
+-copy of file to be printed, if necessary
+-.IP df*
+-daemon control file,
+-.IR lpd (8)
+-.IP tf*
+-transient control file, while 
+-.I lpr
+-is working
+-.RE
+-.IP uucp/
+-work files and staging area for 
+-.IR uucp (1)
+-.RS
+-.IP LOGFILE
+-summary log
+-.IP LOG.*
+-log file for one transaction
+-.RE
+-.RE
+-.IP mail/
+-mailboxes for
+-.IR mail (1)
+-.RS
+-.TP
+-.I uid
+-mail file for user
+-.I uid
+-.TP
+-.IR uid .lock
+-lock file while
+-.I uid
+-is receiving mail
+-.RE
+-.TP
+-.I wd
+-initial working directory of a user,
+-typically
+-.I wd
+-is the user's login name
+-.RS
+-.TP
+-.BR . profile
+-set environment for
+-.IR sh (1),
+-.IR environ (5)
+-.IP calendar
+-user's datebook for
+-.IR calendar (1)
+-.RE
+-.IP doc/
+-papers, mostly in volume 2 of this manual, typically in
+-.IR ms (7)
+-format
+-.RS
+-.IP as/
+-assembler manual
+-.IP c
+-C manual
+-.IP ...
+-.RE
+-.IP sys/
+-system source
+-.RS
+-.IP dev/
+-device drivers
+-.RS
+-.IP bio.c
+-common code
+-.IP cat.c
+-.IR cat (4)
+-.IP dh.c
+-DH11,
+-.IR tty (4)
+-.IP tty
+-.IR tty (4)
+-.IP ...
+-.RE
+-.IP conf/
+-hardware-dependent code
+-.RS
+-.IP mch.s
+-assembly language portion
+-.IP conf
+-configuration generator
+-.IP ...
+-.RE
+-.IP h/
+-header (include) files
+-.RS
+-.IP acct.h
+-.IR acct (5)
+-.IP stat.h
+-.IR stat (2)
+-.IP ...
+-.RE
+-.IP sys/
+-source for system proper
+-.RS
+-.IP main.c
+-.IP pipe.c
+-.IP sysent.c
+-system entry points
+-.IP ...
+-.RE
+-.RE
+-.RE
+-.IP /usr/\tsrc/
+-.RS
+-source programs for utilities, etc.
+-.RS
+-.IP cmd/
+-source of commands
+-.RS
+-.IP as/
+-assembler
+-.RS
+-.IP makefile
+-recipe for rebuilding the assembler
+-.IP as1?.s
+-source of pass1
+-.RE
+-.IP ar.c
+-source for
+-.IR ar (1)
+-.IP ...
+-.IP troff/
+-source for
+-.I nroff
+-and
+-.IR troff (1)
+-.RS
+-.IP nmake
+-makefile for
+-.I nroff
+-.IP tmake
+-makefile for
+-.I troff
+-.IP font/
+-source for font tables, /usr/lib/font/
+-.RS
+-.IP ftR.c
+-Roman
+-.IP ...
+-.RE
+-.IP term/
+-terminal characteristics tables, /usr/lib/term/
+-.RS
+-.IP tab300.c
+-DASI 300
+-.IP ...
+-.RE
+-.IP ...
+-.RE
+-.RE
+-.IP libc/
+-source for functions in /lib/libc.a
+-.RS
+-.IP crt/
+-C runtime support
+-.RS
+-.IP ldiv.s
+-division into a long
+-.IP lmul.s
+-multiplication to produce long
+-.IP ...
+-.RE
+-.IP csu/
+-startup and wrapup routines needed with every C program
+-.RS
+-.IP crt0.s
+-regular startup
+-.IP mcrt0.s
+-modified startup for
+-.I cc \-p
+-.RE
+-.IP sys/
+-system calls (2)
+-.RS
+-.IP access.s
+-.IP alarm.s
+-.IP ...
+-.RE
+-.IP stdio/
+-standard I/O functions (3S)
+-.RS
+-.IP fgets.c
+-.IP fopen.c
+-.IP ...
+-.RE
+-.IP gen/
+-other functions in (3)
+-.RS
+-.IP abs.c
+-.IP atof.c
+-.IP ...
+-.RE
+-.IP compall
+-shell procedure to compile libc
+-.IP mklib
+-shell procedure to make /lib/libc.a
+-.RE
+-.IP libI77/
+-source for /lib/libI77
+-.IP libF77/
+-.IP ...
+-.IP games/
+-source for /usr/games
+-.RE
+-.RE
+-.ad
+-.SH SEE ALSO
+-ls(1), ncheck(1), find(1), grep(1)
+-.SH BUGS
+-The position of files is subject to change without notice.
+//GO.SYSIN DD hier.7
+echo man.7
+sed 's/.//' >man.7 <<'//GO.SYSIN DD man.7'
+-.TH MAN 7 
+-.SH NAME
+-man \- macros to typeset manual
+-.SH SYNOPSIS
+-.B
+-nroff  \-man\ 
+-file ...
+-.PP
+-.B
+-troff  \-man\ 
+-file ...
+-.SH DESCRIPTION
+-These macros are used to lay out pages of this manual.
+-A skeleton page may be found in the file 
+-/usr/man/man0/xx.
+-.PP
+-Any text argument
+-.I t
+-may be zero to six words.
+-Quotes may be used to include blanks in a `word'.
+-If 
+-.I text
+-is empty,
+-the special treatment is applied to
+-the next input line with text to be printed.
+-In this way
+-.BR . I
+-may be used to italicize a whole line, or
+-.BR . SM
+-followed by
+-.BR . B
+-to make small bold letters.
+-.PP
+-A prevailing indent distance is remembered between
+-successive indented paragraphs,
+-and is reset to default value upon reaching a non-indented paragraph.
+-Default units for indents
+-.I i
+-are ens.
+-.PP
+-Type font and size are reset to default values
+-before each paragraph, and after processing
+-font and size setting macros.
+-.PP
+-These strings are predefined by
+-.BR \-man :
+-.IP \e*R
+-.if t `\*R', `(Reg)' in
+-.if t .I nroff.
+-.if n `(Reg)', trademark symbol in
+-.if n .I troff.
+-.IP \e*S
+-Change to default type size.
+-.SH FILES
+-/usr/lib/tmac/tmac.an
+-.br
+-/usr/man/man0/xx
+-.SH SEE ALSO
+-troff(1), man(1)
+-.SH BUGS
+-Relative indents don't nest.
+-.SH REQUESTS
+-.ta \w'.TH n c x 'u +\w'Cause 'u +\w'Argument\ 'u
+-.di xx
+-                      \ka
+-.br
+-.di
+-.in \nau
+-.ti0
+-Request       Cause   If no   Explanation
+-.ti0
+-      Break   Argument
+-.ti0
+-.li
+-.B \fIt\fR    no      \fIt\fR=n.t.l.* Text
+-.I t
+-is bold.
+-.ti0
+-.li
+-.BI \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating bold and italic.
+-.ti0
+-.li
+-.BR \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating bold and Roman.
+-.ti0
+-.li
+-.DT   no      .5i 1i...       Restore default tabs.
+-.ti0
+-.li
+-.HP \fIi\fR   yes     \fIi\fR=p.i.*   Set prevailing indent to
+-.I i.
+-Begin paragraph with hanging indent.
+-.ti0
+-.li
+-.I \fIt\fR    no      \fIt\fR=n.t.l.  Text
+-.I t
+-is italic.
+-.ti0
+-.li
+-.IB \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating italic and bold.
+-.ti0
+-.li
+-.IP \fIx i\fR yes     \fIx\fR=""      Same as .TP with tag
+-.I x.
+-.ti0
+-.li
+-.IR \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating italic and Roman.
+-.ti0
+-.li
+-.LP   yes     -       Same as .PP.
+-.ti0
+-.li
+-.PD \fId\fR   no      \fId\fR=.4v     Interparagraph distance is 
+-.I d.
+-.ti0
+-.li
+-.PP   yes     -       Begin paragraph.
+-Set prevailing indent to .5i.
+-.ti0
+-.li
+-.RE   yes     -       End of relative indent.
+-Set prevailing indent to amount of starting .RS.
+-.ti0
+-.li
+-.RB \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating Roman and bold.
+-.ti0
+-.li
+-.RI \fIt\fR   no      \fIt\fR=n.t.l.  Join
+-words of
+-.I t
+-alternating Roman and italic.
+-.ti0
+-.li
+-.RS \fIi\fR   yes     \fIi\fR=p.i.    Start relative indent,
+-move left margin in distance
+-.I i.
+-Set prevailing indent to .5i for nested indents.
+-.ti0
+-.li
+-.SH \fIt\fR   yes     \fIt\fR=n.t.l.  Subhead.
+-.ti0
+-.li
+-.SM \fIt\fR   no      \fIt\fR=n.t.l.  Text
+-.I t
+-is small.
+-.ti0
+-.li
+-.TH \fIn c x\fR       yes     -       Begin page named
+-.I n
+-of chapter
+-.IR c;
+-.I x
+-is extra commentary, e.g. `local', for page foot.
+-Set prevailing indent and tabs to .5i.
+-.ti0
+-.li
+-.TP \fIi\fR   yes     \fIi\fR=p.i.    Set prevailing indent to
+-.I i.
+-Begin indented paragraph
+-with hanging tag given by next text line.
+-If tag doesn't fit, place it on separate line.
+-.PP
+-.ti0
+-* n.t.l. = next text line; p.i. = prevailing indent
+//GO.SYSIN DD man.7
+echo ms.7
+sed 's/.//' >ms.7 <<'//GO.SYSIN DD ms.7'
+-.hc %
+-.TH MS 7 
+-.SH NAME
+-ms \- macros for formatting manuscripts
+-.SH SYNOPSIS
+-.B "nroff \-ms"
+-[ options ]
+-file ... 
+-.br
+-.B "troff \-ms"
+-[ options ]
+-file ... 
+-.SH DESCRIPTION
+-This package of 
+-.I nroff
+-and
+-.I troff
+-macro definitions provides a canned formatting
+-.li
+-facility for tech%nical papers in various formats.
+-When producing 2-column output on a terminal, filter
+-the output through
+-.IR  col (1).
+-.PP
+-The macro requests are defined below.
+-Many
+-.I nroff
+-and
+-.I troff
+-requests are unsafe in conjunction with
+-this package, however these requests may be used with
+-impunity after the first .PP:
+-.IP
+-.ta \w'.sp n 'u
+-.li
+-.bp   begin new page
+-.nf
+-.li
+-.br   break output line here
+-.li
+-.sp n insert n spacing lines
+-.li
+-.ls n (line spacing) n=1 single, n=2 double space
+-.li
+-.na   no alignment of right margin
+-.fi
+-.PP
+-Output of the
+-.I eqn,
+-.I neqn,
+-.I refer,
+-and
+-.IR  tbl (1)
+-preprocessors
+-for equations and tables is acceptable as input.
+-.SH FILES
+-/usr/lib/tmac/tmac.s
+-.SH "SEE ALSO"
+-eqn(1), troff(1), refer(1), tbl(1)
+-.tr &.
+-.SH REQUESTS 
+-.ta \w'..ND \fIdate\fR 'u +\w'Initial 'u +\w'Cause 'u
+-.br
+-.di x
+-                      \ka
+-.br
+-.di
+-.in \nau
+-.ti0
+-Request       Initial Cause   Explanation
+-.ti0
+-      Value   Break
+-.br
+-.in \nau
+-.ti0
+-.li
+-.1C   yes     yes     One column format on a new page.
+-.ti0
+-.li
+-.2C   no      yes     Two column format.
+-.ti0
+-.li
+-.AB   no      yes     Begin abstract.
+-.ti0
+-.li
+-.AE   -       yes     End abstract.
+-.ti0
+-.li
+-.AI   no      yes     Author's institution follows.
+-Suppressed in TM.
+-.ti0
+-.li
+-.AT   no      yes     Print `\ 1Attached' and turn off line filling.
+-.ti0
+-.li
+-.AU \fIx y\fR no      yes     Author's name follows.
+-.IR x " is location and " "y\fR is"
+-extension, ignored except in TM.
+-.ti0
+-.li
+-.B \fIx\fR    no      no      Print \fIx\fR in boldface; if no argument switch to boldface.
+-.ti 0
+-.li
+-.B1   no      yes     Begin text to be enclosed in a box.
+-.ti0
+-.li
+-.B2   no      yes     End text to be boxed & print it.
+-.ti0
+-.li
+-.BT   date    no      Bottom title, automatically invoked at
+-foot of page.
+-May be redefined.
+-.ti0
+-.li
+-.BX \fIx\fR   no      no      Print \fIx\fR in a box.
+-.ti0
+-.li
+-.CS \fIx...\fR        -       yes     Cover sheet info if
+-TM format, suppressed otherwise.
+-Arguments are number of text pages,
+-other pages, total pages, figures, tables, references.
+-.ti0
+-.li
+-.CT   no      yes     Print `Copies to' and enter no-fill mode.
+-.ti0
+-.li
+-.DA \fIx\fR   nroff   no      `Date line' at bottom of page
+-is
+-.IR x .
+-Default is today.
+-.ti0
+-.li
+-.DE   -       yes     End displayed text.
+-Implies .KE.
+-.ti0
+-.li
+-.DS \fIx\fR   no      yes     Start of displayed text,
+-to appear verbatim line-by-line.
+-.IR x "=I for indented display (default),"
+-.IR x "=L for left-justified on the page,"
+-.IR x "=C for centered,"
+-.IR x "=B for make left-justified block, then center whole block."
+-Implies .KS.
+-.ti0
+-.li
+-.EG   no      -       Print document in BTL format for `Engineer's Notes.'  Must be first.
+-.ti0
+-.li
+-.EN   -       yes     Space after equation
+-produced by
+-.I eqn
+-or
+-.IR neqn .
+-.ti0
+-.li
+-.EQ \fIx y\fR -       yes     Precede equation; break out and
+-add space.
+-Equation number is
+-.IR y .
+-The optional argument \fIx\fR
+-may be
+-.I I
+-to indent equation (default),
+-.I L
+-to left-adjust the equation, or
+-.I C
+-to center the equation.
+-.ti0
+-.li
+-.FE   -       yes     End footnote.
+-.ti0
+-.li
+-.FS   no      no      Start footnote.
+-The note will be moved to the bottom of the page.
+-.ti0
+-.li
+-.HO   -       no      `Bell Laboratories, Holmdel,
+-New Jersey 07733'.
+-.ti0
+-.li
+-.I \fIx\fR    no      no      Italicize \fIx\fR;
+-if \fIx\fR missing, italic text follows.
+-.ti0
+-.li
+-.IH   no      no      `Bell Laboratories, Naperville, Illinois 60540'
+-.ti0
+-.li
+-.IM   no      no      Print document in BTL format for an internal memorandum.  Must be first.
+-.ti0
+-.li
+-.IP \fIx y\fR no      yes     Start indented paragraph,
+-with hanging tag
+-.IR x .
+-Indentation is
+-.IR y ""
+-ens (default 5).
+-.ti0
+-.li
+-.KE   -       yes     End keep.
+-Put kept text on next page if not enough room.
+-.ti0
+-.li
+-.KF   no      yes     Start floating keep.
+-If the kept text must be moved to the next page,
+-float later text back to this page.
+-.ti0
+-.li
+-.KS   no      yes     Start keeping following text.
+-.ti0
+-.li
+-.LG   no      no      Make letters larger.
+-.ti0
+-.li
+-.LP   yes     yes     Start left-blocked paragraph.
+-.ti0
+-.li
+-.MF   -       -       Print document in BTL format for `Memorandum for File.'  Must be first.
+-.ti0
+-.li
+-.MH   -       no      `Bell Laboratories, Murray Hill,
+-New Jersey 07974'.
+-.ti0
+-.li
+-.MR   -       -       Print document in BTL format for `Memorandum for Record.'  Must be first.
+-.ti0
+-.li
+-.ND \fIdate\fR        troff   no      Use date supplied (if any) only in
+-special BTL format positions; omit from page footer.
+-.ti0
+-.li
+-.NH \fIn\fR   -       yes     Same as .SH, with section
+-number supplied automatically.
+-Numbers are multilevel, like 1.2.3,
+-where
+-.IR n ""
+-tells what level is wanted (default is 1).
+-.ti0
+-.li
+-.NL   yes     no      Make letters normal size.
+-.ti0
+-.li
+-.OK   -       yes     `Other keywords' for TM cover
+-sheet follow.
+-.ti0
+-.li
+-.PP   no      yes     Begin paragraph.
+-First line indented.
+-.ti0
+-.li
+-.PT   pg #    -       Page title, automatically invoked at
+-top of page.
+-May be redefined.
+-.ti0
+-.li
+-.PY   -       no      `Bell Laboratories, Piscataway, New Jersey 08854'
+-.ti0
+-.li
+-.QE   -       yes     End quoted (indented and shorter) material.
+-.ti0
+-.li
+-.QP   -       yes     Begin single paragraph which is indented and shorter.
+-.ti0
+-.li
+-.QS   -       yes     Begin quoted (indented and shorter) material.
+-.ti0
+-.li
+-.R    yes     no      Roman text follows.
+-.ti0
+-.li
+-.RE   -       yes     End relative indent level.
+-.ti0
+-.li
+-.RP   no      -       Cover sheet and first page for released
+-paper.
+-Must precede other requests.
+-.ti0
+-.li
+-.RS   -       yes     Start level of relative indentation.
+-Following .IP's are measured from current indentation.
+-.ti0
+-.li
+-.SG \fIx\fR   no      yes     Insert signature(s) of author(s),
+-ignored except in TM.
+-.IR x " is the reference line (initials of author and typist)."
+-.ti0
+-.li
+-.SH   -       yes     Section head follows,
+-font automatically bold.
+-.ti0
+-.li
+-.SM   no      no      Make letters smaller.
+-.ti0
+-.li
+-.TA \fIx\fR...        5...    no      Set tabs in ens.
+-Default is 5 10 15 ...
+-.ti0
+-.li
+-.TE   -       yes     End table.
+-.ti0
+-.li
+-.TH   -       yes     End heading section of table.
+-.ti0
+-.li
+-.TL   no      yes     Title follows.
+-.ti0
+-.li
+-.TM \fIx\fR...        no      -       Print document in BTL technical memorandum format.
+-Arguments are TM number, (quoted list of) case number(s), and file number.
+-Must precede other requests.
+-.ti0
+-.li
+-.TR \fIx\fR   -       -       Print in BTL technical report format; report number is \fIx\fR.  Must be first.
+-.ti0
+-.li
+-.TS \fIx\fR   -       yes     Begin table; if \fIx\fR is
+-.I H
+-table has repeated heading.
+-.ti0
+-.li
+-.UL \fIx\fR   -       no      Underline argument (even in troff).
+-.ti0
+-.li
+-.UX   -       no      `UNIX'; first time used, add footnote `UNIX is a trademark of
+-Bell Laboratories.'
+-.ti0
+-.li
+-.WH   -       no      `Bell Laboratories, Whippany,
+-New Jersey 07981'.
+//GO.SYSIN DD ms.7
+echo term.7
+sed 's/.//' >term.7 <<'//GO.SYSIN DD term.7'
+-.TH TERM 7 
+-.SH NAME
+-terminals\- conventional names
+-.SH DESCRIPTION
+-These names
+-are used by certain commands and are maintained 
+-as part of the shell environment
+-(see
+-.IR sh (1), environ (5)).
+-.LP
+-.nf
+-.ta \w'450\-12\-8  'u
+-1620  DIABLO 1620 (and others using HyType II)
+-1620\-12      same, in 12-pitch mode
+-300   DASI/DTC/GSI 300 (and others using HyType I)
+-300\-12       same, in 12-pitch mode
+-300s  DASI/DTC 300/S
+-300s\-12      same, in 12-pitch mode
+-33    TELETYPE\*R Model 33
+-37    TELETYPE Model 37
+-40\-2 TELETYPE Model 40/2
+-43    TELETYPE Model 43
+-450   DASI 450 (same as Diablo 1620)
+-450\-12       same, in 12-pitch mode
+-450\-12\-8    same, in 12-pitch, 8 lines/inch mode
+-735   Texas Instruments TI735 (and TI725)
+-745   Texas Instruments TI745
+-dumb  terminals with no special features
+-hp    Hewlett-Packard HP264? series terminals
+-4014  Tektronix 4014
+-tn1200        General Electric TermiNet 1200
+-tn300 General Electric TermiNet 300
+-vt05  Digital Equipment Corp. VT05
+-.fi
+-.PP
+-Commands whose behavior may depend on the terminal
+-accept arguments of the form
+-.BR \-Tterm,
+-where
+-.I term
+-is one of the names given above.
+-If no such argument is present,
+-a command may consult the shell environment
+-for the terminal type.
+-.SH SEE ALSO
+-stty(1), tabs(1), plot(1),
+-sh(1), environ(5)
+-.br
+-troff(1) for
+-.I nroff
+-.SH BUGS
+-The programs that ought to adhere to this nomenclature
+-do so only fitfully.
+//GO.SYSIN DD term.7
diff --git a/doc/7thEdMan/vol1/man8.bun b/doc/7thEdMan/vol1/man8.bun
new file mode 100644 (file)
index 0000000..c6143c3
--- /dev/null
@@ -0,0 +1,856 @@
+# To unbundle, run this file
+echo boot.8
+sed 's/.//' >boot.8 <<'//GO.SYSIN DD boot.8'
+-.TH BOOT 8
+-.SH NAME
+-boot \- startup procedures
+-.SH DESCRIPTION
+-A PDP11/45 and PDP11/70 UNIX system is started by
+-a two-stage process.
+-The first is a primary bootstrap
+-which is able to read in relatively small stand-alone programs;
+-the second (called
+-.IR boot )
+-is used to read in the system itself.
+-.PP
+-The primary bootstrap must reside
+-in the otherwise unused block zero of the boot device.
+-It can be read in and started by the standard ROM
+-programs,
+-or if necessary by keying in a small startup routine.
+-This program is capable of loading type 407 executable
+-files (not shared, not separate I&D).
+-The user types on the system console
+-the name of the program wished, in this case
+-.IR boot ,
+-followed by a carriage return;
+-the named program is retrieved from the file system
+-that starts at block 0 of drive 0 of the boot device.
+-No prompt is given,
+-no diagnostic results if the file cannot be found, and no
+-provision is made for correcting typographical errors.
+-.PP
+-The second step, called
+-.I boot,
+-actually brings in the system.
+-When read into location 0 and executed,
+-.I boot
+-sets up memory management, relocates itself into
+-high memory, and types a `:' on the console.
+-Then it
+-reads from the console
+-a device specification (see below) followed immediately by
+-a pathname.
+-.I Boot
+-finds the corresponding file on the given device,
+-loads that file into memory location zero,
+-sets up memory management as required,
+-and calls the program by executing a `trap' instruction.
+-Normal
+-line editing characters can be used.
+-.PP
+-Conventionally, the name of the secondary boot program
+-is `/boot' and the name of the current version of the system
+-is `/unix'.
+-Then, the recipe is:
+-.TP
+-1)
+-Load block 0 of the boot device by fiddling with the
+-console keys as appropriate for your hardware.
+-If you have no appropriate ROM, some programs suitable
+-for manual use are given below.
+-.TP
+-2)
+-Type
+-.IR boot .
+-.TP
+-3)
+-When the prompt is given, type
+-.br
+-      hp(0,0)unix
+-.br
+-or
+-.br
+-      rp(0,0)unix
+-.br
+-depending on whether you are loading from an RP04/5/6 or an RP03
+-respectively.
+-The first 0 indicates the physical unit number;
+-the second indicates
+-the block number of the beginning of the logical file
+-system to be searched.
+-(See below).
+-.PP
+-When the system is running, it types a `#' prompt.
+-After doing any file system checks and setting the date
+-.RI ( date (8))
+-a multi-user system is brought up by typing an EOT
+-(control-d)
+-in response to the `#' prompt.
+-.PP
+-.B Device specifications.
+-A device specification has the following form:
+-.IP " "
+-device(unit,offset)
+-.LP
+-where
+-.I device
+-is the type of the device to be searched,
+-.I unit
+-is the unit number of the device,
+-and 
+-.I offset
+-is the block offset of the file system on the device.
+-.I Device
+-is one of the following
+-.br
+-.nf
+-      rp      RP03
+-      hp      RP04/5/6
+-      rk      RK05
+-.fi
+-For example, the specification
+-.IP " "
+-hp(1,7000)
+-.LP
+-indicates an RP03 disk, unit 1, and the file system found
+-starting at block 7000 (cylinder 35).
+-.PP
+-.SM
+-.B ROM
+-.B programs.
+-The following programs to call the primary bootstrap
+-may be installed in read-only memories
+-or manually keyed into main 
+-memory.
+-Each program is position-independent
+-but should be placed well above location 0
+-so it will not be overwritten.
+-Each reads a block from the
+-beginning of a device into core location
+-zero.
+-The octal words constituting the program are
+-listed on the left.
+-.PP
+-.ne 5
+-.nf
+-.if n .ta 3 11 15 23 38
+-.if t .ta .3i 1i 1.4i 2i 3.5i
+-RK (drive 0):
+-      012700          mov     $rkda,r0
+-      177412
+-      005040          clr     \-(r0)  / rkda cleared by start
+-      010040          mov     r0,\-(r0)
+-      012740          mov     $5,\-(r0)
+-      000005
+-      105710  1:      tstb    (r0)
+-      002376          bge     1b
+-      005007          clr     pc
+-.PP
+-.ne 11
+-RP (drive 0)
+-      012700          mov     $rpmr,r0
+-      176726
+-      005040          clr     \-(r0)
+-      005040          clr     \-(r0)
+-      005040          clr     \-(r0)
+-      010040          mov     r0,\-(r0)
+-      012740          mov     $5,\-(r0)
+-      000005
+-      105710  1:      tstb    (r0)
+-      002376          bge     1b
+-      005007          clr     pc
+-.DT
+-.SH FILES
+-/unix \- system code
+-.br
+-/usr/mdec/rpuboot, /usr/mdec/hpuboot \- copies of primary bootstrap
+-.br
+-/boot \- second stage bootstrap
+-.SH "SEE ALSO"
+-init(8)
+//GO.SYSIN DD boot.8
+echo crash.8
+sed 's/.//' >crash.8 <<'//GO.SYSIN DD crash.8'
+-.TH CRASH 8 
+-.SH NAME
+-crash \- what to do when the system crashes
+-.SH DESCRIPTION
+-This section gives at least a few clues about how to proceed if the
+-system crashes.
+-It can't pretend to be complete.
+-.PP
+-.I Bringing it back up.
+-If the reason for the crash is not evident
+-(see below for guidance on `evident')
+-you may want to try to dump the system if you feel up to
+-debugging.
+-At the moment a dump can be taken only on magtape.
+-With a tape mounted and ready,
+-stop the machine, load address 44, and start.
+-This should write a copy of all of core
+-on the tape with an EOF mark.
+-Caution:
+-Any error is taken to mean the end of core has been reached.
+-This means that you must be sure the ring is in,
+-the tape is ready, and the tape is clean and new.
+-If the dump fails, you can try again,
+-but some of the registers will be lost.
+-See below for what to do with the tape.
+-.PP
+-In restarting after a crash,
+-always bring up the system single-user.
+-This is accomplished by following the directions in
+-.IR boot (8)
+-as modified for your particular installation;
+-a single-user system is indicated by having a particular value
+-in the switches (173030 unless you've changed
+-.I init)
+-as the system starts executing.
+-When it is running,
+-perform a
+-.I dcheck
+-and
+-.IR  icheck (1)
+-on all file systems which could have been in use at the time
+-of the crash.
+-If any serious file system problems are found, they should be repaired.
+-When you are satisfied with the health of your disks,
+-check and set the date if necessary,
+-then come up multi-user.
+-This is most easily accomplished by changing the
+-single-user value in the switches to something else,
+-then logging out
+-by typing an EOT.
+-.PP
+-To even boot \s8UNIX\s10 at all,
+-three files (and the directories leading to them)
+-must be intact.
+-First,
+-the initialization program
+-.I /etc/init
+-must be present and executable.
+-If it is not,
+-the CPU will loop in user mode at location 6.
+-For
+-.I init
+-to work correctly,
+-.I /dev/tty8
+-and
+-.I /bin/sh
+-must be present.
+-If either does not exist,
+-the symptom is best described
+-as thrashing.
+-.I Init
+-will go into a
+-.I fork/exec
+-loop trying to create a
+-Shell with proper standard input and output.
+-.PP
+-If you cannot get the system to boot,
+-a runnable system must be obtained from
+-a backup medium.
+-The root file system may then be doctored as
+-a mounted file system as described below.
+-If there are any problems with the root
+-file system,
+-it is probably prudent to go to a
+-backup system to avoid working on a
+-mounted file system.
+-.PP
+-.I Repairing disks.
+-The first rule to keep in mind is that an addled disk
+-should be treated gently;
+-it shouldn't be mounted unless necessary,
+-and if it is very valuable yet
+-in quite bad shape, perhaps it should be dumped before
+-trying surgery on it.
+-This is an area where experience and informed courage count for much.
+-.PP
+-The problems reported by
+-.I icheck
+-typically fall into two kinds.
+-There can be
+-problems with the free list:
+-duplicates in the free list, or free blocks also in files.
+-These can be cured easily with an
+-.I icheck \-s.
+-If the same block appears in more than one file
+-or if a file contains bad blocks,
+-the files should be deleted, and the free list reconstructed.
+-The best way to delete such a file is to use
+-.IR  clri (1),
+-then remove its directory entries.
+-If any of the affected files is really precious,
+-you can try to copy it to another device
+-first.
+-.PP
+-.I Dcheck
+-may report files which
+-have more directory entries than links.
+-Such situations are potentially dangerous;
+-.I clri
+-discusses a special case of the problem.
+-All the directory entries for the file should be removed.
+-If on the other hand there are more links than directory entries,
+-there is no danger of spreading infection, but merely some disk space
+-that is lost for use.
+-It is sufficient to copy the file (if it has any entries and is useful)
+-then use
+-.I clri
+-on its inode and remove any directory
+-entries that do exist.
+-.PP
+-Finally,
+-there may be inodes reported by
+-.I dcheck
+-that have 0 links and 0 entries.
+-These occur on the root device when the system is stopped
+-with pipes open, and on other file systems when the system
+-stops with files that have been deleted while still open.
+-A
+-.I clri
+-will free the inode, and an
+-.I icheck -s
+-will
+-recover any missing blocks.
+-.PP
+-.I Why did it crash?
+-UNIX types a message
+-on the console typewriter when it voluntarily crashes.
+-Here is the current list of such messages,
+-with enough information to provide
+-a hope at least of the remedy.
+-The message has the form `panic: ...',
+-possibly accompanied by other information.
+-Left unstated in all cases
+-is the possibility that hardware or software
+-error produced the message in some unexpected way.
+-.HP 5
+-blkdev
+-.br
+-The
+-.I getblk
+-routine was called with a nonexistent major device as argument.
+-Definitely hardware or software error.
+-.HP 5
+-devtab
+-.br
+-Null device table entry for the major device used as argument to
+-.I getblk.
+-Definitely hardware or software error.
+-.HP 5
+-iinit
+-.br
+-An I/O error reading the super-block for the root file system
+-during initialization.
+-.HP 5
+-out of inodes
+-.br
+-A mounted file system has no more i-nodes when creating a file.
+-Sorry, the device isn't available;
+-the
+-.I icheck
+-should tell you.
+-.HP 5
+-no fs
+-.br
+-A device has disappeared from the mounted-device table.
+-Definitely hardware or software error.
+-.HP 5
+-no imt
+-.br
+-Like `no fs', but produced elsewhere.
+-.HP 5
+-no inodes
+-.br
+-The in-core inode table is full.
+-Try increasing NINODE in param.h.
+-Shouldn't be a panic, just a user error.
+-.HP 5
+-no clock
+-.br
+-During initialization,
+-neither the line nor programmable clock was found to exist.
+-.HP 5
+-swap error
+-.br
+-An unrecoverable I/O error during a swap.
+-Really shouldn't be a panic,
+-but it is hard to fix.
+-.HP 5
+-unlink \- iget
+-.br
+-The directory containing a file being deleted can't be found.
+-Hardware or software.
+-.HP 5
+-out of swap space
+-.br
+-A program needs to be swapped out, and there is no more swap space.
+-It has to be increased.
+-This really shouldn't be a panic, but there is no easy fix.
+-.HP 5
+-out of text
+-.br
+-A pure procedure program is being executed,
+-and the table for such things is full.
+-This shouldn't be a panic.
+-.HP 5
+-trap
+-.br
+-An unexpected trap has occurred within the system.
+-This is accompanied by three numbers:
+-a `ka6', which is the contents of the segmentation
+-register for the area in which the system's stack is kept;
+-`aps', which is the location where the hardware stored
+-the program status word during the trap;
+-and a `trap type' which encodes
+-which trap occurred.
+-The trap types are:
+-.TP 10
+-0
+-bus error
+-.br
+-.ns
+-.TP 10
+-1
+-illegal instruction
+-.br
+-.ns
+-.TP 10
+-2
+-BPT/trace
+-.br
+-.ns
+-.TP 10
+-3
+-IOT
+-.br
+-.ns
+-.TP 10
+-4
+-power fail
+-.br
+-.ns
+-.TP 10
+-5
+-EMT
+-.br
+-.ns
+-.TP 10
+-6
+-recursive system call (TRAP instruction)
+-.br
+-.ns
+-.TP 10
+-7
+-11/70 cache parity, or programmed interrupt
+-.br
+-.ns
+-.TP 10
+-10
+-floating point trap
+-.br
+-.ns
+-.TP 10
+-11
+-segmentation violation
+-.PP
+-In some of these cases it is
+-possible for octal 20 to be added into the trap type;
+-this indicates that the processor was in user mode when the trap occurred.
+-If you wish to examine the stack after such a trap,
+-either dump the system, or use the console switches to examine core;
+-the required address mapping is described below.
+-.PP
+-.I Interpreting dumps.
+-All file system problems
+-should be taken care of before attempting to look at dumps.
+-The dump should be read into the file
+-.I /usr/sys/core;
+-.IR  cp (1)
+-will do.
+-At this point, you should execute
+-.I ps \-alxk
+-and
+-.I who
+-to print the process table and the users who were on
+-at the time of the crash.
+-You should dump (
+-.IR  od (1))
+-the first 30 bytes of
+-.I /usr/sys/core.
+-Starting at location 4,
+-the registers R0, R1, R2, R3, R4, R5, SP
+-and KDSA6 (KISA6 for 11/40s) are stored.
+-If the dump had to be restarted,
+-R0 will not be correct.
+-Next, take the value of KA6 (location 022(8) in the dump)
+-multiplied by 0100(8) and dump 01000(8) bytes starting from there.
+-This is the per-process data associated with the process running
+-at the time of the crash.
+-Relabel
+-the addresses 140000 to 141776.
+-R5 is C's frame or display pointer.
+-Stored at (R5) is the old R5 pointing to the previous
+-stack frame.
+-At (R5)+2
+-is the saved PC of the calling procedure.
+-Trace
+-this calling chain until
+-you obtain an R5 value of 141756, which
+-is where the user's R5 is stored.
+-If the chain is broken,
+-you have to look for a plausible
+-R5, PC pair and continue from there.
+-Each PC should be looked up in the system's name list
+-using
+-.IR  adb (1)
+-and its `:' command,
+-to get a reverse calling order.
+-In most cases this procedure will give
+-an idea of what is wrong.
+-A more complete discussion
+-of system debugging is impossible here.
+-.SH SEE ALSO
+-clri(1), icheck(1), dcheck(1), boot(8)
+//GO.SYSIN DD crash.8
+echo cron.8
+sed 's/.//' >cron.8 <<'//GO.SYSIN DD cron.8'
+-.TH CRON 8 
+-.SH NAME
+-cron \- clock daemon
+-.SH SYNOPSIS
+-.B /etc/cron
+-.SH DESCRIPTION
+-.I Cron
+-executes commands at specified dates and times
+-according to the instructions in the file
+-/usr/lib/crontab.
+-Since
+-.I cron
+-never exits,
+-it should only be executed once.
+-This is best done by running
+-.I cron
+-from the initialization
+-process through the file
+-/etc/rc;
+-see
+-.IR init (8).
+-.PP
+-Crontab
+-consists of lines of six fields each.
+-The fields are separated by spaces or tabs.
+-The first five are integer patterns to
+-specify the
+-minute (0-59),
+-hour (0-23),
+-day of the month (1-31),
+-month of the year (1-12),
+-and day of the week (1-7 with 1=monday).
+-Each of these patterns may
+-contain a number in the range above;
+-two numbers separated by
+-a minus
+-meaning a range inclusive;
+-a list of numbers separated by
+-commas meaning any of the numbers;
+-or an asterisk meaning all legal values.
+-The sixth field is a string
+-that is executed by the Shell at the
+-specified times.
+-A percent character
+-in this field is translated to a new-line
+-character.
+-Only the first line (up to a % or end of line)
+-of the command field is executed by the Shell.
+-The other lines are made available to the
+-command as standard input.
+-.PP
+-Crontab is examined by
+-.I cron
+-every minute.
+-.SH FILES
+-/usr/lib/crontab
+//GO.SYSIN DD cron.8
+echo getty.8
+sed 's/.//' >getty.8 <<'//GO.SYSIN DD getty.8'
+-.TH GETTY 8 
+-.SH NAME
+-getty  \- set typewriter mode
+-.SH SYNOPSIS
+-.B /etc/getty
+-[ char ]
+-.SH DESCRIPTION
+-.I Getty
+-is invoked
+-by
+-.IR  init (8)
+-immediately after a typewriter is opened
+-following a dial-up.
+-It reads the user's login name and calls
+-.IR login (1)
+-with the name as argument.
+-While reading the name
+-.I getty
+-attempts to adapt the system to the speed and type of terminal
+-being used.
+-.PP
+-.I Init
+-calls
+-.I getty
+-with a single character argument taken from
+-the
+-.IR ttys (5)
+-file entry for the terminal line.
+-This argument determines a sequence of line speeds through which
+-.I getty
+-cycles, and also the `login:' greeting message,
+-which can contain character sequences to put various kinds of
+-terminals in useful states.
+-.PP
+-The user's name is terminated by a new-line or
+-carriage-return character.
+-In the second case CRMOD mode is set
+-(see
+-.IR  ioctl (2)).
+-.PP
+-The name is scanned to see if
+-it contains any lower-case alphabetic characters; if not,
+-and if the name is nonempty, the
+-system is told to map any future upper-case characters
+-into the corresponding lower-case characters.
+-.PP
+-If the terminal's `break' key is depressed,
+-.I getty
+-cycles to the next speed appropriate to the type of line
+-and prints the greeting message again.
+-.PP
+-Finally, login is called with the user's name as argument.
+-.PP
+-The following arguments from the
+-.I ttys
+-file are understood.
+-.TP
+-0
+-Cycles through 300-1200-150-110 baud.
+-Useful as a default for dialup lines accessed by a variety
+-of terminals.
+-.TP
+-\-
+-Intended for an on-line Teletype model 33, for example
+-an operator's console.
+-.TP
+-1
+-Optimized for a 150-baud Teletype model 37.
+-.TP
+-2
+-Intended for an on-line 9600-baud terminal, for example
+-the Textronix 4104.
+-.TP
+-3
+-Starts at 1200 baud, cycles to 300 and back.
+-Useful with 212 datasets where most terminals
+-run at 1200 speed.
+-.TP
+-5
+-Same as `3' but starts at 300.
+-.TP
+-4
+-Useful for on-line console DECwriter (LA36).
+-.SH "SEE ALSO"
+-init(8), login(1), ioctl(2), ttys(5)
+//GO.SYSIN DD getty.8
+echo init.8
+sed 's/.//' >init.8 <<'//GO.SYSIN DD init.8'
+-.TH INIT 8 
+-.SH NAME
+-init, rc  \-  process control initialization
+-.SH SYNOPSIS
+-.B /etc/init
+-.br
+-.B /etc/rc
+-.SH DESCRIPTION
+-.I Init
+-is invoked as the last step of the boot procedure (see
+-.IR boot (8)).
+-Generally its role is to create a process for each
+-typewriter on which a user may log in.
+-.PP
+-When
+-.I init
+-first is executed
+-the console typewriter
+-.I /dev/console.
+-is opened for reading
+-and writing and the shell is invoked immediately.
+-This feature is used to bring up a single-user system.
+-If the shell terminates,
+-.I init
+-comes up multi-user and the process described below is started.
+-.PP
+-When
+-.I init
+-comes up multiuser,
+-it
+-invokes a shell, with input taken from the
+-file
+-.I /etc/rc.
+-This command file
+-performs housekeeping
+-like removing temporary files,
+-mounting file systems, and starting
+-daemons.
+-.PP
+-Then
+-.I init
+-reads the file
+-.I /etc/ttys
+-and
+-forks several times to create a process
+-for each typewriter specified in the file.
+-Each of these processes opens the appropriate typewriter
+-for reading and writing.  These channels thus
+-receive file descriptors 0, 1 and 2, the standard input,
+-output and error files.
+-Opening the typewriter will usually involve a delay,
+-since the
+-.IR open ""
+-is not completed until someone
+-is dialed up and carrier established on the channel.
+-Then
+-.I /etc/getty
+-is called with argument as specified by the last character of
+-the
+-.I ttys
+-file line.
+-.I Getty
+-reads the user's name and invokes
+-.IR login (1)
+-to log in the user and execute the shell.
+-.PP
+-Ultimately the shell will terminate
+-because of an end-of-file either
+-typed explicitly or generated as a result of hanging up.
+-The main path of
+-.IR init ,
+-which has been waiting
+-for such an event,
+-wakes up and removes the appropriate entry from the
+-file
+-.IR utmp ,
+-which records current users, and
+-makes an entry in
+-.IR /usr/adm/wtmp ,
+-which maintains a history
+-of logins and logouts.
+-Then the appropriate typewriter is reopened and
+-.I getty
+-is
+-reinvoked.
+-.PP
+-.I Init
+-catches the
+-hangup signal SIGHUP and interprets it to mean that
+-the
+-system should be brought from multi user to single
+-user.
+-Use `kill -1 1' to send the hangup signal.
+-.SH FILES
+-/dev/tty?, /etc/utmp, /usr/adm/wtmp, /etc/ttys, /etc/rc
+-.SH "SEE ALSO"
+-login(1), kill(1), sh(1), ttys(5), getty(8)
+//GO.SYSIN DD init.8
+echo makekey.8
+sed 's/.//' >makekey.8 <<'//GO.SYSIN DD makekey.8'
+-.TH MAKEKEY 8 
+-.SH NAME
+-makekey \- generate encryption key
+-.SH SYNOPSIS
+-.B /usr/lib/makekey
+-.SH DESCRIPTION
+-.I Makekey
+-improves the usefulness of encryption schemes
+-depending on a key by increasing the amount of time required to
+-search the key space.
+-It reads 10 bytes from its standard input,
+-and writes 13 bytes on its standard output.
+-The output depends on the input in a way intended
+-to be difficult to compute (i.e. to require a substantial
+-fraction of a second).
+-.PP
+-The first eight input bytes
+-(the
+-.IR "input key" )
+-can be arbitrary ASCII characters.
+-The last 
+-two (the
+-.IR salt )
+-are best chosen from the set of digits, upper- and lower-case
+-letters, and `.' and `/'.
+-The salt characters are repeated as the first two characters of the output.
+-The remaining 11 output characters are chosen from the same set as the salt
+-and constitute the
+-.I "output key."
+-.PP
+-The transformation performed is essentially the following:
+-the salt is used to select one of 4096 cryptographic
+-machines all based on the National Bureau of Standards
+-DES algorithm, but modified in 4096 different ways.
+-Using the input key as key,
+-a constant string is fed into the machine and recirculated
+-a number of times.
+-The 64 bits that come out are distributed into the
+-66 useful key bits in the result.
+-.PP
+-.I Makekey
+-is intended for programs that perform encryption
+-(e.g.
+-.I ed
+-and
+-.IR crypt (1)).
+-Usually its input and output will be pipes.
+-.SH SEE ALSO
+-crypt(1), ed(1)
+//GO.SYSIN DD makekey.8
+echo update.8
+sed 's/.//' >update.8 <<'//GO.SYSIN DD update.8'
+-.TH UPDATE 8 
+-.SH NAME
+-update \- periodically update the super block
+-.SH SYNOPSIS
+-.B /etc/update
+-.SH DESCRIPTION
+-.I Update
+-is a program that executes
+-the
+-.IR sync (2)
+-primitive every 30 seconds.
+-This insures that the file system
+-is fairly up to date in case of a crash.
+-This command should not be executed directly,
+-but should be executed out of the
+-initialization shell command file.
+-.SH "SEE ALSO"
+-sync(2), sync(1), init(8)
+-.SH BUGS
+-With
+-.I update
+-running,
+-if the CPU is
+-halted just as
+-the
+-.I sync
+-is executed,
+-a file system can be damaged.
+-This is partially due to DEC hardware that
+-writes zeros when NPR requests fail.
+-A fix would be to have
+-.IR sync (1)
+-temporarily increment the system time by at
+-least 30 seconds to trigger the execution of
+-.I update.
+-This would give 30 seconds grace to halt the CPU.
+//GO.SYSIN DD update.8
diff --git a/doc/7thEdMan/vol2/README b/doc/7thEdMan/vol2/README
new file mode 100644 (file)
index 0000000..98a97e4
--- /dev/null
@@ -0,0 +1,9 @@
+This directory contains source for most of the
+documents contained in Volume 2 of The UNIX
+Programmer's Manual, 7th Edition.
+Most use -ms to format; many also use
+refer, tbl and eqn. Precise incantations
+are engraved in ./run.
+
+The citations for those papers that use
+refer are taken from /usr/dict/papers/Rv7man.
diff --git a/doc/7thEdMan/vol2/adb.bun b/doc/7thEdMan/vol2/adb.bun
new file mode 100644 (file)
index 0000000..1de6023
--- /dev/null
@@ -0,0 +1,2260 @@
+# To unbundle, run this file
+echo tut
+sed 's/.//' >tut <<'//GO.SYSIN DD tut'
+-.de P1
+-.sp .5
+-.if \\n(.$>0 .ta \\$1 \\$2 \\$3 \\$4 \\$5 \\$6
+-.if \\n(.$=0 .ta 1i 1.7i 2.5i
+-.ft 3
+-.nf
+-..
+-.de P2
+-.sp .5
+-.ft 1
+-.fi
+-..
+-.RP
+-.....TM "77-8234-11 77-1273-10" "49170-220 39199" "40952-1 39199-11"
+-.ND May 5, 1977
+-.TL
+-A Tutorial Introduction to ADB
+-.AU "MH2F-207" "3816"
+-J. F. Maranzano
+-.AU "MH2C-512" 7419
+-S. R. Bourne
+-.AI
+-.MH
+-.OK
+-UNIX
+-Debugging
+-C Programming
+-.AB
+-.PP
+-Debugging tools generally provide a wealth of information
+-about the inner workings of programs.
+-These tools have been available on
+-.UX
+-to allow users to
+-examine ``core'' files 
+-that result from aborted programs.
+-A new debugging program, ADB, provides enhanced capabilities
+-to examine "core" and other program files in a
+-variety of formats, run programs with embedded breakpoints and patch files.
+-.PP
+-ADB is an indispensable but complex tool for debugging crashed systems and/or
+-programs.
+-This document provides an introduction to ADB with examples of its use.
+-It explains the various formatting options, 
+-techniques for debugging C programs, examples of printing
+-file system information and patching.
+-.AE
+-.CS 12 15 27 13 0 5
+-.NH
+-Introduction
+-.PP
+-ADB is a new debugging program that is
+-available on UNIX.
+-It provides capabilities to look at
+-``core'' files resulting from aborted programs, print output in a
+-variety of formats, patch files, and run programs
+-with embedded breakpoints.
+-This document provides examples of
+-the more useful features of ADB.
+-The reader is expected to be
+-familiar with the basic commands on
+-.UX
+-with the C
+-language, and with References 1, 2 and 3.
+-.NH
+-A Quick Survey
+-.NH 2
+-Invocation
+-.PP
+-ADB is invoked as:
+-.P1
+-      adb objfile corefile
+-.P2
+-where
+-.ul
+-objfile
+-is an executable UNIX file and 
+-.ul
+-corefile 
+-is a core image file.
+-Many times this will look like:
+-.P1
+-      adb a.out core
+-.P2
+-or more simply:
+-.P1
+-      adb
+-.P2
+-where the defaults are 
+-.ul
+-a.out
+-and
+-.ul
+-core
+-respectively.
+-The filename minus (\-) means ignore this argument as in:
+-.P1
+-      adb \- core
+-.P2
+-.PP
+-ADB has requests for examining locations in either file.
+-The
+-\fB?\fP
+-request examines the contents of 
+-.ul
+-objfile,
+-the
+-\fB/\fP
+-request examines the 
+-.ul
+-corefile.
+-The general form of these requests is:
+-.P1
+-      address ? format
+-.P2
+-or
+-.P1
+-      address / format
+-.P2
+-.NH 2
+-Current Address
+-.PP
+-ADB maintains a current address, called dot,
+-similar in function to the current pointer in the UNIX editor.
+-When an address is entered, the current address is set to that location,
+-so that:
+-.P1
+-      0126?i
+-.P2
+-sets dot to octal 126 and prints the instruction
+-at that address.
+-The request:
+-.P1
+-      .,10/d
+-.P2
+-prints 10 decimal numbers starting at dot.
+-Dot ends up referring to the address of the last item printed.
+-When used with the \fB?\fP or \fB/\fP requests,
+-the current address can be advanced by typing newline; it can be decremented
+-by typing \fB^\fP.
+-.PP
+-Addresses are represented by
+-expressions.
+-Expressions are made up from decimal, octal, and hexadecimal integers,
+-and symbols from the program under test.
+-These may be combined with the operators +, \-, *, % (integer division), 
+-& (bitwise and), | (bitwise inclusive or),  # (round up
+-to the next multiple), and ~ (not).
+-(All arithmetic within ADB is 32 bits.)
+-When typing a symbolic address for a C program, 
+-the user can type 
+-.ul
+-name
+-or
+-.ul
+-_name;
+-ADB will recognize both forms.
+-.NH 2
+-Formats
+-.PP
+-To print data, a user specifies a collection of letters and characters
+-that describe the format of the printout.
+-Formats are "remembered" in the sense that typing a request without one
+-will cause the new printout to appear in the previous format.
+-The following are the most commonly used format letters.
+-.P1
+-\fB   b       \fPone byte in octal
+-\fB   c       \fPone byte as a character
+-\fB   o       \fPone word in octal
+-\fB   d       \fPone word in decimal
+-\fB   f       \fPtwo words in floating point
+-\fB   i       \fPPDP 11 instruction
+-\fB   s       \fPa null terminated character string
+-\fB   a       \fPthe value of dot
+-\fB   u       \fPone word as unsigned integer
+-\fB   n       \fPprint a newline
+-\fB   r       \fPprint a blank space
+-\fB   ^       \fPbackup dot
+-.P2
+-(Format letters are also available for "long" values,
+-for example, `\fBD\fR' for long decimal, and `\fBF\fP' for double floating point.)
+-For other formats see the ADB manual.
+-.NH 2
+-General Request Meanings
+-.PP
+-The general form of a request is:
+-.P1
+-      address,count command modifier
+-.P2
+-which sets `dot' to \fIaddress\fP
+-and executes the command
+-\fIcount\fR times.
+-.PP
+-The following table illustrates some general ADB command meanings:
+-.P1
+-      Command Meaning
+-\fB       ?   \fPPrint contents from \fIa.out\fP file
+-\fB       /   \fPPrint contents from \fIcore\fP file
+-\fB       =   \fPPrint value of "dot"
+-\fB       :   \fPBreakpoint control
+-\fB       $   \fPMiscellaneous requests
+-\fB       ;   \fPRequest separator
+-\fB       !   \fPEscape to shell
+-.P2
+-.PP
+-ADB catches signals, so a user cannot use a quit signal to exit from ADB.
+-The request $q or $Q (or cntl-D) must be used
+-to exit from ADB.
+-.NH
+-Debugging C Programs
+-.NH 2
+-Debugging A Core Image 
+-.PP
+-Consider the C program in Figure 1.
+-The program is used to illustrate a common error made by
+-C programmers.
+-The object of the program is to change the
+-lower case "t" to upper case in the string pointed to by
+-.ul
+-charp
+-and then write the character string to the file indicated by
+-argument 1.
+-The bug shown is that the character "T"
+-is stored in the pointer 
+-.ul
+-charp
+-instead of the string pointed to by
+-.ul
+-charp.
+-Executing the program produces a core file because of an out of bounds memory reference.
+-.PP
+-ADB is invoked by:
+-.P1
+-      adb a.out core
+-.P2
+-The first debugging request:
+-.P1
+-      $c
+-.P2
+-is used to give a C backtrace through the
+-subroutines called.
+-As shown in Figure 2
+-only one function (\fImain\fR) was called and the
+-arguments 
+-.ul
+-argc 
+-and 
+-.ul
+-argv 
+-have octal values 02 and
+-0177762 respectively.
+-Both of these values look
+-reasonable; 02 = two arguments, 0177762 = address on stack
+-of parameter vector.
+-.br
+-The next request:
+-.P1
+-      $C
+-.P2
+-is used to give a C backtrace plus an interpretation
+-of all the local variables in each function and their
+-values in octal.
+-The value of the variable 
+-.ul
+-cc
+-looks incorrect
+-since
+-.ul
+-cc
+-was declared as a character.
+-.PP
+-The next request:
+-.P1
+-      $r
+-.P2
+-prints out the registers including the program
+-counter and an interpretation of the instruction at that
+-location.
+-.PP
+-The request:
+-.P1
+-      $e
+-.P2
+-prints out the values of all external variables.
+-.PP
+-A map exists for each file
+-handled by
+-ADB.
+-The map for the
+-.ul
+-a.out
+-file is referenced by \fB?\fP whereas the map for 
+-.ul
+-core
+-file is referenced by \fB/\fP.
+-Furthermore, a good rule of thumb is to use \fB?\fP for
+-instructions and \fB/\fP for data when looking at programs.
+-To print out information about the maps type:
+-.P1
+-      $m
+-.P2
+-This produces a report of the contents of the maps.
+-More about these maps later.
+-.PP
+-In our example, it is useful to see the
+-contents of the string pointed to by
+-.ul
+-charp.
+-This is done by:
+-.P1
+-      *charp/s
+-.P2
+-which says use 
+-.ul
+-charp
+-as a pointer in the
+-.ul
+-core
+-file
+-and print the information as a character string.
+-This printout clearly shows that the character buffer
+-was incorrectly overwritten and helps identify the error.
+-Printing the locations around 
+-.ul
+-charp
+-shows that the buffer is unchanged
+-but that the pointer is destroyed.
+-Using ADB similarly, we could print information about the
+-arguments to a function.
+-The request:
+-.P1
+-      main.argc/d
+-.P2
+-prints the decimal 
+-.ul
+-core
+-image value of the argument 
+-.ul
+-argc
+-in the function 
+-.ul
+-main.
+-.br
+-The request:
+-.P1
+-      *main.argv,3/o
+-.P2
+-prints the octal values of the three consecutive
+-cells pointed to by 
+-.ul
+-argv
+-in the function 
+-.ul
+-main.
+-Note that these values are the addresses of the arguments
+-to main.
+-Therefore: 
+-.P1
+-      0177770/s
+-.P2
+-prints the ASCII value of the first argument.
+-Another way to print this value would have been
+-.P1
+-      *"/s
+-.P2
+-The " means ditto which remembers the last address
+-typed, in this case \fImain.argc\fP ; the \fB*\fP instructs ADB to use the address field of the
+-.ul
+-core 
+-file as a pointer.
+-.PP
+-The request:
+-.P1
+-      .=o
+-.P2
+-prints the current address (not its contents) in octal which has been set to the address of the first argument.
+-The current address, dot, is used by ADB to
+-"remember" its current location.
+-It allows the user 
+-to reference locations relative to the current
+-address, for example:
+-.P1
+-      .\-10/d
+-.P2
+-.NH 2
+-Multiple Functions
+-.PP
+-Consider the C program illustrated in
+-Figure 3.
+-This program calls functions 
+-.ul
+-f, g,
+-and
+-.ul
+-h 
+-until the stack is exhausted and a core image is produced.
+-.PP
+-Again you can enter the debugger via:
+-.P1
+-      adb
+-.P2
+-which assumes the names 
+-.ul
+-a.out
+-and 
+-.ul
+-core
+-for the executable
+-file and core image file respectively.
+-The request:
+-.P1
+-      $c
+-.P2
+-will fill a page of backtrace references to 
+-.ul
+-f, g,
+-and
+-.ul
+-h.
+-Figure 4 shows an abbreviated list (typing 
+-.ul
+-DEL
+-will terminate the output and bring you back to ADB request level).
+-.PP
+-The request:
+-.P1
+-      ,5$C
+-.P2
+-prints the five most recent activations.
+-.PP
+-Notice that each function 
+-(\fIf,g,h\fP) has a counter
+-of the number of times it was called.
+-.PP
+-The request:
+-.P1
+-      fcnt/d
+-.P2
+-prints the decimal value of the counter for the function
+-.ul
+-f.
+-Similarly 
+-.ul
+-gcnt
+-and
+-.ul
+-hcnt
+-could be printed.
+-To print the value of an automatic variable,
+-for example the decimal value of
+-.ul 
+-x
+-in the last call of the function
+-.ul
+-h,
+-type:
+-.P1
+-      h.x/d
+-.P2
+-It is currently not possible in the exported version to print stack frames other than the most recent activation of a function.
+-Therefore, a user can print everything with 
+-\fB$C\fR or the occurrence of a variable in the most recent call of a function.
+-It is possible with the \fB$C\fR request, however, to print the stack frame
+-starting at some address as \fBaddress$C.\fR
+-.NH 2
+-Setting Breakpoints
+-.PP
+-Consider the C program in Figure 5.
+-This program, which changes tabs into blanks, is adapted from
+-.ul
+-Software Tools
+-by Kernighan and Plauger, pp. 18-27.
+-.PP
+-We will run this program under the control of ADB (see Figure 6a) by:
+-.P1
+-      adb a.out \-
+-.P2
+-Breakpoints are set in the program as:
+-.ul
+-.P1
+-      address:b  [request]
+-.P2
+-The requests:
+-.P1
+-      settab+4:b
+-      fopen+4:b
+-      getc+4:b
+-      tabpos+4:b
+-.P2
+-set breakpoints at the start of these functions.
+-C does not generate statement labels.
+-Therefore it is currently not possible to plant breakpoints at locations
+-other than function entry points without a knowledge of the code
+-generated by the C compiler.
+-The above addresses are entered as
+-.ft B
+-symbol+4
+-.ft R
+-so that they will appear in any
+-C backtrace since the first instruction of each function is a call
+-to the C save routine 
+-(\fIcsv\fR).
+-Note that some of the functions are from the C library.
+-.PP
+-To print the location of breakpoints one types:
+-.P1
+-      $b
+-.P2
+-The display indicates a
+-.ul
+-count
+-field.
+-A breakpoint is bypassed
+-.ul
+-count \-1
+-times before causing a stop.
+-The
+-.ul
+-command
+-field indicates the ADB requests to be executed each time the breakpoint is encountered.
+-In our example no
+-.ul
+-command
+-fields are present.
+-.PP
+-By displaying the original instructions at the function
+-.ul
+-settab
+-we see that 
+-the breakpoint is set after the jsr to the C save routine.
+-We can display the instructions using the ADB request:
+-.P1
+-      settab,5?ia
+-.P2
+-This request displays five instructions starting at
+-.ul
+-settab
+-with the addresses of each location displayed.
+-Another variation is:
+-.P1
+-      settab,5?i
+-.P2
+-which displays the instructions with only the starting address.
+-.PP
+-Notice that we accessed the addresses from the 
+-.ul
+-a.out 
+-file with the \fB?\fP command.
+-In general when asking for a printout of multiple items,
+-ADB will advance the current address the number of
+-bytes necessary to satisfy the request; in the above
+-example five instructions were displayed and the current address was
+-advanced 18 (decimal) bytes.
+-.PP
+-To run the program one simply types:
+-.P1
+-      :r
+-.P2
+-To delete a breakpoint, for instance the entry to the function
+-.ul
+-settab,
+-one types:
+-.P1
+-      settab+4:d
+-.P2
+-To continue execution of the program from the breakpoint type:
+-.P1
+-      :c
+-.PP
+-Once the program has stopped (in this case at the breakpoint for
+-.ul
+-fopen),
+-ADB requests can be used to display the contents of memory.
+-For example:
+-.P1
+-      $C
+-.P2
+-to display a stack trace, or:
+-.P1
+-      tabs,3/8o
+-.P2
+-to print three lines of 8 locations each from the array called
+-.ul
+-tabs.
+-By this time (at location
+-.ul
+-fopen)
+-in the C program,
+-.ul
+-settab
+-has been called and should have set a one in every eighth location of 
+-.ul
+-tabs.
+-.NH 2
+-Advanced Breakpoint Usage
+-.PP
+-We continue execution of the program with:
+-.P1
+-      :c
+-.P2
+-See Figure 6b.
+-.ul
+-Getc
+-is called three times and  the contents of the variable 
+-.ul
+-c
+-in the function
+-.ul
+-main
+-are displayed
+-each time.
+-The single character on the left hand edge is the output from the C program.
+-On the third occurrence of 
+-.ul
+-getc
+-the program stops.
+-We can look at the full buffer of characters by typing:
+-.P1
+-      ibuf+6/20c
+-.P2
+-When we continue the program with:
+-.P1
+-      :c
+-.P2
+-we hit our first breakpoint at
+-.ul
+-tabpos
+-since there is a tab following the
+-"This" word of the data.
+-.PP
+-Several breakpoints of
+-.ul
+-tabpos
+-will occur until the program has changed the tab into equivalent blanks.
+-Since we feel that
+-.ul
+-tabpos
+-is working,
+-we can remove the breakpoint at that location by:
+-.P1
+-      tabpos+4:d
+-.P2
+-If the program is continued with:
+-.P1
+-      :c
+-.P2
+-it resumes normal execution after ADB prints
+-the message
+-.P1
+-      a.out:running
+-.P2
+-.PP
+-The UNIX quit and interrupt signals
+-act on ADB itself rather than on the program being debugged.
+-If such a signal occurs then the program being debugged is stopped and control is returned to ADB.
+-The signal is saved by ADB and is passed on to the test program if:
+-.P1
+-      :c
+-.P2
+-is typed.
+-This can be useful when testing interrupt
+-handling routines.
+-The signal is not passed on to the test program if:
+-.P1
+-      :c  0
+-.P2
+-is typed.
+-.PP
+-Now let us reset the breakpoint at
+-.ul
+-settab
+-and display the instructions located there when we reach the breakpoint.
+-This is accomplished by:
+-.P1
+-      settab+4:b  settab,5?ia  \fR*
+-.P2
+-.FS
+-* Owing to a bug in early versions of ADB (including the
+-version distributed in Generic 3 UNIX) these statements
+-must be written as:
+-.br
+-.in 1i
+-\fBsettab+4:b settab,5?ia;0\fR
+-.ft B
+-.br
+-getc+4,3:b    main.c?C;0
+-.br
+-settab+4:b    settab,5?ia; ptab/o;0
+-.br
+-.ft R
+-.in -1i
+-Note that \fB;0\fR will set dot to zero and stop at the breakpoint.
+-.FE
+-It is also possible to execute the ADB requests for each occurrence of the breakpoint but
+-only stop after the third occurrence by typing:
+-.P1
+-      getc+4,3:b  main.c?C  \fR*
+-.P2
+-This request will print the local variable 
+-.ul
+-c
+-in the function 
+-.ul
+-main
+-at each occurrence of the breakpoint.
+-The semicolon is used to separate multiple ADB requests on a single line.
+-.PP
+-Warning:
+-setting a breakpoint causes the value of dot to be changed;
+-executing the program under ADB does not change dot.
+-Therefore:
+-.P1
+-      settab+4:b  .,5?ia
+-      fopen+4:b
+-.P2
+-will print the last thing dot was set to
+-(in the example \fIfopen+4\fP)
+-.ul
+-not
+-the current location (\fIsettab+4\fP)
+-at which the program is executing.
+-.PP
+-A breakpoint can be overwritten without first deleting the old breakpoint.
+-For example:
+-.P1
+-      settab+4:b  settab,5?ia; ptab/o  \fR*
+-.P2
+-could be entered after typing the above requests.
+-.PP
+-Now the display of breakpoints:
+-.P1
+-      $b
+-.P2
+-shows the above request for the
+-.ul
+-settab
+-breakpoint.
+-When the breakpoint at
+-.ul
+-settab
+-is encountered the ADB requests are executed.
+-Note that the location at
+-.ul
+-settab+4
+-has been changed to plant the breakpoint;
+-all the other locations match their original value.
+-.PP
+-Using the functions,
+-.ul
+-f, g
+-and 
+-.ul
+-h
+-shown in Figure 3,
+-we can follow the execution of each function by planting non-stopping
+-breakpoints.
+-We call ADB with the executable program of Figure 3 as follows:
+-.P1
+-      adb ex3 \-
+-.P2
+-Suppose we enter the following breakpoints:
+-.P1
+-      h+4:b   hcnt/d;  h.hi/;  h.hr/
+-      g+4:b   gcnt/d;  g.gi/;  g.gr/
+-      f+4:b   fcnt/d;  f.fi/;  f.fr/
+-      :r
+-.P2
+-Each request line indicates that the variables are printed in decimal
+-(by the specification \fBd\fR).
+-Since the format is not changed, the \fBd\fR can be left off all but
+-the first request.
+-.PP
+-The output in Figure 7 illustrates two points.
+-First, the ADB requests in the breakpoint line are not
+-examined until the program under
+-test is run.
+-That means any errors in those ADB requests is not detected until run time.
+-At the location of the error ADB stops running the program.
+-.PP
+-The second point is the way ADB handles register variables.
+-ADB uses the symbol table to address variables.
+-Register variables, like \fIf.fr\fR above, have pointers to uninitialized
+-places on the stack.
+-Therefore the message "symbol not found".
+-.PP
+-Another way of getting at the data in this example is to print
+-the variables used in the call as:
+-.P1
+-      f+4:b   fcnt/d;  f.a/;  f.b/;  f.fi/
+-      g+4:b   gcnt/d;  g.p/;  g.q/;  g.gi/
+-      :c
+-.P2
+-The operator / was used instead of ?
+-to read values from the \fIcore\fP file.
+-The output for each function, as shown in Figure 7, has the same format.
+-For the function \fIf\fP, for example, it shows the name and value of the
+-.ul
+-external
+-variable
+-.ul
+-fcnt.
+-It also shows the address on the stack and value of the
+-variables
+-.ul
+-a, b
+-and
+-.ul
+-fi.
+-.PP
+-Notice that the addresses on the stack will continue to decrease
+-until no address space is left for program execution
+-at which time (after many pages of output)
+-the program under test aborts.
+-A display with names would be produced by requests like the following:
+-.P1
+-      f+4:b   fcnt/d;  f.a/"a="d;  f.b/"b="d;  f.fi/"fi="d
+-.P2
+-In this format the quoted string is printed literally and the \fBd\fP
+-produces a decimal display of the variables.
+-The results are shown in Figure 7.
+-.NH 2
+-Other Breakpoint Facilities
+-.LP
+-.IP \(bu 4
+-Arguments and change of standard input and output are passed to a program as:
+-.P1
+-      :r  arg1  arg2 ... <infile  >outfile
+-.P2
+-This request
+-kills any existing program under test and
+-starts the
+-.ul
+-a.out
+-afresh.
+-.IP \(bu
+-The program being debugged can be single stepped
+-by:
+-.P1
+-      :s
+-.P2
+-If necessary, this request will start up the program being
+-debugged and stop after executing
+-the first instruction.
+-.IP \(bu
+-ADB allows a program to be entered at a specific address
+-by typing:
+-.P1
+-      address:r
+-.P2
+-.IP \(bu
+-The count field can be used to skip the first \fIn\fR breakpoints as:
+-.P1
+-      ,n:r
+-.P2
+-The request:
+-.P1
+-      ,n:c
+-.P2
+-may also be used for skipping the first \fIn\fR breakpoints
+-when continuing a program.
+-.sp
+-.IP \(bu
+-A program can be continued at an address different from the breakpoint by:
+-.P1
+-      address:c
+-.P2
+-.IP \(bu
+-The program being debugged runs as a separate process and can be killed by:
+-.P1
+-      :k
+-.P2
+-.LP
+-.NH
+-Maps
+-.PP
+-UNIX supports several executable file formats.  These are used to tell
+-the loader how to load  the program file.  File type 407
+-is the most common and is generated by a C compiler invocation such as
+-\fBcc pgm.c\fP.
+-A 410 file is produced by a C compiler command of the form \fBcc -n pgm.c\fP,
+-whereas a 411 file is produced by \fBcc -i pgm.c\fP.
+-ADB interprets these different file formats and
+-provides access to the different segments through a set of maps (see Figure 8).
+-To print the maps type:
+-.P1
+-      $m
+-.P2
+-.PP
+-In 407 files, both text (instructions) and data are intermixed.
+-This makes it impossible for ADB to differentiate data from
+-instructions and some of the printed symbolic addresses look incorrect;
+-for example, printing data addresses as offsets from routines.
+-.PP
+-In 410 files (shared text), the instructions are separated from data and
+-\fB?*\fR accesses the data part of the \fIa.out\fP file.
+-The \fB?* \fP request tells ADB to use the second part of the
+-map in the
+-.ul
+-a.out
+-file.
+-Accessing data in the \fIcore\fP file shows
+-the data after it was modified by the execution of the program.
+-Notice also that the data segment may have grown during
+-program execution.
+-.PP
+-In 411 files (separated I & D space), the
+-instructions and data are also separated.
+-However, in this
+-case, since data is mapped through a separate set of segmentation
+-registers, the base of the data segment is also relative to address zero.
+-In this case since the addresses overlap it is necessary to use
+-the \fB?*\fR operator to access the data space of the \fIa.out\fP file.
+-In both 410 and 411 files the corresponding
+-core file does not contain the program text.
+-.PP
+-Figure 9 shows the display of three maps
+-for the same program linked as a 407, 410, 411 respectively.
+-The b, e, and f fields are used by ADB to map
+-addresses into file addresses.
+-The "f1" field is the
+-length of the header at the beginning of the file (020 bytes
+-for an \fIa.out\fP file and 02000 bytes for a \fIcore\fP file).
+-The "f2" field is the displacement from the beginning of the file to the data.
+-For a 407 file with mixed text and data this is the
+-same as the length of the header; for 410 and 411 files this
+-is the length of the header plus the size of the text portion.
+-.PP
+-The "b" and "e" fields are the starting and ending locations
+-for a segment.
+-Given an address, A, the location in
+-the file (either \fIa.out\fP or \fIcore\fP) is calculated as:
+-.P1
+-      b1\(<=A\(<=e1 =\h'-.5m'> file address = (A\-b1)+f1
+-      b2\(<=A\(<=e2 =\h'-.5m'> file address = (A\-b2)+f2
+-.P2
+-A user can access locations by using the ADB defined variables.
+-The \fB$v\fR request prints the variables initialized by ADB:
+-.P1
+-      b       base address of data segment
+-      d       length of the data segment
+-      s       length of the stack
+-      t       length of the text
+-      m       execution type (407,410,411)
+-.P2
+-.PP
+-In Figure 9 those variables not present are zero.
+-Use can be made of these variables by expressions such as:
+-.P1
+-      <b
+-.P2
+-in the address field.
+-Similarly the value of the variable can be changed by an assignment request
+-such as:
+-.P1
+-      02000>b
+-.P2
+-that sets \fBb\fP to octal 2000.
+-These variables are useful to know if the file under examination
+-is an executable or \fIcore\fP image file.
+-.PP
+-ADB reads the header of the \fIcore\fP image file to find the
+-values for these variables.
+-If the second file specified does not
+-seem to be a \fIcore\fP file, or if it is missing then the header of
+-the executable file is used instead.
+-.NH
+-Advanced Usage
+-.PP
+-It is possible with ADB to combine formatting requests
+-to provide elaborate displays.
+-Below are several examples.
+-.NH 2
+-Formatted dump
+-.PP
+-The line:
+-.P1
+-      <b,\-1/4o4^8Cn
+-.P2
+-prints 4 octal words followed by their ASCII interpretation
+-from the data space of the core image file.
+-Broken down, the various request pieces mean:
+-.sp
+-.in 1.7i
+-.ta .7i
+-.ti -.7i
+-<b    The base address of the data segment.
+-.sp
+-.ti -.7i
+-<b,\-1        Print from the base address to the end of file.
+-A negative count is used here and elsewhere to loop indefinitely
+-or until some error condition (like end of file) is detected.
+-.sp
+-.ti -1.7i
+-The format \fB4o4^8Cn\fR is broken down as follows:
+-.sp
+-.ti -.7i
+-4o    Print 4 octal locations.
+-.sp
+-.ti -.7i
+-4^    Backup the current address 4 locations (to the original start of the field).
+-.sp
+-.ti -.7i
+-8C    Print 8 consecutive characters using an escape convention;
+-each character in the range 0 to 037 is printed as @ followed by the corresponding character in the range 0140 to 0177.
+-An @ is printed as @@.
+-.sp
+-.ti -.7i
+-n     Print a newline.
+-.in -1.7i
+-.fi
+-.sp
+-.PP
+-The request:
+-.P1
+-      <b,<d/4o4^8Cn
+-.P2
+-could have been used instead to allow the printing to stop
+-at the end of the data segment (<d provides the data segment size in bytes).
+-.PP
+-The formatting requests can be combined with ADB's ability
+-to read in a script to produce a core image dump script.
+-ADB is invoked as:
+-.P1
+-      adb a.out core < dump
+-.P2
+-to read in a script file,
+-.ul
+-dump,
+-of requests.
+-An example of such a script is:
+-.P1
+-      120$w
+-      4095$s
+-      $v
+-      =3n
+-      $m
+-      =3n"C Stack Backtrace"
+-      $C
+-      =3n"C External Variables"
+-      $e
+-      =3n"Registers"
+-      $r
+-      0$s
+-      =3n"Data Segment"
+-      <b,\-1/8ona
+-.P2
+-.PP
+-The request \fB120$w\fP sets the width of the output to
+-120 characters
+-(normally, the width is 80 characters).
+-ADB attempts to print addresses as:
+-.P1
+-      symbol + offset
+-.P2
+-The request \fB4095$s\fP increases the maximum permissible offset
+-to the nearest symbolic address from 255 (default) to 4095.
+-The request \fB=\fP can be used to print literal strings.
+-Thus,
+-headings are provided in this
+-.ul
+-dump
+-program
+-with requests of the form:
+-.P1
+-      =3n"C Stack Backtrace"
+-.P2
+-that spaces three lines and prints the literal
+-string.
+-The request \fB$v\fP prints all non-zero ADB variables (see Figure 8).
+-The request
+-\fB0$s\fP
+-sets the maximum offset for symbol matches to zero thus
+-suppressing the printing of symbolic labels in favor
+-of octal values.
+-Note that this is only done for the printing of the data segment.
+-The request:
+-.P1
+-      <b,\-1/8ona
+-.P2
+-prints a dump from the base of the data segment to the end of file
+-with an octal address field and eight octal numbers per line.
+-.PP
+-Figure 11 shows the results of some formatting requests
+-on the C program of Figure 10.
+-.NH 2
+-Directory Dump
+-.PP
+-As another illustration (Figure 12) consider a set of requests to dump
+-the contents of a directory (which is made up
+-of an integer \fIinumber\fP followed by a 14 character name):
+-.P1
+-      adb dir \-
+-      =n8t"Inum"8t"Name"
+-      0,\-1? u8t14cn
+-.P2
+-In this example, the \fBu\fP prints the \fIinumber\fP as an unsigned decimal integer,
+-the \fB8t\fP means that ADB will space to the next
+-multiple of 8 on the output line, and the \fB14c\fP prints the 14 character file name.
+-.NH 2
+-Ilist Dump
+-.PP
+-Similarly the contents of the \fIilist\fP of a file system, (e.g. /dev/src,
+-on UNIX systems distributed by the UNIX Support Group;
+-see UNIX Programmer's
+-Manual Section V) could be dumped with the following set of 
+-requests:
+-.P1
+-      adb /dev/src \-
+-      02000>b
+-      ?m <b
+-      <b,\-1?"flags"8ton"links,uid,gid"8t3bn",size"8tbrdn"addr"8t8un"times"8t2Y2na
+-.P2
+-In this example the value of the base for the map was changed 
+-to 02000 (by saying \fB?m<b\fR) since that is the start of an \fIilist\fP within a file system.
+-An artifice (\fBbrd\fP above) was used to print the 24 bit size field
+-as a byte, a space, and a decimal integer.
+-The last access time and last modify time are printed with the
+-\fB2Y\fR
+-operator.
+-Figure 12 shows portions of these requests as applied to a directory
+-and file system.
+-.NH 2
+-Converting values
+-.PP
+-ADB may be used to convert values from one representation to
+-another.
+-For example:
+-.P1
+-      072 = odx
+-.P2
+-will print
+-.P1
+-      072     58      #3a
+-.P2
+-which is the octal, decimal and hexadecimal representations
+-of 072 (octal).
+-The format is remembered so that typing
+-subsequent numbers will print them in the given formats.
+-Character values may be converted similarly, for example:
+-.P1
+-      'a' = co
+-.P2
+-prints
+-.P1
+-      a       0141
+-.P2
+-It may also be used to evaluate expressions but be
+-warned that all binary operators have
+-the same precedence which is lower than that for unary operators.
+-.NH
+-Patching
+-.PP
+-Patching files with ADB is accomplished with the 
+-.ul
+-write,
+-\fBw\fP or \fBW\fP, request (which is not like the \fIed\fP editor write command).
+-This is often used in conjunction with the 
+-.ul
+-locate,
+-\fBl\fP or \fBL\fP
+-request.
+-In general, the request syntax for \fBl\fP and \fBw\fP are similar as follows:
+-.P1
+-      ?l value
+-.P2
+-The request \fBl\fP is used to match on two bytes, \fBL\fP is used for
+-four bytes.
+-The request \fBw\fP is used to write two bytes, whereas
+-\fBW\fP writes four bytes.
+-The \fBvalue\fP field in either 
+-.ul
+-locate
+-or
+-.ul
+-write
+-requests
+-is an expression.
+-Therefore, decimal and octal numbers, or character strings are supported.
+-.PP
+-In order to modify a file, ADB must be called as:
+-.P1
+-      adb \-w file1 file2
+-.P2
+-When called with this option, 
+-.ul
+-file1
+-and 
+-.ul
+-file2
+-are created if necessary and opened for both reading and writing.
+-.PP
+-For example, consider the C program shown in Figure 10.
+-We can change the word "This" to "The " in the executable file
+-for this program, \fIex7\fP, by using the following requests:
+-.P1
+-      adb \-w ex7 \-
+-      ?l 'Th'
+-      ?W 'The '
+-.P2
+-The request \fB?l\fP starts at dot and stops at the first match of "Th"
+-having set dot to the address of the location found.
+-Note the use of \fB?\fP to write to the 
+-.ul
+-a.out
+-file.
+-The form \fB?*\fP would have been used for a 411 file.
+-.PP
+-More frequently the 
+-request will be typed as:
+-.P1
+-      ?l 'Th'; ?s
+-.P2
+-and locates the first occurrence of "Th" and print the entire string.
+-Execution of this ADB request will set dot to the address of the 
+-"Th" characters.
+-.PP
+-As another example of the utility of the patching facility,
+-consider a C program that has an internal logic flag.
+-The flag could be set by the user through ADB and the program run.
+-For example:
+-.P1
+-      adb a.out \-
+-      :s arg1 arg2
+-      flag/w 1
+-      :c
+-.P2
+-The \fB:s\fR request is normally used to single step through a process
+-or start a process in single step mode.
+-In this case it starts
+-.ul
+-a.out
+-as a subprocess
+-with arguments \fBarg1\fP and \fBarg2\fP.
+-If there is a subprocess running ADB writes to it rather than to the file
+-so the \fBw\fP request causes \fIflag\fP to be changed in the memory of the subprocess.
+-.NH
+-Anomalies
+-.PP
+-Below is a list of some strange things that users
+-should be aware of.
+-.IP 1.
+-Function calls and arguments are put on the stack by the C
+-save routine.
+-Putting breakpoints at the entry point to routines
+-means that the function appears not to have been called
+-when the
+-breakpoint occurs.
+-.IP 2.
+-When printing addresses, ADB uses
+-either text or data symbols from the \fIa.out\fP file.
+-This sometimes causes unexpected symbol names to be printed 
+-with data (e.g. \fIsavr5+022\fP).
+-This does not happen if
+-\fB?\fR is used for text (instructions)
+-and \fB/\fP for data.
+-.IP 3.
+-ADB cannot handle C register variables
+-in the most recently activated function.
+-.LP
+-.NH
+-Acknowledgements
+-.PP
+-The authors are grateful for the thoughtful comments
+-on how to organize this document
+-from R. B. Brandt, E. N. Pinson and B. A. Tague.
+-D. M. Ritchie made the system changes necessary to accommodate
+-tracing within ADB. He also participated in discussions 
+-during the writing of ADB.
+-His earlier work with DB and CDB led to many of the 
+-features found in ADB.
+-.SG MH-8234-JFM/1273-SRB-unix
+-.NH
+-References
+-.LP
+-.IP 1.
+-D. M. Ritchie and K. Thompson,
+-``The UNIX Time-Sharing System,''
+-CACM, July, 1974.
+-.IP 2.
+-B. W. Kernighan and D. M. Ritchie,
+-.ul
+-The C Programming Language,
+-Prentice-Hall, 1978.
+-.IP 3.
+-K. Thompson and D. M. Ritchie,
+-UNIX Programmer's Manual - 7th Edition,
+-1978.
+-.IP 4.
+-B. W. Kernighan and P. J. Plauger,
+-.ul
+-Software Tools,
+-Addison-Wesley, 1976.
+//GO.SYSIN DD tut
+echo tut1
+sed 's/.//' >tut1 <<'//GO.SYSIN DD tut1'
+-.sp 100
+-.nr PS 9
+-.nr VS 11
+-.     \" START OF Figures
+-.de P1
+-.nf
+-.in +.5i
+-.ta .5i 1i 1.5i 2i 2.5i 3i 3.5i 4i 4.5i 5i
+-.sp
+-.ps 9
+-.vs 11p
+-..
+-.de P2
+-.sp
+-.fi
+-.ps \\n(PS
+-.vs \\n(VS
+-.in -.5i
+-..
+-.SH
+-Figure 1:  C program with pointer bug
+-.LP
+-.P1
+-struct buf {
+-      int fildes;
+-      int nleft;
+-      char *nextp;
+-      char buff[512];
+-      }bb;
+-struct buf *obuf;
+-
+-char *charp "this is a sentence.";
+-
+-main(argc,argv)
+-int argc;
+-char **argv;
+-{
+-      char    cc;
+-
+-      if(argc < 2) {
+-              printf("Input file missing\\n");
+-              exit(8);
+-      }
+-
+-      if((fcreat(argv[1],obuf)) < 0){
+-              printf("%s : not found\\n", argv[1]);
+-              exit(8);
+-      }
+-      charp = \'T\';
+-printf("debug 1 %s\\n",charp);
+-      while(cc=  *charp++)
+-              putc(cc,obuf);
+-      fflush(obuf);
+-}
+-.P2
+-.sp 100
+-.SH
+-Figure 2:  ADB output for C program of Figure 1
+-.LP
+-.P1
+-.ft B
+-adb a.out core
+-$c
+-.ft R
+-~main(02,0177762)
+-.ft B
+-$C
+-.ft R
+-~main(02,0177762)
+-      argc:       02
+-      argv:       0177762
+-      cc:         02124
+-.ft B
+-$r
+-.ft R
+-ps    0170010
+-pc    0204    ~main+0152
+-sp    0177740
+-r5    0177752
+-r4    01
+-r3    0
+-r2    0
+-r1    0
+-r0    0124
+-~main+0152:   mov     _obuf,(sp)
+-.ft B
+-$e
+-.ft R
+-savr5:            0
+-_obuf:            0
+-_charp:           0124
+-_errno:           0
+-_fout:            0
+-.ft B
+-$m
+-.ft R
+-text map    \`ex1\'
+-b1 = 0                     e1 = 02360           f1 = 020
+-b2 = 0                     e2 = 02360           f2 = 020
+-data map    \`core1\'
+-b1 = 0                     e1 = 03500           f1 = 02000
+-b2 = 0175400       e2 = 0200000                 f2 = 05500
+-.ft B
+-*charp/s
+-.ft R
+-0124:         TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT\1dL\ 3x\7f  \ 3N\1dh\ 4@\1dx\7f&\10_
+-~
+-.ft B
+-charp/s
+-.ft R
+-_charp:               T
+- 
+-_charp+02:    this is a sentence.
+- 
+-_charp+026:   Input file missing
+-.ft B
+-main.argc/d
+-.ft R
+-0177756:      2
+-.ft B
+-*main.argv/3o
+-.ft R
+-0177762:      0177770 0177776 0177777
+-.ft B
+-0177770/s
+-.ft R
+-0177770:      a.out
+-.ft B
+-*main.argv/3o
+-.ft R
+-0177762:      0177770 0177776 0177777
+-.ft B
+-*"/s
+-.ft R
+-0177770:      a.out
+-.ft B
+- .=o
+-.ft R
+-              0177770
+-.ft B
+- .\(mi10/d
+-.ft R
+-0177756:      2
+-.ft B
+-$q
+-.P2
+-.sp 100
+-.SH
+-Figure 3:  Multiple function C program for stack trace illustration
+-.LP
+-.P1
+-int   fcnt,gcnt,hcnt;
+-h(x,y)
+-{
+-      int hi; register int hr;
+-      hi = x+1;
+-      hr = x\(miy+1;
+-      hcnt++ ;
+-      hj:
+-      f(hr,hi);
+-}
+-
+-g(p,q)
+-{
+-      int gi; register int gr;
+-      gi = q\(mip;
+-      gr = q\(mip+1;
+-      gcnt++ ;
+-      gj:
+-      h(gr,gi);
+-}
+-
+-f(a,b)
+-{
+-      int fi; register int fr;
+-      fi = a+2*b;
+-      fr = a+b;
+-      fcnt++ ;
+-      fj:
+-      g(fr,fi);
+-}
+-
+-main()
+-{
+-      f(1,1);
+-}
+-.P2
+-.sp 100
+-.SH
+-Figure 4:  ADB output for C program of Figure 3
+-.LP
+-.P1
+-.ft B
+-adb
+-$c
+-.ft R
+-~h(04452,04451)
+-~g(04453,011124)
+-~f(02,04451)
+-~h(04450,04447)
+-~g(04451,011120)
+-~f(02,04447)
+-~h(04446,04445)
+-~g(04447,011114)
+-~f(02,04445)
+-~h(04444,04443)
+-.ft B
+-HIT DEL KEY
+-.ft R
+-adb
+-.ft B
+-,5$C
+-.ft R
+-~h(04452,04451)
+-      x:          04452
+-      y:          04451
+-      hi:         ?
+-~g(04453,011124)
+-      p:          04453
+-      q:          011124
+-      gi:         04451
+-      gr:         ?
+-~f(02,04451)
+-      a:          02
+-      b:          04451
+-      fi:         011124
+-      fr:         04453
+-~h(04450,04447)
+-      x:          04450
+-      y:          04447
+-      hi:         04451
+-      hr:         02
+-~g(04451,011120)
+-      p:          04451
+-      q:          011120
+-      gi:         04447
+-      gr:         04450
+-.ft B
+-fcnt/d
+-.ft R
+-_fcnt:                1173
+-.ft B
+-gcnt/d
+-.ft R
+-_gcnt:                1173
+-.ft B
+-hcnt/d
+-.ft R
+-_hcnt:                1172
+-.ft B
+-h.x/d
+-.ft R
+-022004:               2346
+-.ft B
+-$q
+-.P2
+-.sp 100
+-.SH
+-Figure 5:  C program to decode tabs
+-.LP
+-.P1
+-#define MAXLINE       80
+-#define YES           1
+-#define NO            0
+-#define TABSP         8
+-.sp .5
+-char  input[] "data";
+-char  ibuf[518];
+-int   tabs[MAXLINE];
+-.sp .5
+-main()
+-{
+-      int col, *ptab;
+-      char c;
+-.sp .5
+-      ptab = tabs;
+-      settab(ptab);   /*Set initial tab stops */
+-      col = 1;
+-      if(fopen(input,ibuf) < 0) {
+-              printf("%s : not found\\n",input);
+-              exit(8);
+-      }
+-      while((c = getc(ibuf)) != \(mi1) {
+-              switch(c) {
+-                      case \(fm\\t\(fm:       /* TAB */
+-                              while(tabpos(col) != YES) {
+-                                      putchar(\(fm \(fm);     /* put BLANK */
+-                                      col++ ;
+-                              }
+-                              break;
+-                      case \(fm\\n\(fm:       /*NEWLINE */
+-                              putchar(\(fm\\n\(fm);
+-                              col = 1;
+-                              break;
+-                      default:
+-                              putchar(c);
+-                              col++ ;
+-              }
+-      }
+-}
+-.sp .5
+-/* Tabpos return YES if col is a tab stop */
+-tabpos(col)
+-int col;
+-{
+-      if(col > MAXLINE)
+-              return(YES);
+-      else
+-              return(tabs[col]);
+-}
+-.sp .5
+-/* Settab - Set initial tab stops */
+-settab(tabp)
+-int *tabp;
+-{
+-      int i;
+-.sp .5
+-      for(i = 0; i<= MAXLINE; i++) 
+-              (i%TABSP) ? (tabs[i] = NO) : (tabs[i] = YES);
+-}
+-.P2
+-.sp 100
+-.SH
+-Figure 6a:  ADB output for C program of Figure 5
+-.LP
+-.P1
+-.ft B
+-adb a.out \(mi
+-settab+4:b
+-fopen+4:b
+-getc+4:b
+-tabpos+4:b
+-$b
+-.ft R
+-breakpoints
+-count bkpt            command
+-1     ~tabpos+04
+-1     _getc+04
+-1     _fopen+04
+-1     ~settab+04
+-.ft B
+-settab,5?ia
+-.ft R
+-~settab:              jsr     r5,csv
+-~settab+04:   tst     \(mi(sp)
+-~settab+06:   clr     0177770(r5)
+-~settab+012:  cmp     $0120,0177770(r5)
+-~settab+020:  blt     ~settab+076
+-~settab+022:
+-.ft B
+-settab,5?i
+-.ft R
+-~settab:              jsr     r5,csv
+-              tst     \(mi(sp)
+-              clr     0177770(r5)
+-              cmp     $0120,0177770(r5)
+-              blt     ~settab+076
+-.ft B
+-:r
+-.ft R
+-a.out: running
+-breakpoint    ~settab+04:     tst     \(mi(sp)
+-.ft B
+-settab+4:d
+-:c
+-.ft R
+-a.out: running
+-breakpoint    _fopen+04:      mov     04(r5),nulstr+012
+-.ft B
+-$C
+-.ft R
+-_fopen(02302,02472)
+-~main(01,0177770)
+-      col:        01
+-      c:          0
+-      ptab:       03500
+-.ft B
+-tabs,3/8o
+-.ft R
+-03500:                01      0       0       0       0       0       0       0
+-              01      0       0       0       0       0       0       0
+-              01      0       0       0       0       0       0       0
+-.P2
+-.sp 100
+-.SH
+-Figure 6b:  ADB output for C program of Figure 5
+-.LP
+-.P1
+-.ft B
+-:c
+-.ft R
+-a.out: running
+-breakpoint    _getc+04:       mov     04(r5),r1
+-.ft B
+-ibuf+6/20c
+-.ft R
+-__cleanu+0202:                This    is      a test  of
+-.ft B
+-:c
+-.ft R
+-a.out: running
+-breakpoint    ~tabpos+04:     cmp     $0120,04(r5)
+-.ft B
+-tabpos+4:d
+-settab+4:b  settab,5?ia
+-settab+4:b  settab,5?ia;  0
+-getc+4,3:b  main.c?C;  0
+-settab+4:b  settab,5?ia;  ptab/o;  0
+-$b
+-.ft R
+-breakpoints
+-count bkpt            command
+-1     ~tabpos+04
+-3     _getc+04        main.c?C;0
+-1     _fopen+04
+-1     ~settab+04      settab,5?ia;ptab?o;0
+-~settab:              jsr     r5,csv
+-~settab+04:   bpt
+-~settab+06:   clr     0177770(r5)
+-~settab+012:  cmp     $0120,0177770(r5)
+-~settab+020:  blt     ~settab+076
+-~settab+022:
+-0177766:      0177770
+-0177744:      @\`
+-T0177744:     T
+-h0177744:     h
+-i0177744:     i
+-s0177744:     s
+-.P2
+-.sp 100
+-.SH
+-Figure 7:  ADB output for C program with breakpoints
+-.LP
+-.in +.5i
+-.nf
+-.ps 8
+-.vs 9
+-.ft B
+-adb ex3 \(mi
+-h+4:b hcnt/d; h.hi/; h.hr/
+-g+4:b gcnt/d; g.gi/; g.gr/
+-f+4:b fcnt/d; f.fi/; f.fr/
+-:r
+-.ft R
+-ex3: running
+-_fcnt:                0
+-0177732:      214
+-symbol not found
+-.ft B
+-f+4:b fcnt/d; f.a/; f.b/; f.fi/
+-g+4:b gcnt/d; g.p/; g.q/; g.gi/
+-h+4:b hcnt/d; h.x/; h.y/; h.hi/
+-:c
+-.ft R
+-ex3: running
+-_fcnt:                0
+-0177746:      1
+-0177750:      1
+-0177732:      214
+-_gcnt:                0
+-0177726:      2
+-0177730:      3
+-0177712:      214
+-_hcnt:                0
+-0177706:      2
+-0177710:      1
+-0177672:      214
+-_fcnt:                1
+-0177666:      2
+-0177670:      3
+-0177652:      214
+-_gcnt:                1
+-0177646:      5
+-0177650:      8
+-0177632:      214
+-.ft B
+-HIT DEL
+-f+4:b fcnt/d; f.a/"a = "d; f.b/"b = "d; f.fi/"fi = "d
+-g+4:b gcnt/d; g.p/"p = "d; g.q/"q = "d; g.gi/"gi = "d
+-h+4:b hcnt/d; h.x/"x = "d; h.y/"h = "d; h.hi/"hi = "d
+-:r
+-.ft R
+-ex3: running
+-_fcnt:                0
+-0177746:      a = 1
+-0177750:      b = 1
+-0177732:      fi = 214
+-_gcnt:                0
+-0177726:      p = 2
+-0177730:      q = 3
+-0177712:      gi = 214
+-_hcnt:                0
+-0177706:      x = 2
+-0177710:      y = 1
+-0177672:      hi = 214
+-_fcnt:                1
+-0177666:      a = 2
+-0177670:      b = 3
+-0177652:      fi = 214
+-.ft B
+-HIT DEL
+-$q
+-.in -.5i
+-.sp 100
+-.SH
+-Figure 8:  ADB address maps
+-.LP
+-.de l1
+-.tc
+-.ta 1.20i +1.6i +2.5i
+-..
+-.de l3
+-.tc
+-.ta 1.6i +2.80i +.2i +1.55i
+-..
+-.de l2
+-.tc
+-.ti 1.0i
+-.ta +0.5i +3.0i +1.75i
+-.tc _
+-..
+-.de l5
+-.tc 
+-.ti 1.0i
+-.ta +0.75i +3.0i +1.5i
+-.tc _
+-..
+-.de l6
+-.tc
+-.ti 1.0i
+-.ta +.8i +2.85i +0.4i +1.1i
+-..
+-.de l8
+-.tc
+-.ti 1.0i
+-.ta +0.5i +3.0i +1.75i
+-.tc _
+-..
+-.de la
+-.tc
+-.ta 1.20i +1.25i +1.7i
+-..
+-.de lc
+-.tc
+-.ti 1.0i
+-.ta +.85i +1.6i +.35i +1.1i
+-..
+-.de lb
+-.tc
+-.ti 1.0i
+-.ta +0.75i +1.75i +1.5i
+-.tc _
+-..
+-.ul
+-407 files
+-.sp
+-.l1
+-a.out hdr     text+data
+-.l2
+-|     |       |
+-.l3
+-      0       D
+-.sp
+-.l1
+-core  hdr     text+data       stack
+-.l5
+-|     |       ......| |
+-.l6
+-      0       D       S       E
+-.sp 2
+-.ul
+-410 files (shared text)
+-.sp
+-.l1
+-a.out hdr      text   data
+-.l2
+-|     |       |       |
+-.l3
+-      0       T       B       D
+-.sp
+-.la
+-core  hdr     data    stack
+-.lb
+-|     |       ......| |
+-.lc
+-      B       D       S       E
+-.sp 2
+-.ul
+-411 files (separated I and D space)
+-.sp
+-.l1
+-a.out hdr     text    data
+-.l2
+-|     |       |       |
+-.l3
+-      0       T       0       D
+-.sp
+-.la
+-core  hdr     data    stack
+-.lb
+-|     |       ......| |
+-.lc
+-      0       D       S       E
+-.sp 2
+-The following 
+-.ul 
+-adb
+-variables are set.
+-.nf
+-.ta .75i 1.5i 3.5i 4.5i 5.5i
+-.sp
+-                      407     410     411
+-.sp
+-      b       base of data    0       B       0
+-      d       length of data  D       D\(miB  D
+-      s       length of stack S       S       S
+-      t       length of text  0       T       T
+-.sp 100
+-.SH
+-Figure 9:  ADB output for maps
+-.LP
+-.nf
+-.in +.5i
+-.ft B
+-adb map407 core407
+-$m
+-.ft R
+-text map    \`map407\'
+-b1 = 0                     e1 = 0256            f1 = 020
+-b2 = 0                     e2 = 0256            f2 = 020
+-data map    \`core407\'
+-b1 = 0                     e1 = 0300            f1 = 02000
+-b2 = 0175400       e2 = 0200000         f2 = 02300
+-.ft B
+-$v
+-.ft R
+-variables
+-d = 0300
+-m = 0407
+-s = 02400
+-.ft B
+-$q
+-.sp 2
+-adb map410 core410
+-$m
+-.ft R
+-text map    \`map410\'
+-b1 = 0                     e1 = 0200            f1 = 020
+-b2 = 020000        e2 = 020116          f2 = 0220
+-data map    \`core410\'
+-b1 = 020000        e1 = 020200          f1 = 02000
+-b2 = 0175400       e2 = 0200000         f2 = 02200
+-.ft B
+-$v
+-.ft R
+-variables
+-b = 020000
+-d = 0200
+-m = 0410
+-s = 02400
+-t = 0200
+-.ft B
+-$q
+-.sp 2
+-adb map411 core411
+-$m
+-.ft R
+-text map    \`map411\'
+-b1 = 0                     e1 = 0200            f1 = 020
+-b2 = 0                     e2 = 0116            f2 = 0220
+-data map    \`core411\'
+-b1 = 0                     e1 = 0200            f1 = 02000
+-b2 = 0175400       e2 = 0200000         f2 = 02200
+-.ft B
+-$v
+-.ft R
+-variables
+-d = 0200
+-m = 0411
+-s = 02400
+-t = 0200
+-.ft B
+-$q
+-.in -.5i
+-.sp 100
+-.SH
+-Figure 10:  Simple C program for illustrating formatting and patching
+-.LP
+-.P1
+-char  str1[]  "This is a character string";
+-int   one     1;
+-int   number  456;
+-long  lnum    1234;
+-float fpt     1.25;
+-char  str2[]  "This is the second character string";
+-main()
+-{
+-      one = 2;
+-}
+-.P2
+-.sp 100
+-.SH
+-Figure 11:  ADB output illustrating fancy formats
+-.LP
+-.nf
+-.ps 9
+-.vs 11p
+-.ft B
+-adb map410 core410
+-<b,\(mi1/8ona
+-.ft R
+-020000:               0       064124  071551  064440  020163  020141  064143  071141
+-.sp .5
+-_str1+016:    061541  062564  020162  072163  064562  063556  0       02
+-.sp .5
+-_number:
+-_number:      0710    0       02322   040240  0       064124  071551  064440
+-.sp .5
+-_str2+06:     020163  064164  020145  062563  067543  062156  061440  060550
+-.sp .5
+-_str2+026:    060562  072143  071145  071440  071164  067151  0147    0
+-.sp .5
+-savr5+02:     0       0       0       0       0       0       0       0
+-.sp .5
+-.ft B
+-<b,20/4o4^8Cn
+-.ft R
+-020000:               0       064124  071551  064440  @\`@\`This i
+-              020163  020141  064143  071141  s a char
+-              061541  062564  020162  072163  acter st
+-              064562  063556  0       02      ring@\`@\`@b@\`
+-.sp .5
+-_number:      0710    0       02322   040240  H@a@\`@\`R@d @@
+-              0       064124  071551  064440  @\`@\`This i
+-              020163  064164  020145  062563  s the se
+-              067543  062156  061440  060550  cond cha
+-              060562  072143  071145  071440  racter s
+-              071164  067151  0147    0       tring@\`@\`@\`
+-              0       0       0       0       @\`@\`@\`@\`@\`@\`@\`@\`
+-              0       0       0       0       @\`@\`@\`@\`@\`@\`@\`@\`
+-data address not found
+-.ft B
+-<b,20/4o4^8t8cna
+-.ft R
+-020000:               0       064124  071551  064440          This i
+-_str1+06:     020163  020141  064143  071141          s a char
+-_str1+016:    061541  062564  020162  072163          acter st
+-_str1+026:    064562  063556  0       02              ring\ 2
+-_number:
+-_number:      0710    0       02322   040240          HR
+-_fpt+02:      0       064124  071551  064440          This i
+-_str2+06:     020163  064164  020145  062563          s the se
+-_str2+016:    067543  062156  061440  060550          cond cha
+-_str2+026:    060562  072143  071145  071440          racter  s
+-_str2+036:    071164  067151  0147    0               tring
+-savr5+02:     0       0       0       0
+-savr5+012:    0       0       0       0
+-data address not found
+-.ft B
+-<b,10/2b8t^2cn
+-.ft R
+-020000:               0       0
+-.sp .5
+-_str1:                0124    0150            Th
+-              0151    0163            is
+-              040     0151             i
+-              0163    040             s
+-              0141    040             a
+-              0143    0150            ch
+-              0141    0162            ar
+-              0141    0143            ac
+-              0164    0145            te
+-.ft B
+-$Q
+-.sp 100
+-.SH
+-Figure 12:  Directory and inode dumps
+-.LP
+-.nf
+-.ft B
+-adb dir \(mi
+-=nt"Inode"t"Name"
+-0,\(mi1?ut14cn
+-.ft R
+-
+-              Inode   Name
+-0:            652     .
+-              82      ..
+-              5971    cap.c
+-              5323    cap
+-              0       pp
+-.sp 4
+-.ft B
+-adb /dev/src \(mi
+-.ft B
+-02000>b
+-?m<b
+-.ft R
+-new map           \`/dev/src\'
+-b1 = 02000         e1 = 0100000000      f1 = 0
+-b2 = 0                     e2 = 0               f2 = 0
+-.ft B
+-$v
+-.ft R
+-variables
+-b = 02000
+-.ft B
+-<b,\(mi1?"flags"8ton"links,uid,gid"8t3bn"size"8tbrdn"addr"8t8un"times"8t2Y2na
+-.ft R
+-02000:                flags   073145
+-              links,uid,gid   0163    0164    0141
+-              size    0162    10356
+-              addr    28770   8236    25956   27766   25455   8236    25956   25206
+-              times   1976 Feb 5 08:34:56     1975 Dec 28 10:55:15
+-
+-02040:                flags   024555
+-              links,uid,gid   012     0163    0164
+-              size    0162    25461
+-              addr    8308    30050   8294    25130   15216   26890   29806   10784
+-              times   1976 Aug 17 12:16:51    1976 Aug 17 12:16:51
+-
+-02100:                flags   05173
+-              links,uid,gid   011     0162    0145
+-              size    0147    29545
+-              addr    25972   8306    28265   8308    25642   15216   2314    25970
+-              times   1977 Apr 2 08:58:01     1977 Feb 5 10:21:44
+-.\"
+-.\"   Start of Summary
+-.sp 100
+-.TL
+-ADB Summary
+-.LP
+-.LP
+-.if t .2C
+-.nr VS 9
+-.nr VS 11
+-.SH
+-Command Summary
+-.LP
+-.ta .7i
+-a)   formatted printing
+-.sp .5
+-.IP "\fB? \fIformat\fR" .7i
+-print from \fIa.out\fR file according to \fIformat\fR
+-.IP "\fB/ \fIformat\fR" .7i
+-print from \fIcore\fR file according to \fIformat\fR
+-.IP "\fB= \fIformat\fR" .7i
+-print the value of \fIdot\fR
+-.sp .5
+-.IP "\fB?w\fR expr" .7i
+-write expression into \fIa.out\fR file
+-.IP "\fB/w\fR expr" .7i
+-write expression into \fIcore\fR file
+-.sp .5
+-.IP "\fB?l\fR expr" .7i
+-locate expression in \fIa.out\fR file
+-.LP
+-.ta .7i
+-b)   breakpoint and program control
+-.LP
+-.ta .7i
+-.nf
+-.ta .7i
+-\fB:b\fR      set breakpoint at \fIdot\fR
+-\fB:c\fR      continue running program
+-\fB:d\fR      delete breakpoint
+-\fB:k\fR      kill the program being debugged
+-\fB:r\fR      run \fIa.out\fR file under ADB control
+-\fB:s\fR      single step
+-.LP
+-.ta .7i
+-c)   miscellaneous printing
+-.LP
+-.ta .7i
+-.nf
+-\fB$b\fR      print current breakpoints
+-\fB$c\fR      C stack trace
+-\fB$e\fR      external variables
+-\fB$f\fR      floating registers
+-\fB$m\fR      print ADB segment maps
+-\fB$q\fR      exit from ADB
+-\fB$r\fR      general registers
+-\fB$s\fR      set offset for symbol match
+-\fB$v\fR      print ADB variables
+-\fB$w\fR      set output line width
+-.LP
+-.ta .7i
+-d)   calling the shell
+-.LP
+-.ta .7i
+-.nf
+-\fB!\fR       call \fIshell\fP to read rest of line
+-.LP
+-.ta .7i
+-e)   assignment to variables
+-.LP
+-.ta .7i
+-.nf
+-\fB>\fIname\fR        assign dot to variable or register \fIname\fR
+-.sp 100
+-.SH
+-Format Summary
+-.LP
+-.ta .7i
+-.nf
+-\fBa  \fRthe value of dot
+-\fBb  \fRone byte in octal
+-\fBc  \fRone byte as a character
+-\fBd  \fRone word in decimal
+-\fBf  \fRtwo words in floating point
+-\fBi  \fRPDP 11 instruction
+-\fBo  \fRone word in octal
+-\fBn  \fRprint a newline
+-\fBr  \fRprint a blank space
+-\fBs  \fRa null terminated character string
+-\fIn\fBt      \fRmove to next \fIn\fR space tab
+-\fBu  \fRone word as unsigned integer
+-\fBx  \fRhexadecimal
+-\fBY  \fRdate
+-\fB^  \fRbackup dot
+-\fB"..."\fR   print string
+-.LP
+-.ta .7i
+-.SH
+-Expression Summary
+-.LP
+-.ta .7i
+-a) expression components
+-.LP
+-.ta .1.1i
+-.nf
+-\fBdecimal integer    \fRe.g. 256
+-\fBoctal integer      \fRe.g. 0277
+-\fBhexadecimal        \fRe.g. #ff
+-\fBsymbols    \fRe.g. flag  _main  main.argc
+-\fBvariables  \fRe.g. <b
+-\fBregisters  \fRe.g. <pc <r0
+-\fB(expression)       \fRexpression grouping
+-.LP
+-.ta .7i
+-b) dyadic operators
+-.LP
+-.ta .7i
+-.nf
+-\fB+\fP       add
+-\fB\(mi\fP    subtract
+-\fB*\fP       multiply
+-\fB%\fP       integer division
+-\fB&\fP       bitwise and
+-\fB|\fP       bitwise or
+-\fB#\fP       round up to the next multiple
+-.LP
+-.ta .7i
+-c) monadic operators
+-.LP
+-.ta .7i
+-.nf
+-\v'.25m'\s+2\fB~\fP\s0\v'-.25m'       not
+-\fB*\fR       contents of location
+-\fB\(mi\fR    integer negate
+-.fi
+//GO.SYSIN DD tut1
diff --git a/doc/7thEdMan/vol2/adv.ed.bun b/doc/7thEdMan/vol2/adv.ed.bun
new file mode 100644 (file)
index 0000000..1741c90
--- /dev/null
@@ -0,0 +1,2857 @@
+# To unbundle, run this file
+echo ae.mac
+sed 's/.//' >ae.mac <<'//GO.SYSIN DD ae.mac'
+-.tr _\(em
+-.de UL
+-.if n .ul
+-.if n \\$3\\$1\\$2
+-.if t \\$3\f3\\$1\fP\\$2
+-..
+-.de IT
+-.if t \\$3\f2\\$1\fP\\$2
+-.if n .ul
+-.if n \\$3\\$1\\$2
+-..
+-.de UI
+-\f3\\$1\fI\\$2\fR\\$3
+-..
+-.de P1
+-.if n .ls 1
+-.nf
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ta .3i .6i .9i 1.2i 1.5i 1.8i
+-.tr -\-
+-.             use first argument as indent if present
+-.if \\n(.$ .DS I \\$1
+-.if !\\n(.$ .DS I 5
+-..
+-.de P2
+-.DE
+-.tr --
+-.if n .ls 2
+-..
+-.if t .ds B \s6\|\v'.1m'\(sq\v'-.1m'\|\s0
+-.if n .ds B [\b]
+-.if t .ds m \(mi
+-.if n .ds m -
+-.if t .ds n \(no
+-.if n .ds n -
+-.if t .ds s \v'.41m'\s+4*\s-4\v'-.41m'
+-.if n .ds s *
+-.if t .ds S \(sl
+-.if n .ds S /
+-.if t .ds d \s+4\&.\&\s-4
+-.if n .ds d \&.\&
+-.if t .ds a \z@@
+-.if n .ds a @
+-.if t .ds . \s+2\fB.\fP\s-2
+-.if n .ds . .
+-.if t .ds e \z\e\h'2u'\e
+-.if n .ds e \e
+-.hy 14
+-.     2=not last lines; 4= no -xx; 8=no xx-
+-.tr *\(**
+//GO.SYSIN DD ae.mac
+echo ae0
+sed 's/.//' >ae0 <<'//GO.SYSIN DD ae0'
+-.....TM 76-1273-8 39199 39199-11
+-.RP
+-.TL
+-Advanced Editing on UNIX
+-.AU "MH 2C518" 6021
+-Brian W. Kernighan
+-.AI
+-.MH
+-.AB
+-This paper is meant to help
+-secretaries, typists and programmers
+-to make effective use of the
+-.UX
+-facilities
+-for preparing and editing text.
+-It provides explanations and examples of
+-.IP \(bu
+-special characters, line addressing and global commands in the editor
+-.UL ed ;
+-.IP \(bu
+-commands for ``cut and paste'' operations on files
+-and parts of files,
+-including the
+-.UL mv ,
+-.UL cp ,
+-.UL cat
+-and
+-.UL rm
+-commands,
+-and the
+-.UL r ,
+-.UL w ,
+-.UL m
+-and
+-.UL t
+-commands of the editor;
+-.IP \(bu
+-editing scripts and
+-editor-based programs like
+-.UL grep
+-and
+-.UL sed .
+-.PP
+-Although the treatment is aimed
+-at non-programmers,
+-new
+-.UC UNIX
+-users
+-with any background
+-should find helpful hints
+-on how to get their jobs done
+-more easily.
+-.AE
+-.CS 16 0 16 0 0 3
+-.if n .ls 2
+-.if t .2C
+-.nr PS 9
+-.nr VS 11
+//GO.SYSIN DD ae0
+echo ae1
+sed 's/.//' >ae1 <<'//GO.SYSIN DD ae1'
+-.NH
+-INTRODUCTION
+-.PP
+-Although
+-.UX
+-provides remarkably effective tools for text editing,
+-that by itself is no guarantee
+-that everyone will automatically
+-make the most effective use of them.
+-In particular, people who are not computer specialists _
+-typists, secretaries, casual users _
+-often use the system less effectively than they might.
+-.PP
+-This document is intended as a sequel to
+-.ul
+-A Tutorial Introduction to the UNIX Text Editor
+-[1],
+-providing explanations and examples of how to edit with less effort.
+-(You should also be familiar with the material in
+-.ul
+-UNIX For Beginners
+-[2].)
+-Further information on all commands discussed here can be found in
+-.ul
+-The UNIX Programmer's Manual
+-[3].
+-.PP
+-Examples are based on observations
+-of users
+-and the difficulties they encounter.
+-Topics covered include special characters in searches and substitute commands,
+-line addressing, the global commands,
+-and line moving and copying.
+-There are also brief discussions of
+-effective use
+-of related tools, like those for file manipulation,
+-and those based on
+-.UL ed ,
+-like
+-.UL grep 
+-and
+-.UL sed .
+-.PP
+-A word of caution.
+-There is only one way to learn to use something,
+-and that is to
+-.ul
+-use
+-it.
+-Reading a description is no substitute
+-for trying something.
+-A paper like this one should
+-give you ideas about what to try,
+-but until you actually try something,
+-you will not learn it.
+//GO.SYSIN DD ae1
+echo ae2
+sed 's/.//' >ae2 <<'//GO.SYSIN DD ae2'
+-.NH
+-SPECIAL CHARACTERS
+-.PP
+-The editor
+-.UL ed
+-is the primary interface to the system
+-for many people, so
+-it is worthwhile to know
+-how to get the most out of
+-.UL ed
+-for the least effort.
+-.PP
+-The next few sections will discuss
+-shortcuts
+-and labor-saving devices.
+-Not all of these will be instantly useful
+-to any one person, of course,
+-but a few will be,
+-and the others should give you ideas to store
+-away for future use.
+-And as always,
+-until you try these things,
+-they will remain theoretical knowledge,
+-not something you have confidence in.
+-.SH
+-The List command `l'
+-.PP
+-.UL ed
+-provides two commands for printing the contents of the lines
+-you're editing.
+-Most people are familiar with
+-.UL p ,
+-in combinations like
+-.P1
+-1,$p
+-.P2
+-to print all the lines you're editing,
+-or
+-.P1
+-s/abc/def/p
+-.P2
+-to change 
+-`abc'
+-to
+-`def'
+-on the current line.
+-Less familiar is the
+-.ul
+-list
+-command
+-.UL l
+-(the letter `\fIl\|\fR'),
+-which gives slightly more information than
+-.UL p .
+-In particular,
+-.UL l
+-makes visible characters that are normally invisible,
+-such as tabs and backspaces.
+-If you list a line that contains some of these,
+-.UL l
+-will print each tab as
+-.UL \z\(mi>
+-and each backspace as
+-.UL \z\(mi< .
+-This makes it much easier to correct the sort of typing mistake
+-that inserts extra spaces adjacent to tabs,
+-or inserts a backspace followed by a space.
+-.PP
+-The
+-.UL l
+-command
+-also `folds' long lines for printing _
+-any line that exceeds 72 characters is printed on multiple lines;
+-each printed line except the last is terminated by a backslash 
+-.UL \*e ,
+-so you can tell it was folded.
+-This is useful for printing long lines on short terminals.
+-.PP
+-Occasionally the
+-.UL l
+-command will print in a line a string of numbers preceded by a backslash,
+-such as \*e07 or \*e16.
+-These combinations are used to make visible characters that normally don't print,
+-like form feed or vertical tab or bell.
+-Each such combination is a single character.
+-When you see such characters, be wary _
+-they may have surprising meanings when printed on some terminals.
+-Often their presence means that your finger slipped while you were typing;
+-you almost never want them.
+-.SH
+-The Substitute Command `s'
+-.PP
+-Most of the next few sections will be taken up with a discussion
+-of the
+-substitute
+-command
+-.UL s .
+-Since this is the command for changing the contents of individual
+-lines,
+-it probably has the most complexity of any 
+-.UL ed 
+-command,
+-and the most potential for effective use.
+-.PP
+-As the simplest place to begin,
+-recall the meaning of a trailing
+-.UL g
+-after a substitute command.
+-With
+-.P1
+-s/this/that/
+-.P2
+-and
+-.P1
+-s/this/that/g
+-.P2
+-the
+-first
+-one replaces the
+-.ul
+-first
+-`this' on the line
+-with `that'.
+-If there is more than one `this' on the line,
+-the second form
+-with the trailing
+-.UL g
+-changes
+-.ul
+-all
+-of them.
+-.PP
+-Either form of the
+-.UL s
+-command can be followed by
+-.UL p
+-or
+-.UL l
+-to `print' or `list' (as described in the previous section)
+-the contents of the line:
+-.P1
+-s/this/that/p
+-s/this/that/l
+-s/this/that/gp
+-s/this/that/gl
+-.P2
+-are all legal, and mean slightly different things.
+-Make sure you know what the differences are.
+-.PP
+-Of course, any
+-.UL s
+-command can be preceded by one or two `line numbers'
+-to specify that the substitution is to take place
+-on a group of lines. 
+-Thus
+-.P1
+-1,$s/mispell/misspell/
+-.P2
+-changes the 
+-.ul
+-first
+-occurrence of
+-`mispell' to `misspell' on every line of the file.
+-But
+-.P1
+-1,$s/mispell/misspell/g
+-.P2
+-changes 
+-.ul
+-every
+-occurrence in every line
+-(and this is more likely to be what you wanted in this
+-particular case).
+-.PP
+-You should also notice that if you add a
+-.UL p
+-or
+-.UL l
+-to the end of any of these substitute commands,
+-only the last line that got changed will be printed,
+-not all the lines.
+-We will talk later about how to print all the lines
+-that were modified.
+-.SH
+-The Undo Command `u'
+-.PP
+-Occasionally you will make a substitution in a line,
+-only to realize too late that it was a ghastly mistake.
+-The `undo' command
+-.UL u
+-lets you `undo' the last substitution:
+-the last line that was substituted can be restored to
+-its previous state by typing the command
+-.P1
+-u
+-.P2
+-.SH
+-The Metacharacter `\*.'
+-.PP
+-As you have undoubtedly noticed
+-when you use
+-.UL ed ,
+-certain characters have unexpected meanings
+-when they occur in the left side of a substitute command,
+-or in a search for a particular line.
+-In the next several sections, we will talk about
+-these special characters,
+-which are often called `metacharacters'.
+-.PP
+-The first one is the period `\*.'.
+-On the left side of a substitute command,
+-or in a search with `/.../',
+-`\*.' stands for
+-.ul
+-any
+-single character.
+-Thus the search
+-.P1
+-/x\*.y/
+-.P2
+-finds any line where `x' and `y' occur separated by
+-a single character, as in
+-.P1
+-x+y
+-x\-y
+-x\*By
+-x\*.y
+-.P2
+-and so on.
+-(We will use \*B to stand for a space whenever we need to
+-make it visible.)
+-.PP
+-Since `\*.' matches a single character,
+-that gives you a way to deal with funny characters
+-printed by
+-.UL l .
+-Suppose you have a line that, when printed with the
+-.UL l
+-command, appears as
+-.P1
+- ....   th\*e07is   ....
+-.P2
+-and you want to get rid of the 
+-\*e07
+-(which represents the bell character, by the way).
+-.PP
+-The most obvious solution is to try
+-.P1
+-s/\*e07//
+-.P2
+-but this will fail. (Try it.)
+-The brute force solution, which most people would now take,
+-is to re-type the entire line.
+-This is guaranteed, and is actually quite a reasonable tactic
+-if the line in question isn't too big,
+-but for a very long line,
+-re-typing is a bore.
+-This is where the metacharacter `\*.' comes in handy.
+-Since `\*e07' really represents a single character,
+-if we say
+-.P1
+-s/th\*.is/this/
+-.P2
+-the job is done.
+-The `\*.' matches the mysterious character between the `h' and the `i',
+-.ul
+-whatever it is.
+-.PP
+-Bear in mind that since `\*.' matches any single character,
+-the command
+-.P1
+-s/\*./,/
+-.P2
+-converts the first character on a line into a `,',
+-which very often is not what you intended.
+-.PP
+-As is true of many characters in
+-.UL ed ,
+-the `\*.' has several meanings, depending
+-on its context.
+-This line shows all three:
+-.P1
+-\&\*.s/\*./\*./
+-.P2
+-The first `\*.' is a line number,
+-the number of
+-the line we are editing,
+-which is called `line dot'.
+-(We will discuss line dot more in Section 3.)
+-The second `\*.' is a metacharacter
+-that matches any single character on that line.
+-The third `\*.' is the only one that really is
+-an honest literal period.
+-On the
+-.ul
+-right
+-side of a substitution, `\*.'
+-is not special.
+-If you apply this command to the line
+-.P1
+-Now is the time\*.
+-.P2
+-the result will
+-be
+-.P1
+-\&\*.ow is the time\*.
+-.P2
+-which is probably not what you intended.
+-.SH
+-The Backslash `\*e'
+-.PP
+-Since a period means `any character',
+-the question naturally arises of what to do
+-when you really want a period.
+-For example, how do you convert the line
+-.P1
+-Now is the time\*.
+-.P2
+-into
+-.P1
+-Now is the time?
+-.P2
+-The backslash `\*e' does the job.
+-A backslash turns off any special meaning that the next character
+-might have; in particular,
+-`\*e\*.' converts the `\*.' from a `match anything'
+-into a period, so
+-you can use it to replace
+-the period in
+-.P1
+-Now is the time\*.
+-.P2
+-like this:
+-.P1
+-s/\*e\*./?/
+-.P2
+-The pair of characters `\*e\*.' is considered by
+-.UL ed
+-to be a single real period.
+-.PP
+-The backslash can also be used when searching for lines
+-that contain a special character.
+-Suppose you are looking for a line that contains
+-.P1
+-\&\*.PP
+-.P2
+-The search
+-.P1
+-/\*.PP/
+-.P2
+-isn't adequate, for it will find
+-a line like
+-.P1
+-THE APPLICATION OF ...
+-.P2
+-because the `\*.' matches the letter `A'.
+-But if you say
+-.P1
+-/\*e\*.PP/
+-.P2
+-you will find only lines that contain `\*.PP'.
+-.PP
+-The backslash can also be used to turn off special meanings for
+-characters other than `\*.'.
+-For example, consider finding a line that contains a backslash.
+-The search
+-.P1
+-/\*e/
+-.P2
+-won't work,
+-because the `\*e' isn't a literal `\*e', but instead means that the second `/'
+-no longer \%delimits the search.
+-But by preceding a backslash with another one,
+-you can search for a literal backslash.
+-Thus
+-.P1
+-/\*e\*e/
+-.P2
+-does work.
+-Similarly, you can search for a forward slash `/' with
+-.P1
+-/\*e//
+-.P2
+-The backslash turns off the meaning of the immediately following `/' so that
+-it doesn't terminate the /.../ construction prematurely.
+-.PP
+-As an exercise, before reading further, find two substitute commands each of which will
+-convert the line
+-.P1
+-\*ex\*e\*.\*ey
+-.P2
+-into the line
+-.P1
+-\*ex\*ey
+-.P2
+-.PP
+-Here are several solutions;
+-verify that each works as advertised.
+-.P1
+-s/\*e\*e\*e\*.//
+-s/x\*.\*./x/
+-s/\*.\*.y/y/
+-.P2
+-.PP
+-A couple of miscellaneous notes about
+-backslashes and special characters.
+-First, you can use any character to delimit the pieces
+-of an
+-.UL s
+-command: there is nothing sacred about slashes.
+-(But you must use slashes for context searching.)
+-For instance, in a line that contains a lot of slashes already, like
+-.P1
+-//exec //sys.fort.go // etc...
+-.P2
+-you could use a colon as the delimiter _
+-to delete all the slashes, type
+-.P1
+-s:/::g
+-.P2
+-.PP
+-Second, if # and @ are your character erase and line kill characters,
+-you have to type \*e# and \*e@;
+-this is true whether you're talking to
+-.UL ed
+-or any other program.
+-.PP
+-When you are adding text with
+-.UL a
+-or
+-.UL i
+-or
+-.UL c ,
+-backslash is not special, and you should only put in
+-one backslash for each one you really want.
+-.SH
+-The Dollar Sign `$'
+-.PP
+-The next metacharacter, the `$', stands for `the end of the line'.
+-As its most obvious use, suppose you have the line
+-.P1
+-Now is the
+-.P2
+-and you wish to add the word `time' to the end.
+-Use the $ like this:
+-.P1
+-s/$/\*Btime/
+-.P2
+-to get
+-.P1
+-Now is the time
+-.P2
+-Notice that a space is needed before `time' in
+-the substitute command,
+-or you will get
+-.P1
+-Now is thetime
+-.P2
+-.PP
+-As another example, replace the second comma in
+-the following line with a period without altering the first:
+-.P1
+-Now is the time, for all good men,
+-.P2
+-The command needed is
+-.P1
+-s/,$/\*./
+-.P2
+-The $ sign here provides context to make specific which comma we mean.
+-Without it, of course, the
+-.UL s
+-command would operate on the first comma to produce
+-.P1
+-Now is the time\*. for all good men,
+-.P2
+-.PP
+-As another example, to convert
+-.P1
+-Now is the time\*.
+-.P2
+-into
+-.P1
+-Now is the time?
+-.P2
+-as we did earlier, we can use
+-.P1
+-s/\*.$/?/
+-.P2
+-.PP
+-Like `\*.', the `$'
+-has multiple meanings depending on context.
+-In the line
+-.P1
+-$s/$/$/
+-.P2
+-the first `$' refers to the
+-last line of the file,
+-the second refers to the end of that line,
+-and the third is a literal dollar sign,
+-to be added to that line.
+-.SH
+-The Circumflex `^'
+-.PP
+-The circumflex (or hat or caret)
+-`^' stands for the beginning of the line.
+-For example, suppose you are looking for a line that begins
+-with `the'.
+-If you simply say 
+-.P1
+-/the/
+-.P2
+-you will in all likelihood find several lines that contain `the' in the middle before
+-arriving at the one you want.
+-But with
+-.P1
+-/^the/
+-.P2
+-you narrow the context, and thus arrive at the desired one
+-more easily.
+-.PP
+-The other use of `^' is of course to enable you to insert
+-something at the beginning of a line:
+-.P1
+-s/^/\*B/
+-.P2
+-places a space at the beginning of the current line.
+-.PP
+-Metacharacters can be combined. To search for a
+-line that contains 
+-.ul
+-only 
+-the characters
+-.P1
+-\&\*.PP
+-.P2
+-you can use the command
+-.P1
+-/^\*e\*.PP$/
+-.P2
+-.SH
+-The Star `*'
+-.PP
+-Suppose you have a line that looks like this:
+-.P1
+-\fItext \fR x                y \fI text \fR
+-.P2
+-where 
+-.ul
+-text 
+-stands
+-for lots of text,
+-and there are some indeterminate number of spaces between the
+-.UL x
+-and the
+-.UL y .
+-Suppose the job is to replace all the spaces between
+-.UL x
+-and
+-.UL y
+-by a single space.
+-The line is too long to retype, and there are too many spaces
+-to count.
+-What now?
+-.PP
+-This is where the metacharacter `*'
+-comes in handy.
+-A character followed by a star
+-stands for as many consecutive occurrences of that
+-character as possible.
+-To refer to all the spaces at once, say
+-.P1
+-s/x\*B*y/x\*By/
+-.P2
+-The construction
+-`\*B*'
+-means
+-`as many spaces as possible'.
+-Thus `x\*B*y' means `an x, as many spaces as possible, then a y'.
+-.PP
+-The star can be used with any character, not just space.
+-If the original example was instead
+-.P1
+-\fItext \fR x--------y \fI text \fR
+-.P2
+-then all `\-' signs can be replaced by a single space
+-with the command
+-.P1
+-s/x-*y/x\*By/
+-.P2
+-.PP
+-Finally, suppose that the line was
+-.P1
+-\fItext \fR x\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.y \fI text \fR
+-.P2
+-Can you see what trap lies in wait for the unwary?
+-If you blindly type
+-.P1
+-s/x\*.*y/x\*By/
+-.P2
+-what will happen?
+-The answer, naturally, is that it depends.
+-If there are no other x's or y's on the line,
+-then everything works, but it's blind luck, not good management.
+-Remember that `\*.' matches
+-.ul
+-any
+-single character?
+-Then `\*.*' matches as many single characters as possible,
+-and unless you're careful, it can eat up a lot more of the line
+-than you expected.
+-If the line was, for example, like this:
+-.P1
+-\fItext  \fRx\fI  text  \fR x\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.\*.y \fI  text  \fRy\fI  text  \fR
+-.P2
+-then saying
+-.P1
+-s/x\*.*y/x\*By/
+-.P2
+-will take everything from the
+-.ul
+-first
+-`x' to the
+-.ul
+-last
+-`y',
+-which, in this example, is undoubtedly more than you wanted.
+-.PP
+-The solution, of course, is to turn off the special meaning of
+-`\*.' with
+-`\*e\*.':
+-.P1
+-s/x\*e\*.*y/x\*By/
+-.P2
+-Now everything works, for `\*e\*.*' means `as many
+-.ul
+-periods
+-as possible'.
+-.PP
+-There are times when the pattern `\*.*' is exactly what you want.
+-For example, to change
+-.P1
+-Now is the time for all good men ....
+-.P2
+-into
+-.P1
+-Now is the time\*.
+-.P2
+-use `\*.*' to eat up everything after the `for':
+-.P1
+-s/\*Bfor\*.*/\*./
+-.P2
+-.PP
+-There are a couple of additional pitfalls associated with `*' that you should be aware of.
+-Most notable is the fact that `as many as possible' means
+-.ul
+-zero
+-or more.
+-The fact that zero is a legitimate possibility is
+-sometimes rather surprising.
+-For example, if our line contained
+-.P1
+-\fItext \fR xy \fI text \fR x             y \fI text \fR
+-.P2
+-and we said
+-.P1
+-s/x\*B*y/x\*By/
+-.P2
+-the
+-.ul
+-first
+-`xy' matches this pattern, for it consists of an `x',
+-zero spaces, and a `y'.
+-The result is that the substitute acts on the first `xy',
+-and does not touch the later one that actually contains some intervening spaces.
+-.PP
+-The way around this, if it matters, is to specify a pattern like
+-.P1
+-/x\*B\*B*y/
+-.P2
+-which says `an x, a space, then as many more spaces as possible, then a y',
+-in other words, one or more spaces.
+-.PP
+-The other startling behavior of `*' is again related to the fact
+-that zero is a legitimate number of occurrences of something
+-followed by a star. The command
+-.P1
+-s/x*/y/g
+-.P2
+-when applied to the line
+-.P1
+-abcdef
+-.P2
+-produces
+-.P1
+-yaybycydyeyfy
+-.P2
+-which is almost certainly not what was intended.
+-The reason for this behavior is that zero is a legal number
+-of matches,
+-and there are no x's at the beginning of the line
+-(so that gets converted into a `y'),
+-nor between the `a' and the `b'
+-(so that gets converted into a `y'), nor ...
+-and so on.
+-Make sure you really want zero matches;
+-if not, in this case write
+-.P1
+-s/xx*/y/g
+-.P2
+-`xx*' is one or more x's.
+-.SH
+-The Brackets `[ ]'
+-.PP
+-Suppose that you want to delete any numbers
+-that appear
+-at the beginning of all lines of a file.
+-You might first think of trying a series of commands like
+-.P1
+-1,$s/^1*//
+-1,$s/^2*//
+-1,$s/^3*//
+-.P2
+-and so on,
+-but this is clearly going to take forever if the numbers are at all long.
+-Unless you want to repeat the commands over and over until
+-finally all numbers are gone,
+-you must get all the digits on one pass.
+-This is the purpose of the brackets [ and ].
+-.PP
+-The construction
+-.P1
+-[0123456789]
+-.P2
+-matches any single digit _
+-the whole thing is called a `character class'.
+-With a character class, the job is easy.
+-The pattern `[0123456789]*' matches zero or more digits (an entire number), so
+-.P1
+-1,$s/^[0123456789]*//
+-.P2
+-deletes all digits from the beginning of all lines.
+-.PP
+-Any characters can appear within a character class,
+-and just to confuse the issue there are essentially no special characters
+-inside the brackets;
+-even the backslash doesn't have a special meaning.
+-To search for special characters, for example, you can say
+-.P1
+-/[\*.\*e$^[]/
+-.P2
+-Within [...], the `[' is not special.
+-To get a `]' into a character class,
+-make it the first character.
+-.PP
+-It's a nuisance to have to spell out the digits,
+-so you can abbreviate them as
+-[0\-9];
+-similarly, [a\-z] stands for the lower case letters,
+-and
+-[A\-Z] for upper case.
+-.PP
+-As a final frill on character classes, you can specify a class
+-that means `none of the following characters'.
+-This is done by beginning the class with a `^':
+-.P1
+-[^0-9]
+-.P2
+-stands for `any character 
+-.ul
+-except
+-a digit'.
+-Thus you might find the first line that doesn't begin with a tab or space
+-by a search like
+-.P1
+-/^[^(space)(tab)]/
+-.P2
+-.PP
+-Within a character class,
+-the circumflex has a special meaning 
+-only if it occurs at the beginning.
+-Just to convince yourself, verify that
+-.P1
+-/^[^^]/
+-.P2
+-finds a line that doesn't begin with a circumflex.
+-.SH
+-The Ampersand `&'
+-.PP
+-The ampersand `&' is used primarily to save typing.
+-Suppose you have the line
+-.P1
+-Now is the time
+-.P2
+-and you want to make it
+-.P1
+-Now is the best time
+-.P2
+-Of course you can always say
+-.P1
+-s/the/the best/
+-.P2
+-but it seems silly to have to repeat the `the'.
+-The `&' is used to eliminate the repetition.
+-On the
+-.ul
+-right
+-side of a substitute, the ampersand means `whatever
+-was just matched', so you can say
+-.P1
+-s/the/& best/
+-.P2
+-and the `&' will stand for `the'.
+-Of course this isn't much of a saving if the thing
+-matched is just `the', but if it is something truly long or awful,
+-or if it is something like `.*'
+-which matches a lot of text,
+-you can save some tedious typing.
+-There is also much less chance of making a typing error
+-in the replacement text.
+-For example, to parenthesize a line,
+-regardless of its length,
+-.P1
+-s/\*.*/(&)/
+-.P2
+-.PP
+-The ampersand can occur more than once on the right side:
+-.P1
+-s/the/& best and & worst/
+-.P2
+-makes
+-.P1
+-Now is the best and the worst time
+-.P2
+-and
+-.P1
+-s/\*.*/&? &!!/
+-.P2
+-converts the original line into
+-.P1
+-Now is the time? Now is the time!!
+-.P2
+-.PP
+-To get a literal ampersand, naturally the backslash is used to turn off the special meaning:
+-.P1
+-s/ampersand/\*e&/
+-.P2
+-converts the word into the symbol.
+-Notice that `&' is not special on the left side
+-of a substitute, only on the
+-.ul
+-right 
+-side.
+-.SH
+-Substituting Newlines
+-.PP
+-.UL ed
+-provides a facility for splitting a single line into two or more shorter lines by `substituting in a newline'.
+-As the simplest example, suppose a line has gotten unmanageably long
+-because of editing (or merely because it was unwisely typed).
+-If it looks like
+-.P1
+-\fItext \fR   xy  \fI text \fR
+-.P2
+-you can break it between the `x' and the `y' like this:
+-.P1
+-s/xy/x\*e
+-y/
+-.P2
+-This is actually a single command,
+-although it is typed on two lines.
+-Bearing in mind that `\*e' turns off special meanings,
+-it seems relatively intuitive that a `\*e' at the end of
+-a line would make the newline there
+-no longer special.
+-.PP
+-You can in fact make a single line into several lines
+-with this same mechanism.
+-As a large example, consider underlining the word `very'
+-in a long line
+-by splitting `very' onto a separate line,
+-and preceding it by the
+-.UL roff
+-or
+-.UL nroff
+-formatting command `.ul'.
+-.P1
+-\fItext \fR a very big \fI text \fR
+-.P2
+-The command
+-.P1
+-s/\*Bvery\*B/\*e
+-\&.ul\*e
+-very\*e
+-/
+-.P2
+-converts the line into four shorter lines,
+-preceding the word `very' by the
+-line
+-`.ul',
+-and eliminating the spaces around the `very',
+-all at the same time.
+-.PP
+-When a newline is substituted
+-in, dot is left pointing at the last line created.
+-.PP
+-.SH
+-Joining Lines
+-.PP
+-Lines may also be joined together,
+-but this is done with the
+-.UL j
+-command
+-instead of
+-.UL s .
+-Given the lines
+-.P1
+-Now is
+-\*Bthe time
+-.P2
+-and supposing that dot is set to the first of them,
+-then the command
+-.P1
+-j
+-.P2
+-joins them together.
+-No blanks are added,
+-which is why we carefully showed a blank 
+-at the beginning of the second line.
+-.PP
+-All by itself,
+-a
+-.UL j
+-command
+-joins line dot to line dot+1,
+-but any contiguous set of lines can be joined.
+-Just specify the starting and ending line numbers.
+-For example,
+-.P1
+-1,$jp
+-.P2
+-joins all the lines into one big one
+-and prints it.
+-(More on line numbers in Section 3.)
+-.SH
+-Rearranging a Line with \*e( ... \*e)
+-.PP
+-(This section should be skipped on first reading.)
+-Recall that `&' is a shorthand that stands for whatever
+-was matched by the left side of an
+-.UL s
+-command.
+-In much the same way you can capture separate pieces
+-of what was matched;
+-the only difference is that you have to specify
+-on the left side just what pieces you're interested in.
+-.PP
+-Suppose, for instance, that 
+-you have a file of lines that consist of names in the form
+-.P1
+-Smith, A. B.
+-Jones, C.
+-.P2
+-and so on,
+-and you want the initials to precede the name, as in
+-.P1
+-A. B. Smith
+-C. Jones
+-.P2
+-It is possible to do this with a series of editing commands,
+-but it is tedious and error-prone.
+-(It is instructive to figure out how it is done, though.)
+-.PP
+-The alternative
+-is to `tag' the pieces of the pattern (in this case,
+-the last name, and the initials),
+-and then rearrange the pieces.
+-On the left side of a substitution,
+-if part of the pattern is enclosed between
+-\*e( and \*e),
+-whatever matched that part is remembered,
+-and available for use on the right side.
+-On the right side,
+-the symbol `\*e1' refers to whatever
+-matched the first \*e(...\*e) pair,
+-`\*e2' to the second \*e(...\*e),
+-and so on.
+-.PP
+-The command
+-.P1
+-1,$s/^\*e([^,]*\*e),\*B*\*e(\*.*\*e)/\*e2\*B\*e1/
+-.P2
+-although hard to read, does the job.
+-The first \*e(...\*e) matches the last name,
+-which is any string up to the comma;
+-this is referred to on the right side with `\*e1'.
+-The second \*e(...\*e) is whatever follows
+-the comma and any spaces,
+-and is referred to as `\*e2'.
+-.PP
+-Of course, with any editing sequence this complicated,
+-it's foolhardy to simply run it and hope.
+-The global commands 
+-.UL g
+-and 
+-.UL v
+-discussed in section 4
+-provide a way for you to print exactly those
+-lines which were affected by the
+-substitute command,
+-and thus verify that it did what you wanted
+-in all cases.
+//GO.SYSIN DD ae2
+echo ae3
+sed 's/.//' >ae3 <<'//GO.SYSIN DD ae3'
+-.NH
+-LINE ADDRESSING IN THE EDITOR
+-.PP
+-The next general area we will discuss is that of
+-line addressing in
+-.UL ed ,
+-that is, how you specify what lines are to be
+-affected by editing commands.
+-We have already used constructions like 
+-.P1
+-1,$s/x/y/
+-.P2
+-to specify a change on all lines.
+-And most users are long since familiar with
+-using a single newline (or return) to print the next line,
+-and with
+-.P1
+-/thing/
+-.P2
+-to find a line that contains `thing'.
+-Less familiar, surprisingly enough, is the
+-use of
+-.P1
+-?thing?
+-.P2
+-to scan
+-.ul
+-backwards
+-for the previous occurrence of `thing'.
+-This is especially handy when you realize that the thing
+-you want to operate on is back up the page from
+-where you are currently editing.
+-.PP
+-The slash and question mark are the only characters you can
+-use to delimit a context search, though you can use
+-essentially any character in a substitute command.
+-.SH
+-Address Arithmetic
+-.PP
+-The next step is to combine the line numbers
+-like `\*.', `$', `/.../' and `?...?'
+-with `+' and `\-'.
+-Thus
+-.P1
+-$-1
+-.P2
+-is a command to print the next to last line of
+-the current file (that is, one line before line `$').
+-For example, to recall how far you got in a previous editing session,
+-.P1
+-$-5,$p
+-.P2
+-prints the last six lines.
+-(Be sure you understand why it's six, not five.)
+-If there aren't six, of course, you'll get an error message.
+-.PP
+-As another example,
+-.P1
+-\&\*.-3,\*.+3p
+-.P2
+-prints from three lines before where you are now
+-(at line dot)
+-to three lines after,
+-thus giving you a bit of context.
+-By the way, the `+' can be omitted:
+-.P1
+-\&\*.-3,\*.3p
+-.P2
+-is absolutely identical in meaning.
+-.PP
+-Another area in which you can save typing effort
+-in specifying lines is to use `\-' and `+' as line numbers
+-by themselves.
+-.P1
+--
+-.P2
+-by itself is a command to move back up one line in the file.
+-In fact, you can string several minus signs together to move
+-back up that many lines:
+-.P1
+----
+-.P2
+-moves up three lines, as does `\-3'.
+-Thus
+-.P1
+--3,+3p
+-.P2
+-is also identical to the examples above.
+-.PP
+-Since `\-' is shorter than `\*.\-1',
+-constructions like
+-.P1
+--,\*.s/bad/good/
+-.P2
+-are useful. This changes `bad' to `good' on the previous line and
+-on the current line.
+-.PP
+-`+' and `\-' can be used in combination with searches using `/.../' and `?...?',
+-and with `$'.
+-The search
+-.P1
+-/thing/--
+-.P2
+-finds the line containing `thing', and positions you
+-two lines before it.
+-.SH
+-Repeated Searches
+-.PP
+-Suppose you ask for the search
+-.P1
+-/horrible thing/
+-.P2
+-and when the line is printed you discover that it
+-isn't the horrible thing that you wanted,
+-so it is necessary to repeat the search again.
+-You don't have to re-type the search,
+-for the construction
+-.P1
+-//
+-.P2
+-is a shorthand for `the previous thing that was searched for',
+-whatever it was.
+-This can be repeated as many times as necessary.
+-You can also go backwards:
+-.P1
+-??
+-.P2
+-searches for the same thing,
+-but in the reverse direction.
+-.PP
+-Not only can you repeat the search, but you can
+-use `//' as the left side of a substitute command,
+-to mean
+-`the most recent pattern'.
+-.P1
+-/horrible thing/
+-.ft I
+- .... ed prints line with `horrible thing' ...
+-.ft R
+-s//good/p
+-.P2
+-To go backwards and change a line, say
+-.P1
+-??s//good/
+-.P2
+-Of course, you can still use the `&' on the right hand side of a substitute to stand for
+-whatever got matched:
+-.P1
+-//s//&\*B&/p
+-.P2
+-finds the next occurrence of whatever you searched for last,
+-replaces it by two copies of itself,
+-then prints the line just to verify that it worked.
+-.SH
+-Default Line Numbers and the Value of Dot
+-.PP
+-One of the most effective ways to speed up your editing
+-is always to know what lines will be affected
+-by a command if you don't specify the lines it is to act on,
+-and on what line you will be positioned (i.e., the value of dot) when a command finishes.
+-If you can edit without specifying unnecessary
+-line numbers, you can save a lot of typing.
+-.PP
+-As the most obvious example, if you issue a search command
+-like
+-.P1
+-/thing/
+-.P2
+-you are left pointing at the next line that contains `thing'.
+-Then no address is required with commands like
+-.UL s
+-to make a substitution on that line,
+-or
+-.UL p
+-to print it,
+-or
+-.UL l
+-to list it,
+-or
+-.UL d
+-to delete it,
+-or
+-.UL a
+-to append text after it,
+-or
+-.UL c
+-to change it,
+-or
+-.UL i
+-to insert text before it.
+-.PP
+-What happens if there was no `thing'?
+-Then you are left right where you were _
+-dot is unchanged.
+-This is also true if you were sitting
+-on the only `thing' when you issued the command.
+-The same rules hold for searches that use
+-`?...?'; the only difference is the direction
+-in which you search.
+-.PP
+-The delete command
+-.UL d 
+-leaves dot pointing
+-at the line that followed the last deleted line.
+-When line `$' gets deleted,
+-however,
+-dot points at the
+-.ul
+-new
+-line `$'.
+-.PP
+-The line-changing commands
+-.UL a ,
+-.UL c
+-and
+-.UL i
+-by default all affect the current line _
+-if you give no line number with them,
+-.UL a
+-appends text after the current line,
+-.UL c
+-changes the current line,
+-and
+-.UL i
+-inserts text before the current line.
+-.PP
+-.UL a ,
+-.UL c ,
+-and
+-.UL i
+-behave identically in one respect _
+-when you stop appending, changing or inserting,
+-dot points at the last line entered.
+-This is exactly what you want for typing and editing on the fly.
+-For example, you can say
+-.P1
+-.ta 1.5i
+-a
+- ... text ...
+- ... botch ...        (minor error)
+-\&\*.
+-s/botch/correct/      (fix botched line)
+-a
+- ... more text ...
+-.P2
+-without specifying any line number for the substitute command or for
+-the second append command.
+-Or you can say
+-.P1 2
+-.ta 1.5i
+-a
+- ... text ...
+- ... horrible botch ...       (major error)
+-\&\*.
+-c     (replace entire line)
+- ... fixed up line ...
+-.P2
+-.PP
+-You should experiment to determine what happens if you add
+-.ul
+-no
+-lines with
+-.UL a ,
+-.UL c
+-or
+-.UL i .
+-.PP
+-The
+-.UL r
+-command will read a file into the text being edited,
+-either at the end if you give no address,
+-or after the specified line if you do.
+-In either case, dot points at the last line read in.
+-Remember that you can even say
+-.UL 0r
+-to read a file in at the beginning of the text.
+-(You can also say
+-.UL 0a
+-or
+-.UL 1i
+-to start adding text at the beginning.)
+-.PP
+-The
+-.UL w
+-command writes out the entire file.
+-If you precede the command by one line number,
+-that line is written,
+-while if you precede it by two line numbers,
+-that range of lines is written.
+-The 
+-.UL w
+-command does
+-.ul
+-not
+-change dot:
+-the current line remains the same,
+-regardless of what lines are written.
+-This is true even if you say something like
+-.P1
+-/^\*e\*.AB/,/^\*e\*.AE/w abstract
+-.P2
+-which involves a context search.
+-.PP
+-Since the
+-.UL w
+-command is so easy to use,
+-you should save what you are editing regularly
+-as you go along
+-just in case the system crashes, or in case you do something foolish,
+-like clobbering what you're editing.
+-.PP
+-The least intuitive behavior, in a sense, is that of the
+-.UL s
+-command.
+-The rule is simple _
+-you are left sitting on the last line that got changed.
+-If there were no changes, then dot is unchanged.
+-.PP
+-To illustrate,
+-suppose that there are three lines in the buffer, and you are sitting on
+-the middle one:
+-.P1
+-x1
+-x2
+-x3
+-.P2
+-Then the command
+-.P1
+-\&-,+s/x/y/p
+-.P2
+-prints the third line, which is the last one changed.
+-But if the three lines had been
+-.P1
+-x1
+-y2
+-y3
+-.P2
+-and the same command had been issued while
+-dot pointed
+-at the second line, then the result
+-would be to change and print only the first line,
+-and that is where dot would be set.
+-.SH
+-Semicolon `;'
+-.PP
+-Searches with `/.../' and `?...?' start
+-at the current line and move
+-forward or backward respectively
+-until they either find the pattern or get back to the current line.
+-Sometimes this is not what is wanted.
+-Suppose, for example, that the buffer contains lines like this:
+-.P1
+- \*.
+- \*.
+- \*.
+- ab
+- \*.
+- \*.
+- \*.
+- bc
+- \*. 
+- \*.
+-.P2
+-Starting at line 1, one would expect that the command
+-.P1
+-/a/,/b/p
+-.P2
+-prints all the lines from the `ab' to the `bc' inclusive.
+-Actually this is not what happens.
+-.ul
+-Both
+-searches
+-(for `a' and for `b')
+-start from the same point, and thus they both find the line
+-that contains `ab'.
+-The result is to print a single line.
+-Worse, if there had been a line with a `b' in it
+-before the `ab' line, then the print command
+-would be in error, since the second line number
+-would be less than the first, and it is illegal to
+-try to print lines in reverse order.
+-.PP
+-This is because the comma separator
+-for line numbers doesn't set dot as each address is processed;
+-each search starts from the same place.
+-In 
+-.UL ed ,
+-the semicolon `;' can be used just like comma,
+-with the single difference that use of a semicolon
+-forces dot to be set at that point
+-as the line numbers are being evaluated.
+-In effect, the semicolon `moves' dot.
+-Thus in our example above, the command
+-.P1
+-/a/;/b/p
+-.P2
+-prints the range of lines from `ab' to `bc',
+-because after the `a' is found, dot is set to that line,
+-and then `b' is searched for, starting beyond that line.
+-.PP
+-This property is most often useful in a very simple situation.
+-Suppose you want to find the 
+-.ul
+-second
+-occurrence of `thing'.
+-You could say
+-.P1
+-/thing/
+-//
+-.P2
+-but this prints the first occurrence as well as the second,
+-and is a nuisance when you know very well that it is only
+-the second one you're interested in.
+-The solution is to say
+-.P1
+-/thing/;//
+-.P2
+-This says to find the first occurrence of `thing', set dot to that line, then find the second
+-and print only that.
+-.PP
+-Closely related is searching for the second previous
+-occurrence of something, as in
+-.P1
+-?something?;??
+-.P2
+-Printing the third or fourth or ...
+-in either direction is left as an exercise.
+-.PP
+-Finally, bear in mind that if you want to find the first occurrence of
+-something in a file, starting at an arbitrary place within the file,
+-it is not sufficient to say
+-.P1
+-1;/thing/
+-.P2
+-because this fails if `thing' occurs on line 1.
+-But it is possible to say
+-.P1
+-0;/thing/
+-.P2
+-(one of the few places where 0 is a legal line number),
+-for this starts the search at line 1.
+-.SH
+-Interrupting the Editor
+-.PP
+-As a final note on what dot gets set to,
+-you should be aware that if you hit the interrupt or delete
+-or rubout or break key
+-while
+-.UL ed
+-is doing a command, things are put back together again and your state
+-is restored as much as possible to what it was before the command
+-began.
+-Naturally, some changes are irrevocable _
+-if you are reading or writing a file or making substitutions or deleting lines, these will be stopped
+-in some clean but unpredictable state in the middle
+-(which is why it is not usually wise to stop them).
+-Dot may or may not be changed.
+-.PP
+-Printing is more clear cut.
+-Dot is not changed until the printing is done.
+-Thus if you print until you see an interesting line,
+-then hit delete, you are
+-.ul
+-not
+-sitting on that line or even near it.
+-Dot is left where it was when the
+-.UL p
+-command was started.
+//GO.SYSIN DD ae3
+echo ae4
+sed 's/.//' >ae4 <<'//GO.SYSIN DD ae4'
+-.NH
+-GLOBAL COMMANDS
+-.PP
+-The global commands
+-.UL g
+-and
+-.UL v
+-are used to perform one or more editing commands on all lines that either
+-contain
+-.UL g ) (
+-or don't contain
+-.UL v ) (
+-a specified pattern.
+-.PP
+-As the simplest example, the command
+-.P1
+-g/UNIX/p
+-.P2
+-prints all lines that contain the word `UNIX'.
+-The pattern that goes between the slashes can be anything
+-that could be used in a line search or in a substitute command;
+-exactly the same rules and limitations apply.
+-.PP
+-As another example, then,
+-.P1
+-g/^\*e\*./p
+-.P2
+-prints all the formatting commands in a file (lines that begin with `\*.').
+-.PP
+-The
+-.UL v
+-command is identical to
+-.UL g ,
+-except that it operates on those line that do
+-.ul
+-not
+-contain an occurrence of the pattern.
+-(Don't look too hard for mnemonic significance to
+-the letter `v'.)
+-So
+-.P1
+-v/^\*e\*./p
+-.P2
+-prints all the lines that don't begin with `\*.' _
+-the actual text lines.
+-.PP
+-The command that follows
+-.UL g
+-or
+-.UL v
+-can be anything:
+-.P1
+-g/^\*e\*./d
+-.P2
+-deletes all lines that begin with `\*.',
+-and
+-.P1
+-g/^$/d
+-.P2
+-deletes all empty lines.
+-.PP
+-Probably the most useful command that can follow a global is the
+-substitute command, for this can be used to make a change
+-and print each affected line for verification.
+-For example, we could change the word `Unix' to `UNIX'
+-everywhere, and verify that 
+-it really worked, 
+-with
+-.P1
+-g/Unix/s//UNIX/gp
+-.P2
+-Notice that we used `//' in the substitute command to mean
+-`the previous pattern', in this case, `Unix'.
+-The 
+-.UL p
+-command is done on every line
+-that matches the pattern,
+-not just those on which a substitution took place.
+-.PP
+-The global command operates by making
+-two passes over the file.
+-On the first pass, all lines that match the pattern are marked.
+-On the second pass, each marked line in turn is examined,
+-dot is set to that line, and the command executed.
+-This means that it is possible for the command that follows a
+-.UL g
+-or
+-.UL v
+-to use addresses, set dot, and so on, quite freely.
+-.P1
+-g/^\*e\*.PP/+
+-.P2
+-prints the line that follows each `.PP' command (the signal for
+-a new paragraph in some formatting packages).
+-Remember that `+' means `one line past dot'.
+-And
+-.P1
+-g/topic/?^\*e\*.SH?1
+-.P2
+-searches for each line that contains `topic', scans backwards until it finds
+-a line that begins `.SH' (a section heading) and prints the line
+-that follows that,
+-thus showing the section headings under which `topic' is mentioned.
+-Finally,
+-.P1
+-g/^\*e\*.EQ/+,/^\*e\*.EN/-p
+-.P2
+-prints all the lines that lie between
+-lines beginning with `.EQ' and `.EN' formatting commands.
+-.PP
+-The
+-.UL g
+-and
+-.UL v
+-commands can also be
+-preceded by line numbers, in which case the lines searched
+-are only those in the range specified.
+-.SH
+-Multi-line Global Commands
+-.PP
+-It is possible to do more than one command under the control of a
+-global command, although the syntax for expressing the operation
+-is not especially natural or pleasant.
+-As an example,
+-suppose the task is to change `x' to `y' and `a' to `b' on all lines
+-that contain `thing'.
+-Then
+-.P1
+-g/thing/s/x/y/\*e
+-s/a/b/
+-.P2
+-is sufficient.
+-The `\*e' signals the
+-.UL g
+-command that the set of commands continues on the next line;
+-it terminates on the first line that does not end with `\*e'.
+-(As a minor blemish, you can't use a substitute command
+-to insert a newline within a 
+-.UL g
+-command.)
+-.PP
+-You should watch out for this problem:
+-the command
+-.P1
+-g/x/s//y/\*e
+-s/a/b/
+-.P2
+-does
+-.ul
+-not
+-work as you expect.
+-The remembered pattern is the last pattern that was actually
+-executed,
+-so sometimes it will be
+-`x' (as expected), and sometimes it will be `a'
+-(not expected).
+-You must spell it out, like this:
+-.P1
+-g/x/s/x/y/\*e
+-s/a/b/
+-.P2
+-.PP
+-It is also possible to execute 
+-.UL a ,
+-.UL c
+-and
+-.UL i
+-commands under a global command; as with other multi-line constructions,
+-all that is needed is to add a `\*e' at the end of each line except the last.
+-Thus to add a `.nf' and `.sp' command before each `.EQ' line, type
+-.P1
+-g/^\*e\*.EQ/i\*e
+-\&\*.nf\*e
+-\&\*.sp
+-.P2
+-There is no need for a final line containing a
+-`\*.' to terminate the 
+-.UL i
+-command,
+-unless there are further commands
+-being done under the global.
+-On the other hand, it does no harm to put it in either.
+//GO.SYSIN DD ae4
+echo ae5
+sed 's/.//' >ae5 <<'//GO.SYSIN DD ae5'
+-.NH
+-CUT AND PASTE WITH UNIX COMMANDS
+-.PP
+-One editing area in which non-programmers
+-seem not very confident
+-is in what might be called
+-`cut and paste' operations _
+-changing the name of a file,
+-making a copy of a file somewhere else,
+-moving a few lines from one place to another in a file,
+-inserting one file in the middle of another,
+-splitting a file into pieces,
+-and
+-splicing two or more files together.
+-.PP
+-Yet most of these operations are actually quite easy,
+-if you keep your wits about you
+-and go cautiously.
+-The next several sections talk about cut and paste.
+-We will begin with the
+-.UX
+-commands
+-for moving entire files around,
+-then discuss
+-.UL ed
+-commands
+-for operating on pieces of files.
+-.SH
+-Changing the Name of a File
+-.PP
+-You have a file named 
+-`memo'
+-and you want it to be called
+-`paper'
+-instead.
+-How is it done?
+-.PP
+-The
+-.UX
+-program that renames files
+-is called
+-.UL mv
+-(for `move');
+-it `moves' the file from one name to another, like this:
+-.P1
+-mv  memo  paper
+-.P2
+-That's all there is to it:
+-.UL mv
+-from the old name to the new name.
+-.P1
+-mv  oldname  newname
+-.P2
+-Warning: if there is already a file around with the new name,
+-its present contents will be
+-silently
+-clobbered
+-by the information from the other file.
+-The one exception is that you can't move a file
+-to itself _
+-.P1
+-mv  x  x
+-.P2
+-is illegal.
+-.SH
+-Making a Copy of a File
+-.PP
+-Sometimes what you want is a copy of a file _
+-an entirely fresh version.
+-This might be because you want to work on a file, and
+-yet save a copy in case something gets fouled up,
+-or just because you're paranoid.
+-.PP
+-In any case, the way to do it is with the
+-.UL cp
+-command.
+-.UL cp \& (
+-stands for `copy';
+-the
+-.UC UNIX
+-system
+-is big on short command names,
+-which are appreciated by heavy users,
+-but sometimes a strain for novices.)
+-Suppose you have a file called
+-`good'
+-and
+-you want to save a copy before you make some
+-dramatic editing changes.
+-Choose a name _
+-`savegood'
+-might be acceptable _ then type
+-.P1
+-cp  good  savegood
+-.P2
+-This copies
+-`good'
+-onto
+-`savegood',
+-and you now have two identical copies of the file
+-`good'.
+-(If
+-`savegood'
+-previously contained something,
+-it gets overwritten.)
+-.PP
+-Now if you decide at some time that you want to get
+-back to the original state of
+-`good',
+-you can say
+-.P1
+-mv  savegood  good
+-.P2
+-(if you're not interested in
+-`savegood'
+-any more), or
+-.P1
+-cp  savegood  good
+-.P2
+-if you still want to retain a safe copy.
+-.PP
+-In summary, 
+-.UL mv
+-just renames a file;
+-.UL cp
+-makes a duplicate copy.
+-Both of them clobber the `target' file
+-if it already exists, so you had better
+-be sure that's what you want to do
+-.ul
+-before
+-you do it.
+-.SH
+-Removing a File
+-.PP
+-If you decide you are really done with a file
+-forever, you can remove it
+-with the
+-.UL rm
+-command:
+-.P1
+-rm  savegood
+-.P2
+-throws away (irrevocably) the file called
+-`savegood'.
+-.SH
+-Putting Two or More Files Together
+-.PP
+-The next step is the familiar one of collecting two or more
+-files into one big one.
+-This will be needed, for example,
+-when the author of a paper
+-decides that several sections need to be combined
+-into one.
+-There are several ways to do it,
+-of which the cleanest, once you get used to it,
+-is a program called
+-.UL cat .
+-(Not 
+-.ul
+-all
+-.UC UNIX 
+-programs have two-letter names.)
+-.UL cat
+-is short for
+-`concatenate', which is exactly
+-what we want to do.
+-.PP
+-Suppose the job is to combine the files
+-`file1'
+-and
+-`file2'
+-into a single file called
+-`bigfile'.
+-If you say
+-.P1
+-cat  file
+-.P2
+-the contents of
+-`file'
+-will get printed on your terminal.
+-If you say
+-.P1
+-cat  file1  file2
+-.P2
+-the contents of
+-`file1'
+-and then the contents of
+-`file2'
+-will
+-.ul
+-both
+-be printed on your terminal,
+-in that order.
+-So
+-.UL cat
+-combines the files, all right,
+-but it's not much help to print them on the terminal _
+-we want them in 
+-`bigfile'.
+-.PP
+-Fortunately, there is a way.
+-You can tell
+-the system
+-that instead of printing on your terminal,
+-you want the same information put in a file. 
+-The way to do it is to add to the command line
+-the character
+-.UL >
+-and the name of the file
+-where you want the output to go.
+-Then you can say
+-.P1
+-cat  file1  file2  >bigfile
+-.P2
+-and the job is done.
+-(As with
+-.UL cp
+-and
+-.UL mv ,
+-you're putting something into
+-`bigfile',
+-and anything that was already there is destroyed.)
+-.PP
+-This ability to
+-`capture' the output of a program
+-is one of the most useful aspects of
+-the 
+-.UC UNIX
+-system.
+-Fortunately it's not limited to the
+-.UL cat 
+-program _
+-you can use it with 
+-.ul
+-any
+-program that prints on your terminal.
+-We'll see some more uses for it in a moment.
+-.PP
+-Naturally, you can combine several files,
+-not just two:
+-.P1
+-cat  file1  file2  file3  ...  >bigfile
+-.P2
+-collects a whole bunch.
+-.PP
+-Question:
+-is there any difference between
+-.P1
+-cp  good  savegood
+-.P2
+-and
+-.P1
+-cat  good  >savegood
+-.P2
+-Answer: for most purposes, no.
+-You might reasonably ask why there are two programs
+-in that case,
+-since
+-.UL cat
+-is obviously all you need.
+-The answer is that 
+-.UL cp
+-will do some other things as well,
+-which you can investigate for yourself
+-by reading the manual.
+-For now we'll stick to simple usages.
+-.SH
+-Adding Something to the End of a File
+-.PP
+-Sometimes you want to add one file to the end of another.
+-We have enough building blocks now that you can do it;
+-in fact before reading further it would be valuable
+-if you figured out how.
+-To be specific,
+-how would you use
+-.UL cp ,
+-.UL mv
+-and/or
+-.UL cat
+-to add the file
+-`good1'
+-to the end of the file
+-`good'?
+-.PP
+-You could try
+-.P1
+-cat  good  good1  >temp
+-mv  temp  good
+-.P2
+-which is probably most direct.
+-You should also understand why
+-.P1
+-cat  good  good1  >good
+-.P2
+-doesn't work.
+-(Don't practice with a good `good'!)
+-.PP
+-The easy way is to use a variant of
+-.UL > ,
+-called
+-.UL >> .
+-In fact,
+-.UL >> 
+-is identical to
+-.UL >
+-except that instead of clobbering the old file,
+-it simply tacks stuff on at the end.
+-Thus you could say
+-.P1
+-cat  good1  >>good
+-.P2
+-and
+-`good1'
+-is added to the end of
+-`good'.
+-(And if
+-`good'
+-didn't exist,
+-this makes a copy of
+-`good1'
+-called
+-`good'.)
+//GO.SYSIN DD ae5
+echo ae6
+sed 's/.//' >ae6 <<'//GO.SYSIN DD ae6'
+-.NH
+-CUT AND PASTE WITH THE EDITOR
+-.PP
+-Now we move on to manipulating pieces of files _
+-individual lines or groups of lines.
+-This is another area where new users seem
+-unsure of themselves.
+-.SH
+-Filenames
+-.PP
+-The first step is to ensure that you know the
+-.UL ed
+-commands for reading and writing files.
+-Of course you can't go very far without knowing
+-.UL r
+-and
+-.UL w .
+-Equally useful, but less well known, is the `edit' command
+-.UL e .
+-Within
+-.UL ed ,
+-the command
+-.P1
+-e  newfile
+-.P2
+-says `I want to edit a new file called
+-.ul
+-newfile,
+-without leaving the editor.'
+-The
+-.UL e
+-command discards whatever you're currently working on
+-and starts over on 
+-.ul
+-newfile.
+-It's exactly the same as if you had quit with the
+-.UL q
+-command, then re-entered
+-.UL ed
+-with a new file name,
+-except that if you have a pattern remembered, then a command
+-like
+-.UL //
+-will still work.
+-.PP
+-If you enter
+-.UL ed
+-with the command
+-.P1
+-ed  file
+-.P2
+-.UL ed 
+-remembers the name of the file,
+-and any subsequent
+-.UL e ,
+-.UL r
+-or
+-.UL w
+-commands that don't contain a filename
+-will refer to this remembered file.
+-Thus
+-.P1 2
+-.ta .5i .6i .7i
+-ed  file1
+- ... (editing) ...
+-w     (writes back in file1)
+-e  file2      (edit new file, without leaving editor)
+- ... (editing on file2) ...
+-w     (writes back on file2)
+-.P2
+-(and so on) does a series of edits on various files
+-without ever leaving
+-.UL ed
+-and without typing the name of any file more than once.
+-(As an aside, if you examine the sequence of commands here,
+-you can see why many
+-UNIX
+-systems use
+-.UL e
+-as a synonym
+-for
+-.UL ed .)
+-.PP
+-You can find out the remembered file name at any time
+-with the
+-.UL f
+-command;
+-just type
+-.UL f
+-without a file name.
+-You can also change the name of the remembered file name with
+-.UL f ;
+-a useful sequence is
+-.P1
+-ed  precious
+-f  junk
+- ... (editing) ...
+-.P2
+-which gets a copy of a precious file,
+-then uses
+-.UL f
+-to guarantee that a careless 
+-.UL w
+-command won't clobber the original.
+-.SH
+-Inserting One File into Another
+-.PP
+-Suppose you have a file called
+-`memo',
+-and you want the file called
+-`table'
+-to be inserted just after the reference to
+-Table 1.
+-That is, in
+-`memo'
+-somewhere is a line that says
+-.IP
+-Table 1 shows that ...
+-.LP
+-and the data contained in
+-`table'
+-has to go there,
+-probably so it will be formatted
+-properly by
+-.UL nroff
+-or
+-.UL troff .
+-Now what?
+-.PP
+-This one is easy.
+-Edit
+-`memo',
+-find
+-`Table 1',
+-and add the file
+-`table'
+-right there:
+-.P1
+-ed  memo
+-/Table 1/
+-.ft I
+-Table 1 shows that ... [response from ed]
+-.ft
+-\&\*.r  table
+-.P2
+-The critical line is the last one.
+-As we said earlier, the
+-.UL r
+-command reads a file;
+-here you asked for it to be read in right after
+-line dot.
+-An
+-.UL r
+-command without any address
+-adds lines at the end,
+-so it is the same as
+-.UL $r .
+-.SH
+-Writing out Part of a File
+-.PP
+-The other side of the coin is writing out part of
+-the document you're editing.
+-For example, maybe
+-you want to split out into a separate file
+-that table from the previous example,
+-so it can be formatted and tested separately.
+-Suppose that in the file being edited 
+-we have
+-.P1
+-\&\*.TS
+- ...[lots of stuff]
+-\&\*.TE
+-.P2
+-which is the way a table is set up for the
+-.UL tbl
+-program.
+-To isolate
+-the table
+-in a separate file called
+-`table',
+-first find the start of the table
+-(the `.TS' line), then write out the interesting part:
+-.P1
+-/^\*e\*.TS/
+-.ft I
+-\&\*.TS  [ed prints the line it found]
+-.ft R
+-\&\*.,/^\*e\*.TE/w table
+-.P2
+-and the job is done.
+-If you are confident, you can do it all at once with
+-.P1
+-/^\*e\*.TS/;/^\*e\*.TE/w table
+-.P2
+-.PP
+-The point is that the
+-.UL w
+-command can
+-write out a group of lines, instead of the whole file.
+-In fact, you can write out a single line if you like;
+-just give one line number instead of two.
+-For example, if you have just typed a horribly complicated line
+-and you know that it (or something like it) is going to be needed later,
+-then save it _ don't re-type it.
+-In the editor, say
+-.P1
+-a
+-\&...lots of stuff...
+-\&...horrible line...
+-\&\*.
+-\&\*.w  temp
+-a
+-\&\*.\*.\*.more stuff\*.\*.\*.
+-\&\*.
+-\&\*.r temp
+-a
+-\&\*.\*.\*.more stuff\*.\*.\*.
+-\&\*.
+-.P2
+-This last example is worth studying, to be sure you appreciate
+-what's going on.
+-.SH
+-Moving Lines Around
+-.PP
+-Suppose you want to 
+-move a paragraph from its present position in a paper
+-to the end.
+-How would you do it?
+-As a concrete example, suppose each paragraph in the paper
+-begins with the formatting command
+-`.PP'.
+-Think about it and write down the details before reading on.
+-.PP
+-The brute force way
+-(not necessarily bad)
+-is to write the paragraph onto a temporary file,
+-delete it from its current position,
+-then read in the temporary file at the end.
+-Assuming that you are sitting on the 
+-`.PP' command that begins
+-the paragraph, this is the sequence of commands:
+-.P1
+-\&\*.,/^\*e\*.PP/-w temp
+-\&\*.,//-d
+-$r temp
+-.P2
+-That is, from where you are now
+-(`\*.')
+-until one line before the next `\*.PP'
+-(`/^\*e\*.PP/\-')
+-write onto
+-`temp'.
+-Then delete the same lines.
+-Finally, read
+-`temp'
+-at the end.
+-.PP
+-As we said, that's the brute force way.
+-The easier way (often)
+-is to use the
+-.ul
+-move
+-command
+-.UL m
+-that 
+-.UL ed
+-provides _
+-it lets you do the whole set of operations
+-at one crack,
+-without any temporary file.
+-.PP
+-The 
+-.UL m
+-command
+-is like many other
+-.UL ed
+-commands in that it takes up to two line numbers in front
+-that tell what lines are to be affected.
+-It is also
+-.ul
+-followed
+-by a line number that tells where the lines are to go.
+-Thus
+-.P1
+-line1, line2 m line3
+-.P2
+-says to move all the lines between
+-`line1'
+-and
+-`line2'
+-after
+-`line3'.
+-Naturally, any of
+-`line1'
+-etc., can be patterns between slashes,
+-$
+-signs, or other ways to specify lines.
+-.PP
+-Suppose again that you're sitting at the first line of the
+-paragraph.
+-Then you can say
+-.P1
+-\&\*.,/^\*e\*.PP/-m$
+-.P2
+-That's all.
+-.PP
+-As another example of a frequent operation,
+-you can reverse the order of two adjacent lines
+-by moving the first one
+-to after the second.
+-Suppose that you are positioned at the first.
+-Then
+-.P1
+-m+
+-.P2
+-does it.
+-It says to move line dot to after one line after line dot.
+-If you are positioned on the second line,
+-.P1
+-m--
+-.P2
+-does the interchange.
+-.PP
+-As you can see, the
+-.UL m
+-command is more succinct and direct than
+-writing, deleting and re-reading.
+-When is brute force better anyway?
+-This is a matter of personal taste _
+-do what you have most confidence in.
+-The main difficulty with the
+-.UL m
+-command
+-is that if you use patterns to specify both the lines
+-you are moving and the target,
+-you have to take care that you specify them properly,
+-or you may well not move the lines you thought you did.
+-The result of a botched
+-.UL m
+-command can be a ghastly mess.
+-Doing the job a step at a time
+-makes it easier for you to verify at each step
+-that you accomplished what you wanted to.
+-It's also a good idea to issue a 
+-.UL w
+-command
+-before doing anything complicated;
+-then if you goof, it's easy to back up
+-to where you were.
+-.SH
+-Marks
+-.PP
+-.UL ed
+-provides a facility for marking a line
+-with a particular name so you can later reference it
+-by name
+-regardless of its actual line number.
+-This can be handy for moving lines,
+-and for keeping track of them as they move.
+-The
+-.ul
+-mark
+-command is
+-.UL k ;
+-the command
+-.P1
+-kx
+-.P2
+-marks the current line with the name `x'.
+-If a line number precedes the
+-.UL k ,
+-that line is marked.
+-(The mark name must be a single lower case letter.)
+-Now you can refer to the marked line with the address
+-.P1
+-\(fmx
+-.P2
+-.PP
+-Marks are most useful for moving things around.
+-Find the first line of the block to be moved, and mark it
+-with
+-.ul
+-\(fma.
+-Then find the last line and mark it with
+-.ul
+-\(fmb.
+-Now position yourself at the place where the stuff is to go
+-and say
+-.P1
+-\(fma,\(fmbm\*.
+-.P2
+-.PP
+-Bear in mind that only one line can have a particular
+-mark name associated with it
+-at any given time.
+-.SH
+-Copying Lines
+-.PP
+-We mentioned earlier the idea of saving a line
+-that was hard to type or used often,
+-so as to cut down on typing time.
+-Of course this could be more than one line;
+-then the saving is presumably even greater.
+-.PP
+-.UL ed
+-provides another command,
+-called
+-.UL t
+-(for `transfer')
+-for making a copy of a group of one or more lines
+-at any point.
+-This is often easier than writing and reading.
+-.PP
+-The 
+-.UL t
+-command is identical to the
+-.UL m
+-command, except that instead of moving lines
+-it simply duplicates them at the place you named.
+-Thus
+-.P1
+-1,$t$
+-.P2
+-duplicates the entire contents that you are editing.
+-A more common use for
+-.UL t
+-is for creating a series of lines that differ only slightly.
+-For example, you can say
+-.P1
+-.ta 1i
+-a
+-\&..........  x  ......... (long line)
+-\&\*.
+-t\*.  (make a copy)
+-s/x/y/        (change it a bit)
+-t\*.  (make third copy)
+-s/y/z/        (change it a bit)
+-.P2
+-and so on.
+-.SH
+-The Temporary Escape `!'
+-.PP
+-Sometimes it is convenient to be able
+-to temporarily escape from the editor to do
+-some other
+-.UX
+-command,
+-perhaps one of the file copy or move commands
+-discussed in section 5,
+-without leaving the editor.
+-The `escape' command 
+-.UL !
+-provides a way to do this.
+-.PP
+-If you say
+-.P1
+-!any UNIX command
+-.P2
+-your current editing state is suspended,
+-and the
+-.UX
+-command you asked for is executed.
+-When the command finishes,
+-.UL ed
+-will signal you by printing another
+-.UL ! ;
+-at that point you can resume editing.
+-.PP
+-You can really do
+-.ul
+-any
+-.UX
+-command, including another 
+-.UL ed .
+-(This is quite common, in fact.)
+-In this case, you can even do another
+-.UL ! .
+//GO.SYSIN DD ae6
+echo ae7
+sed 's/.//' >ae7 <<'//GO.SYSIN DD ae7'
+-.NH
+-SUPPORTING TOOLS
+-.PP
+-There are several tools and techniques that go along with the
+-editor, all of which are relatively easy once you
+-know how
+-.UL ed
+-works,
+-because they are all based on the editor.
+-In this section we will give some fairly cursory examples
+-of these tools,
+-more to indicate their existence than to provide
+-a complete tutorial.
+-More information on each can be found in
+-[3].
+-.SH
+-Grep
+-.PP
+-Sometimes you want to find all occurrences of some word or pattern in
+-a set of files, to edit them
+-or perhaps just to verify their presence or absence.
+-It may be possible to edit each file separately and look
+-for the pattern of interest, but if there are many files
+-this can get very tedious,
+-and if the files are really big,
+-it may be impossible because of limits in 
+-.UL ed .
+-.PP
+-The program
+-.UL grep
+-was invented to get around these limitations.
+-The search patterns that we have described in the paper are often
+-called `regular expressions', and
+-`grep' stands for
+-.P1
+-g/re/p
+-.P2
+-That describes exactly what
+-.UL grep
+-does _
+-it prints every line in a set of files that contains a
+-particular pattern.
+-Thus
+-.P1
+-grep  \(fmthing\(fm  file1  file2  file3  ...
+-.P2
+-finds `thing' wherever it occurs in any of the files
+-`file1',
+-`file2',
+-etc.
+-.UL grep
+-also indicates the file in which the line was found,
+-so you can later edit it if you like.
+-.PP
+-The pattern represented by `thing' can be any
+-pattern you can use in the editor,
+-since
+-.UL grep
+-and
+-.UL ed
+-use exactly the same mechanism for
+-pattern searching.
+-It is wisest always to enclose the pattern in the
+-single quotes \(fm...\(fm if it contains any non-alphabetic
+-characters, since many such characters also mean something
+-special to the
+-.UX
+-command interpreter
+-(the `shell').
+-If you don't quote them, the command interpreter will
+-try to interpret them before
+-.UL grep
+-gets a chance.
+-.PP
+-There is also a way to find lines that
+-.ul
+-don't 
+-contain a pattern:
+-.P1
+-grep  -v  \(fmthing\(fm  file1  file2  ...
+-.P2
+-finds all lines that
+-don't contains `thing'.
+-The
+-.UL \-v
+-must occur in the position shown.
+-Given
+-.UL grep
+-and
+-.UL grep\ \-v ,
+-it is possible to do things like selecting all lines that
+-contain some combination of patterns.
+-For example, to get all lines that contain `x' but not `y':
+-.P1
+-grep  x  file...  |  grep  -v  y
+-.P2
+-(The notation | is a `pipe',
+-which causes the output of the first command to be used as
+-input to the second command; see [2].)
+-.SH
+-Editing Scripts
+-.PP
+-If a fairly complicated set of editing operations 
+-is to be done on a whole set of files,
+-the easiest thing to do is to make up a `script',
+-i.e., a file that contains the operations you want to perform,
+-then apply this script to each file in turn.
+-.PP
+-For example, suppose you want to change every
+-`Unix' to `UNIX' and every `Gcos' to `GCOS' in a large number of files.
+-Then put into the file `script' the lines
+-.P1
+-g/Unix/s//UNIX/g
+-g/Gcos/s//GCOS/g
+-w
+-q
+-.P2
+-Now you can say
+-.P1
+-ed file1 <script
+-ed file2 <script
+-\&...
+-.P2
+-This causes
+-.UL ed
+-to take its commands from the prepared script.
+-Notice that the whole job has to be planned in advance.
+-.PP
+-And of course by using the
+-.UX
+-command interpreter, you can
+-cycle through a set of files
+-automatically, with varying degrees of ease.
+-.SH
+-Sed
+-.PP
+-.UL sed
+-(`stream editor')
+-is a version of the editor with restricted capabilities
+-but which is capable of processing unlimited amounts of input.
+-Basically
+-.UL sed
+-copies its input to its output, applying one or more
+-editing commands to each line of input.
+-.PP
+-As an example, suppose that we want to do the `Unix' to `UNIX'
+-part of the
+-example given above,
+-but without rewriting the files.
+-Then the command
+-.P1
+-sed  \(fms/Unix/UNIX/g\(fm  file1  file2  ...
+-.P2
+-applies the command
+-`s/Unix/UNIX/g'
+-to all lines from `file1', `file2', etc.,
+-and copies all lines to the output.
+-The advantage of using
+-.UL sed
+-in such a case is that it can be used
+-with input too large for
+-.UL ed
+-to handle.
+-All the output can be collected in one place,
+-either in a file or perhaps piped into another program.
+-.PP
+-If the editing transformation is so complicated
+-that
+-more than one editing command is needed,
+-commands can be supplied from a file,
+-or on the command line,
+-with a slightly more complex syntax.
+-To take commands from a file, for example,
+-.P1
+-sed  -f  cmdfile  input-files...
+-.P2
+-.PP
+-.UL sed
+-has further capabilities, including conditional testing
+-and branching, which we cannot go into here.
+//GO.SYSIN DD ae7
+echo ae9
+sed 's/.//' >ae9 <<'//GO.SYSIN DD ae9'
+-.SH
+-Acknowledgement
+-.PP
+-I am grateful to Ted Dolotta
+-for his careful reading and valuable suggestions.
+-.SH
+-References
+-.IP [1]
+-Brian W. Kernighan,
+-.ul
+-A Tutorial Introduction to the UNIX Text Editor,
+-Bell Laboratories internal memorandum.
+-.IP [2]
+-Brian W. Kernighan,
+-.ul
+-UNIX For Beginners,
+-Bell Laboratories internal memorandum.
+-.IP [3]
+-Ken L. Thompson and Dennis M. Ritchie,
+-.ul
+-The UNIX Programmer's Manual.
+-Bell Laboratories.
+//GO.SYSIN DD ae9
diff --git a/doc/7thEdMan/vol2/assembler b/doc/7thEdMan/vol2/assembler
new file mode 100644 (file)
index 0000000..d9840ee
--- /dev/null
@@ -0,0 +1,1009 @@
+.\"tbl ... ^ [tn]roff -ms
+.hc %
+.TL
+Assembler Reference Manual
+.AU
+Dennis M. Ritchie
+.AI
+.MH
+.SH
+0.  Introduction
+.PP
+This document describes the usage and input syntax
+of the \s8UNIX PDP\s10-11 assembler \fIas\fP.
+The details
+of the \s8PDP\s10-11 are not described.
+.PP
+The input syntax of the \s8UNIX\s10 assembler is generally
+similar to that of the \s8DEC\s10 assembler \s8PAL\s10-11\s8R\s10, although
+its internal workings and output format
+are unrelated.
+It may be useful to read the publication \s8DEC\s10-11-\s8ASDB\s10-\s8D\s10,
+which describes \s8PAL\s10-11\s8R\s10, although naturally
+one must use care in assuming that its rules apply
+to \fIas\fP.
+.PP
+\fIAs\fP is a rather ordinary assembler without
+macro capabilities.
+It produces an output file that contains
+relocation information and a complete
+symbol table;
+thus the output is acceptable to the \s8UNIX\s10 link-editor
+\fIld\fP, which
+may be used to combine the outputs of several
+assembler runs and to obtain
+object programs from libraries.
+The output format has been designed
+so that if a program contains no unresolved
+ref%er%ences to external symbols, it is executable
+without further processing.
+.SH
+1.  Usage
+.PP
+\fIas\fP is used as follows:
+.DS
+as \fR[\fB \-u \fR] [ \fB\-o \fIoutput\fR ] \fIfile\s6\d1\u\s10 .\|.\|.
+.DE
+If the optional ``\-u'' argument is
+given, all undefined symbols
+in the current assembly will be made undefined-external.
+See the \fB.globl\fR directive below.
+.PP
+The other arguments name files
+which are concatenated and assembled.
+Thus programs may be written in several
+pieces and assembled together.
+.PP
+The output of the assembler is by default placed on
+the file \fIa.out\fR in the current directory;
+the ``\-o'' flag causes the output to be placed on the named file.
+If there were no unresolved
+external ref%er%ences, and no errors detected,
+the output file is marked executable; otherwise, if it is
+produced at all, it is made non-executable.
+.SH
+2.  Lexical conventions
+.PP
+Assembler tokens include identifiers (alternatively, ``symbols'' or ``names''),
+temporary symbols,
+constants, and operators.
+.SH
+2.1  Identifiers
+.PP
+An identifier consists of a sequence of alphanumeric characters (including
+period ``\|\fB.\fR\|'', underscore ``\(ul'',
+and tilde ``~''
+as alphanumeric)
+of which the first may not
+be numeric.
+Only the first eight characters are significant.
+When a name begins with a tilde, the tilde is discarded
+and that occurrence of the identifier generates
+a unique entry in the symbol table which can match
+no other occurrence of the identifier.
+This feature is used
+by the C compiler to place names of local variables
+in the output symbol table
+without having to worry
+about 
+making them unique.
+.SH
+2.2  Temporary symbols
+.PP
+A temporary symbol consists of a digit followed by ``f\|'' or
+``b''.
+Temporary symbols are discussed fully in \(sc5.1.
+.SH
+2.3  Constants
+.PP
+An octal constant consists of a sequence of digits; ``8'' and
+``9'' are taken to have octal value 10 and 11.
+The constant
+is truncated to 16 bits and interpreted in two's complement
+notation.
+.PP
+A decimal constant consists of a sequence of digits terminated
+by a decimal point ``\fB.\fR''.  The magnitude of the constant should be
+representable in 15 bits; i.e., be less than 32,768.
+.PP
+A single-character constant consists of a single quote ``\|\(fm\|''
+followed by an \s8ASCII\s10 character not a new-line.
+Certain dual-character escape sequences
+are acceptable in place of the \s8ASCII\s10 character to represent
+new-line and other non-graphics (see \fIString state%ments\fP, \(sc5.5).
+The constant's value has the code for the
+given character in the least significant
+byte of the word and is null-padded on the left.
+.PP
+A double-character constant consists of a double
+quote ``\|"\|'' followed by a pair of \s8ASCII\s10 characters
+not including new-line.
+Certain dual-character escape sequences are acceptable
+in place of either of the \s8ASCII\s10 characters
+to represent new-line and other non-graphics
+(see \fIString state%ments\fR, \(sc5.5).
+The constant's value has the code for the first
+given character in the least significant
+byte and that for the second character in
+the most significant byte.
+.SH
+2.4  Operators
+.PP
+There are several single- and double-character
+operators; see \(sc6.
+.SH
+2.5  Blanks
+.PP
+Blank and tab characters
+may be interspersed freely between tokens, but may
+not be used within tokens (except character constants).
+A blank or tab is required to separate adjacent
+identifiers or constants not otherwise separated.
+.SH
+2.6  Comments
+.PP
+The character ``\|/\|'' introduces a comment, which extends
+through the end of the line on which it appears.
+Comments are ignored by the assembler.
+.SH
+3.  Segments
+.PP
+Assembled code and data
+fall into three segments: the text segment, the data segment, and the bss segment.
+The text segment is the one in which the assembler begins,
+and it is the one into which instructions are typically placed.
+The \s8UNIX\s10 system will, if desired,
+enforce the purity of the text segment of programs by
+trapping write operations
+into it.
+Object programs produced by the assembler must be processed
+by the link-editor \fIld\fR
+(using its ``\-n'' flag)
+if the text segment is to be write-protected.
+A single copy of the text
+segment is shared among all processes
+executing such a program.
+.PP
+The data segment is available for placing
+data or instructions which
+will be modified during execution.
+Anything which may go in the text segment may be put
+into the data segment.
+In programs with write-protected, sharable text segments,
+data segment contains the initialized but variable
+parts of a program.
+If the text segment is not pure, the data segment begins
+immediately after the
+text segment;
+if the text segment is pure, the data segment begins at the lowest
+8K byte boundary after the text segment.
+.PP
+The bss segment may not contain any explicitly initialized code
+or data.
+The length of the bss segment (like that of text or data)
+is determined by the high-water mark of the location counter
+within it.
+The bss segment is actually an extension of
+the data segment and begins immediately after it.
+At the start of execution of a program, the bss segment
+is set to 0.
+Typically the bss segment is set up
+by state%ments exemplified by
+.DS
+lab\fB: .\fR = \fB.\fR+10
+.DE
+The advantage in using the bss segment
+for storage that starts off empty is that the initialization
+information need not be stored in the output file.
+See also \fILocation counter\fP and \fIAssignment state%ments\fP
+below.
+.SH
+4.  The location counter
+.PP
+One special symbol, ``\|\fB.\fP\|'', is the location counter.
+Its value at any time is the offset
+within the appropriate segment of the start of
+the state%ment in which it appears.
+The location counter may be assigned to,
+with the restriction that the
+current segment may not change;
+furthermore,
+the value of ``\|\fB.\fP\|'' may not decrease.
+If the effect of the assignment is to increase the value of ``\|\fB.\fP\|'',
+the required number of null bytes are generated
+(but see \fISegments\fP above).
+.SH
+5.  Statements
+.PP
+A source program is composed of a sequence of
+\fIstate%ments\fP.
+Statements are separated either by new-lines
+or by semicolons.
+There are five kinds of state%ments: null state%ments,
+expression state%ments, assignment state%ments,
+string state%ments,
+and keyword state%ments.
+.PP
+Any kind of state%ment may be preceded by
+one or more labels.
+.SH
+5.1  Labels
+.PP
+There are two kinds of label:
+name labels and numeric labels.
+A name label consists of a name followed
+by a colon (\|:\|).
+The effect of a name label is to assign the current
+value and type of the location counter ``\|\fB.\fP\|''
+to the name.
+An error is indicated in pass 1 if the
+name is already defined;
+an error is indicated in pass 2 if the ``\|\fB.\fP\|''
+value assigned changes the definition
+of the label.
+.PP
+A numeric label consists of a digit \fI0\fR to \fI9\fR followed by a colon (\|:\|).
+Such a label serves to define temporary
+symbols of the form ``\fIn\fR\|b'' and ``\fIn\fR\|f\|'', where \fIn\fR is
+the digit of the label.
+As in the case of name labels, a numeric label assigns
+the current value and type of ``\|\fB.\fP\|'' to the temporary
+symbol.
+However, several numeric labels with the same
+digit may be used within the same assembly.
+Ref%er%ences of the form ``\fIn\fR\|f\|'' refer to the first
+numeric label ``\fIn\|\fR:'' \fIf\fR\|orward from the ref%er%ence;
+``\fIn\|\fRb'' symbols refer to the first ``\fIn\|\fR\|:'' label
+\fIb\|\fRackward from the ref%er%ence.
+This sort of temporary label was introduced by Knuth
+[\fIThe Art of Computer Programming, Vol I: Fundamental Algorithms\|\fR].
+Such labels tend to conserve both the symbol table
+space of the assembler and the
+inventive powers of the programmer.
+.SH
+5.2  Null state%ments
+.PP
+A null state%ment is an empty state%ment (which may, however,
+have labels).
+A null state%ment is ignored by the assembler.
+Common examples of null state%ments are empty
+lines or lines containing only a label.
+.SH
+5.3  Expression state%ments
+.PP
+An expression state%ment consists of an arithmetic
+expression not beginning with
+a keyword.
+The assembler computes its (16-bit) value
+and places it in the output stream, together with the
+appropriate relocation bits.
+.SH
+5.4  Assignment state%ments
+.PP
+An assignment state%ment consists of an identifier, an equals sign (\|=\|),
+and an expression.
+The value and type of the expression are assigned to
+the identifier.
+It is not required that the type or value be
+the same in pass 2 as in pass 1, nor is it an
+error to redefine any symbol by assignment.
+.PP
+Any external attribute of the expression is lost across
+an assignment.
+This means that it is not possible to declare a global
+symbol by assigning to it, and that it is impossible
+to define a symbol to be offset from a non-locally
+defined global symbol.
+.PP
+As mentioned,
+it is permissible to assign to the
+location counter ``\|\fB.\fP\|''.
+It is required, however, that the type of
+the expression assigned be of the same type
+as ``\|\fB.\fP\|'',
+and it is forbidden to decrease the value
+of ``\fB\|.\|\fR''.
+In practice, the most common assignment to ``\|\fB.\fP\|'' has the form
+``.\|=\|.\|+\|\fIn\fR''
+for some number \fIn;\fR this has the effect of generating
+\fIn\fR null bytes.
+.SH
+5.5  String state%ments
+.PP
+A string state%ment generates a sequence of bytes containing \s8ASCII\s10 characters.
+A string state%ment consists of a left string quote ``<''
+followed by a sequence of \s8ASCII\s10 characters not including newline,
+followed by a right string quote ``>''.
+Any of the \s8ASCII\s10 characters may
+be replaced by a two-character escape sequence to represent
+certain non-graphic characters, as follows:
+.DS C
+.TS
+l l l.
+\en    \s8NL\s10       (012)
+\es    \s8SP\s10       (040)
+\et    \s8HT\s10       (011)
+\ee    \s8EOT\s10      (004)
+\e0    \s8NUL\s10      (000)
+\er    \s8CR\s10       (015)
+\ea    \s8ACK\s10      (006)
+\ep    \s8PFX\s10      (033)
+\e\e   \e
+\e>    >
+.TE
+.DE
+The last two are included so that the escape character
+and the right string quote may be represented.
+The same escape sequences
+may also be used within single- and double-character
+constants (see \(sc2.3 above).
+.SH
+5.6  Keyword state%ments
+.PP
+Keyword state%ments are numerically the most common type,
+since most machine instructions are of this
+sort.
+A keyword state%ment begins with one of the many predefined
+keywords of the assembler;
+the syntax of the remainder depends
+on the keyword.
+All the keywords are listed below with the syntax they require.
+.SH
+6.  Expressions
+.PP
+An expression is a sequence of symbols representing a value.
+Its constituents are identifiers, constants, temporary symbols,
+operators, and brackets.
+Each expression has a type.
+.PP
+All operators in expressions are fundamentally binary in
+nature; if an operand is missing on the left, a 0
+of absolute type is assumed.
+Arithmetic
+is two's complement and has 16 bits of precision.
+All operators have equal precedence, and expressions
+are evaluated
+strictly left to right except for the effect
+of brackets.
+.SH
+6.1  Expression operators
+.PP
+The operators are:
+.IP (blank) 8
+when there is no operand between
+operands, the effect is
+exactly the same as if a ``+'' had appeared.
+.pg
+.ti 0
+.IP + 8
+addition
+.IP \- 8
+subtraction
+.IP * 8
+multiplication
+.IP \e\(sl 8
+division (note that plain ``\|/\|'' starts a comment)
+.IP 8 & 8
+bitwise \fBand\fR
+.IP \(bv 8
+bitwise \fBor\fR
+.IP \e> 8
+logical right shift
+.IP \\e< 8
+logical left shift
+.hc
+.IP % 8
+modulo
+.IP ! 8
+.hc %
+\fIa\fR\|!\|\fIb\fR is \fIa \fBor \fR(\|\fBnot \fIb\fR\|);
+i.e., the \fBor\fR of the first operand and
+the one's complement of the second; most common use is
+as a unary.
+.IP ^ 8
+result has the value of first operand and the type of the second;
+most often used to define new machine instructions
+with syntax identical to existing instructions.
+.PP
+Expressions may be grouped by use of square brackets ``\|[\|\|]\|''.
+(Round parentheses are reserved for address modes.)
+.SH
+6.2  Types
+.PP
+The assembler deals with a number of types
+of expressions.  Most types
+are attached to keywords and used to select the
+routine which treats that keyword.  The types likely
+to be met explicitly are:
+.IP undefined 8
+.br
+Upon first encounter, each symbol is undefined.
+It may become undefined if it is assigned an undefined expression.
+It is an error to attempt to assemble an undefined
+expression in pass 2; in pass 1, it is not (except that
+certain keywords require operands which are not undefined).
+.IP "undefined external" 8
+.br
+A symbol which is declared \fB.globl\fR but not defined
+in the current assembly is an undefined
+external.
+If such a symbol is declared, the link editor \fIld\fR
+must be used to load the assembler's output with
+another routine that defines the undefined ref%er%ence.
+.IP absolute 8
+An absolute symbol is defined ultimately from a constant.
+Its value is unaffected by any possible future applications
+of the link-editor to the output file.
+.IP text 8
+The value of a text symbol is measured
+with respect to the beginning of the text segment of the program.
+If the assembler output is link-edited, its text
+symbols may change in value
+since the program need
+not be the first in the link editor's output.
+Most text symbols are defined by appearing as labels.
+At the start of an assembly, the value of ``\|\fB.\fP\|'' is text 0.
+.IP data 8
+The value of a data symbol is measured
+with respect to the origin of the data segment of a program.
+Like text symbols, the value of a data symbol may change
+during a subsequent link-editor run since previously
+loaded programs may have data segments.
+After the first \fB.data\fR state%ment, the value of ``\|\fB.\fP\|''
+is data 0.
+.IP bss 8
+The value of a bss symbol is measured from
+the beginning of the bss segment of a program.
+Like text and data symbols, the value of a bss symbol
+may change during a subsequent link-editor
+run, since previously loaded programs may have bss segments.
+After the first \fB.bss\fR state%ment, the value of ``\|\fB.\fP\|'' is bss 0.
+.IP "external absolute, text, data, or bss" 8
+.br
+symbols declared \fB.globl\fR
+but defined within an assembly as absolute, text, data, or bss
+symbols may be used exactly as if they were not
+declared \fB.globl\fR; however, their value and type are available
+to the link editor so that the program may be loaded with others
+that ref%er%ence these symbols.
+.IP register 8
+.br
+The symbols
+.DS
+\fBr0\fR  .\|.\|. \fBr5
+fr0\fR  .\|.\|. \fBfr5
+sp
+pc
+.DE
+are predefined
+as register symbols.
+Either they or symbols defined from them must
+be used to refer to the six general-purpose,
+six floating-point, and
+the 2 special-purpose machine registers.
+The behavior of the floating register names
+is identical to that of the corresponding
+general register names; the former
+are provided as a mnemonic aid.
+.IP "other types" 8
+.br
+Each keyword known to the assembler has a type which
+is used to select the routine which processes
+the associated keyword state%ment.
+The behavior of such symbols
+when not used as keywords is the same as if they were absolute.
+.SH
+6.3  Type propagation in expressions
+.PP
+When operands are combined by expression operators,
+the result has a type which depends on the types
+of the operands and on the operator.
+The rules involved are complex to state but
+were intended to be sensible and predictable.
+For purposes of expression evaluation the
+important types are
+.DS
+undefined
+absolute
+text
+data
+bss
+undefined external
+other
+.DE
+The combination rules are then:
+If one of the operands
+is undefined, the result is undefined.
+If both operands are absolute, the result is absolute.
+If an absolute is combined with one of the ``other types''
+mentioned above,
+or with a register expression, the result
+has the register or other type.
+As a consequence,
+one can refer to r3 as ``r0+3''.
+If two operands of ``other type'' are combined,
+the result has the
+numerically larger type
+An ``other type'' combined with an explicitly
+discussed type other than absolute
+acts like an absolute.
+.PP
+Further rules applying to particular operators
+are:
+.IP +
+If one operand is text-, data-, or bss-segment
+relocatable, or is an undefined external,
+the result has the postulated type and the other operand
+must be absolute.
+.IP \-
+If the first operand is a relocatable
+text-, data-, or bss-segment symbol, the second operand
+may be absolute (in which case the result has the
+type of the first operand);
+or the second operand may have the same type
+as the first (in which case the result is absolute).
+If the first operand is external undefined, the second must be
+absolute.
+All other combinations are illegal.
+.IP ^
+This operator follows no other rule than
+that the result has the value
+of the first operand and the type of the second.
+.PP
+.IP others
+.br
+It is illegal to apply these operators to any but absolute
+symbols.
+.SH
+7.  Pseudo-operations
+.PP
+The keywords listed below introduce
+state%ments that generate data in unusual forms or
+influence the later operations of the assembler.
+The metanotation
+.DS
+[ stuff ] .\|.\|.
+.DE
+means that 0 or more instances of the given stuff may appear.
+Also, boldface tokens are literals, italic words
+are substitutable.
+.SH
+7.1  \fB.byte  \fIexpression  \fR[  \fB, \fIexpression \fR]  .\|.\|.
+.PP
+The \fIexpression\fRs in the comma-separated
+list are truncated to 8 bits and assembled in successive
+bytes.
+The expressions must be absolute.
+This state%ment and the string state%ment above are the only ones
+that assemble data one byte at at time.
+.SH
+7.2  \fB.even\fR
+.PP
+If the location counter ``\|\fB.\fP\|'' is odd, it is advanced by one
+so the next state%ment will be assembled
+at a word boundary.
+.SH
+7.3  \fB.if  \fIexpression\fR
+.PP
+The \fIexpression\fR must be absolute and defined in pass 1.
+If its value is nonzero, the \fB.if\fR is ignored; if zero,
+the state%ments between the \fB.if\fR and the matching \fB.endif\fR
+(below) are ignored.
+\&\fB.if\fR may be nested.
+The effect of \fB.if\fR cannot extend beyond
+the end of the input file in which it appears.
+(The state%ments are not totally ignored, in
+the following
+sense: \fB.if\fRs and \fB.endif\fRs are scanned for, and
+moreover all names
+are entered in the symbol table.
+Thus names occurring only inside
+an \fB.if\fR
+will show up as undefined if the symbol
+table is listed.)
+.SH
+7.4  \fB.endif\fR
+.PP
+This state%ment marks the end of a conditionally-assembled section of code.
+See \fB.if\fR above.
+.SH
+7.5  \fB.globl  \fIname  \fR[  \fB,\fI  name  \fR]  .\|.\|.
+.PP
+This state%ment makes the \fInames\fR external.
+If they are otherwise defined (by assignment or
+appearance as a label)
+they act within the assembly exactly as if
+the \fB.globl\fR state%ment were not given; however,
+the link editor \fIld\fR may be used
+to combine this routine with other routines that refer
+these symbols.
+.PP
+Conversely, if the given symbols are not defined
+within the current assembly, the link editor
+can combine the output of this assembly
+with that of others which define the symbols.
+As discussed in \(sc1, it is possible to force
+the assembler to make all otherwise
+undefined symbols external.
+.SH
+7.6  \fB.text\fR
+.SH
+7.7  \fB.data\fR
+.SH
+7.8  \fB.bss\fR
+.PP
+These three pseudo-operations cause the
+assembler to begin assembling into the text, data, or
+bss segment respectively.
+Assembly starts in the text segment.
+It is forbidden to assemble any
+code or data into the bss segment, but symbols may
+be defined and ``\|\fB.\fP\|'' moved about by assignment.
+.SH
+7.9  \fB.comm\fI  name  \fB,  \fIexpression\fR
+.PP
+Provided the \fIname\fR is not defined elsewhere,
+this state%ment is equivalent to
+.DS
+\&.globl  name
+name = expression ^ name
+.DE
+That is, the type of \fIname\fR
+is ``undefined external'', and its value is \fIexpression\fR.
+In fact the \fIname\fR behaves
+in the current assembly just like an
+undefined external.
+However, the link-editor \fIld\fR has been special-cased
+so that all external symbols which are not
+otherwise defined, and which have a non-zero
+value, are defined to lie in the bss
+segment, and enough space is left after the
+symbol to hold \fIexpression\fR
+bytes.
+All symbols which become defined in this way
+are located before all the explicitly defined
+bss-segment locations.
+.SH
+8.   Machine instructions
+.PP
+Because of the rather complicated instruction and addressing
+structure of the \s8PDP\s10-11, the syntax of machine instruction
+state%ments is varied.
+Although the following sections give the syntax
+in detail, the machine handbooks should
+be consulted on the semantics.
+.SH
+8.1  Sources and Destinations
+.PP
+The syntax of general source and destination
+addresses is the same.
+Each must have one of the following forms,
+where \fIreg\fR is a register symbol, and \fIexpr\fR
+is any sort of expression:
+.DS C
+.TS
+c c c
+l l l.
+syntax words   mode
+_
+\fIreg\fR      0       00+\fIreg\fB
+(\|\fIreg\fB\|)\|+     \fR0    20+\fIreg\fB
+\fB\-\|(\|\fIreg\fB\|) \fR0    40+\fIreg\fR
+\fIexpr\|\fB(\|\fIreg\fB\|)    \fR1    60+\fIreg\fB
+(\|\fIreg\fB\|)        \fR0    10+\fIreg\fB
+*\|\fIreg\fB   \fR0    10+\fIreg\fB
+\fB*\|(\|\fIreg\fB\|)\|+       \fR0    30+\fIreg\fB
+\fB*\|\-\|(\|\fIreg\fB\|)      \fR0    50+\fIreg\fB
+*\|(\|\fIreg\fB\|)     \fR1    70+\fIreg\fB
+\fB*\|\fIexpr\fB\|(\|\fIreg\fB\|)      \fR1    70+\fIreg\fB
+\fIexpr        \fR1    67
+\fB$\|\fIexpr  \fR1    27
+\fB*\|\fIexpr  \fR1    77
+\fB*\|$\|\fIexpr       \fR1    37
+.TE
+.DE
+The \fIwords\fR column gives the number of address words generated;
+the \fImode\fR column gives the octal address-mode number.
+The syntax of the address forms is
+identical to that in \s8DEC\s10 assemblers, except that ``*'' has
+been substituted for ``@''
+and ``$'' for ``#''; the \s8UNIX\s10 typing conventions make ``@'' and ``#''
+rather inconvenient.
+.PP
+Notice that mode ``*reg'' is identical to ``(reg)'';
+that ``*(reg)'' generates an index word (namely, 0);
+and that addresses consisting of an unadorned expression
+are assembled as pc-relative ref%er%ences independent
+of the type of the expression.
+To force a non-relative ref%er%ence, the form ``*$expr'' can
+be used, but notice that further indirection is impossible.
+.SH
+8.3  Simple machine instructions
+.PP
+The following instructions
+are defined as absolute symbols:
+.KS
+.DS
+.ft B
+clc
+clv
+clz
+cln
+sec
+sev
+sez
+sen
+.DE
+.KE
+They therefore require
+no special syntax.
+The \s8PDP\s10-11 hardware allows more than one of the ``clear''
+class, or alternatively more than one of the ``set'' class
+to be \fBor\fR-ed together; this may be expressed as follows:
+.DS
+clc\|\|\|\(bv\|\|clv
+.DE
+.SH
+8.4  Branch
+.PP
+The following instructions take an expression as operand.
+The expression must lie in the same segment as the ref%er%ence,
+cannot be undefined-external,
+and its value cannot differ from the current location of ``\|\fB.\fP\|''
+by more than 254 bytes:
+.KS
+.DS
+.ft B
+.ta 1.5i 2.5i
+br     blos
+bne    bvc
+beq    bvs
+bge    bhis
+blt    bec     \fR(=\fB bcc\fR)\fB
+bgt    bcc
+ble    blo
+bpl    bcs
+bmi    bes     \fR(=\fB bcs\fR)\fB
+bhi
+.DE
+.KE
+\fBbes\fR (``branch on error set'')
+and \fBbec\fR (``branch on error clear'')
+are intended to test the error bit
+returned by system calls (which
+is the c-bit).
+.SH
+8.5   Extended branch instructions
+.PP
+The following symbols are followed by an expression
+representing an address
+in the same segment as ``\|\fB.\|\fP''.
+If the target address is close enough,
+a branch-type instruction is generated;
+if the address is too far away,
+a \fBjmp\fR will be used.
+.pg
+.KS
+.DS
+.ft B
+.ta 1.5i
+jbr    jlos
+jne    jvc
+jeq    jvs
+jge    jhis
+jlt    jec
+jgt    jcc
+jle    jlo
+jpl    jcs
+jmi    jes
+jhi
+.DE
+.KE
+\fBjbr\fR turns into a plain \fBjmp\fR
+if its target is too remote;
+the others (whose names are contructed
+by replacing the ``b'' in the branch instruction's
+name by ``j''\|)
+turn into the converse branch over a \fBjmp\fR
+to the target address.
+.SH
+8.6  Single operand instructions
+.PP
+The following
+symbols are names of single-operand
+machine instructions.
+The form
+of address expected is discussed in \(sc8.1 above.
+.KS
+.DS
+.ta 1.5i
+clr    sbcb
+clrb   ror
+com    rorb
+comb   rol
+inc    rolb
+incb   asr
+dec    asrb
+decb   asl
+neg    aslb
+negb   jmp
+adc    swab
+adcb   tst
+sbc    tstb
+.DE
+.KE
+.SH
+8.7  Double operand instructions
+.PP
+The following instructions take a general source
+and destination (\(sc8.1), separated by a comma, as operands.
+.KS
+.DS
+.ft B
+.ta 1.5i
+mov
+movb
+cmp
+cmpb
+bit
+bitb
+bic
+bicb
+bis
+bisb
+add
+sub
+.DE
+.KE
+.SH
+8.8  Miscellaneous instructions
+.PP
+The following instructions have
+more specialized syntax.
+Here \fIreg\fR is
+a register name, \fIsrc\fR and \fIdst\fR a general source
+or destination
+(\(sc8.1), and \fIexpr\fR is an expression:
+.KS
+.DS
+.ta .5i 2i
+\fBjsr\fI      reg,dst
+\fBrts\fI      reg
+\fBsys\fI      expr
+\fBash \fIsrc\|,\|reg  \fR(or, \fBals\fR)\fB
+\fBashc        \fIsrc\|,\|reg  \fR(or, \fBalsc\fR)\fB
+\fBmul \fIsrc\|,\|reg  \fR(or, \fBmpy\fR)\fB
+\fBdiv \fIsrc\|,\|reg  \fR(or, \fBdvd\fR)\fR
+\fBxor \fIreg\|,\|dst\fB
+\fBsxt \fIdst\fB
+\fBmark        \fIexpr\fB
+\fBsob \fIreg\|,\|expr\fB
+.DE
+.KE
+\fBsys\fR is another name for the \fBtrap\fR instruction.
+It is used to code system calls.
+Its operand is required to be expressible in 6 bits.
+The expression in \fBmark\fR must be expressible
+in six bits, and the expression in \fBsob\fR must
+be in the same segment as ``\fB\|.\|\fR'',
+must not be external-undefined, must be less than ``\|\fB.\fR\|'',
+and must be within 510 bytes of ``\|\fB.\fR\|''.
+.SH
+8.9  Floating-point unit instructions
+.PP
+The following floating-point operations are defined,
+with syntax as indicated:
+.KS
+.DS
+.ta .5i 2i
+\fBcfcc
+\fBsetf
+\fBsetd
+\fBseti
+\fBsetl
+\fBclrf        \fIfdst
+\fBnegf        \fIfdst
+\fBabsf        \fIfdst
+\fBtstf        \fIfsrc
+\fBmovf        \fIfsrc,\|freg  \fR(= ldf\fR\|)
+\fBmovf        \fIfreg,\|fdst  \fR(= stf\fR\|)
+\fBmovif       \fIsrc,\|freg   \fR(= ldcif\fR\|)
+\fBmovfi       \fIfreg,\|dst   \fR(= stcfi\fR\|)
+\fBmovof       \fIfsrc,\|freg  \fR(= ldcdf\fR\|)
+\fBmovfo       \fIfreg,\|fdst  \fR(= stcfd\fR\|)
+\fBmovie       \fIsrc,\|freg   \fR(= ldexp\fR)
+\fBmovei       \fIfreg,\|dst   \fR(= stexp\fR)
+\fBaddf        \fIfsrc,\|freg
+\fBsubf        \fIfsrc,\|freg
+\fBmulf        \fIfsrc,\|freg
+\fBdivf        \fIfsrc,\|freg
+\fBcmpf        \fIfsrc,\|freg
+\fBmodf        \fIfsrc,\|freg
+\fBldfps       \fIsrc
+\fBstfps       \fIdst
+\fBstst        \fIdst\fR
+.DE
+.KE
+\fIfsrc\fR, \fIfdst\fR, and \fIfreg\fR mean floating-point
+source, destination, and register respectively.
+Their syntax is identical to that for
+their non-floating counterparts, but
+note that only
+floating registers 0-3 can be a \fIfreg\fR.
+.PP
+The names of several of the operations
+have been changed to bring out an analogy with
+certain fixed-point instructions.
+The only strange case is \fBmovf\fR, which turns into
+either \fBstf\fR or \fBldf\fR
+depending respectively on whether its first operand is
+or is not a register.
+Warning:  \fBldf\fR sets the floating condition codes,
+\fBstf\fR does not.
+.SH
+9.  Other symbols
+.SH
+9.1  \fB.\|.\fR
+.PP
+The symbol ``\fB\|.\|.\|\fR''
+is the
+\fIrelocation counter\fR.
+Just before each assembled word is placed in the output stream,
+the current value of this symbol is added to the word
+if the word refers to a text, data or bss segment location.
+If the output word is a pc-relative address word
+that refers to an absolute location,
+the value of ``\fB\|.\|.\|\fR'' is subtracted.
+.PP
+Thus the value of ``\fB\|.\|.\|\fR'' can be taken to mean
+the starting memory location of the program.
+The initial value of ``\|\fB.\|.\fR\|'' is 0.
+.PP
+The value of ``\|\fB.\|.\fR\|'' may be changed by assignment.
+Such a course of action is sometimes
+necessary, but the consequences
+should be carefully thought out.
+It is particularly ticklish
+to change ``\|\fB.\|.\fR\|'' midway in an assembly
+or to do so in a program which will
+be treated by the loader, which has
+its own notions of ``\|\fB.\|.\fR\|''.
+.SH
+9.2  System calls
+.PP
+System call names are not predefined.
+They may be found in the file
+.I /usr/include/sys.s
+.SH
+10.  Diagnostics
+.PP
+When
+an input file cannot be read, its name
+followed by a question mark is typed and assembly
+ceases.
+When syntactic or semantic errors occur, a single-character diagnostic is typed out
+together with the line number and the file name in which it
+occurred.  Errors in pass 1 cause cancellation of pass 2.
+The possible errors are:
+.KS
+.DS
+.ta .3i
+)       parentheses error
+]       parentheses error
+>       string not terminated properly
+*       indirection (\|*\|) used illegally
+\&\fB.\fR       illegal assignment to ``\|\fB.\fR\|''
+\s8A\s10        error in address
+\s8B\s10        branch address is odd or too remote
+\s8E\s10        error in expression
+\s8F\s10        error in local (``f\|'' or ``b'') type symbol
+\s8G\s10        garbage (unknown) character
+\s8I\s10        end of file inside an \fB.if\fR
+\s8M\s10        multiply defined symbol as label
+\s8O\s10        word quantity assembled at odd address
+\s8P\s10        phase error\(em ``\|\fB.\fP\|'' different in pass 1 and 2
+\s8R\s10        relocation error
+\s8U\s10        undefined symbol
+\s8X\s10        syntax error
+.DE
+.KE
diff --git a/doc/7thEdMan/vol2/awk b/doc/7thEdMan/vol2/awk
new file mode 100644 (file)
index 0000000..758da7d
--- /dev/null
@@ -0,0 +1,1401 @@
+.fp 3 G
+....TM "78-1271-12, 78-1273-6" 39199 39199-11
+.ND "September 1, 1978"
+....TR 68
+.RP
+.      \" macros here
+.tr _\(em
+.if t .tr ~\(ap
+.tr |\(or
+.tr *\(**
+.de UC
+\&\\$3\s-1\\$1\\s0\&\\$2
+..
+.de IT
+.if n .ul
+\&\\$3\f2\\$1\fP\|\\$2
+..
+.de UL
+.if n .ul
+\&\\$3\f3\\$1\fP\&\\$2
+..
+.de P1
+.DS I 3n
+.nf
+.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+.if t .ta .3i .6i .9i 1.2i
+.if t .tr -\-'\(fm*\(**
+.if t .tr _\(ul
+.ft 3
+.lg 0
+.ss 18
+.              \"use first argument as indent if present
+..
+.de P2
+.ps \\n(PS
+.vs \\n(VSp
+.ft R
+.ss 12
+.if n .ls 2
+.tr --''``^^!!
+.if t .tr _\(em
+.fi
+.lg
+.DE
+..
+.hw semi-colon
+.hy 14
+.              \"2=not last lines; 4= no -xx; 8=no xx-
+.              \"special chars in programs
+.de WS
+.sp \\$1
+..
+.      \" end of macros
+.TL
+Awk \(em A Pattern Scanning and Processing Language
+.br
+(Second Edition)
+.AU "MH 2C-522" 4862
+Alfred V. Aho
+.AU "MH 2C-518" 6021
+Brian W. Kernighan
+.AU "MH 2C-514" 7214
+Peter J. Weinberger
+.AI
+.MH
+.AB
+.IT Awk
+is a programming language whose
+basic operation
+is to search a set of files
+for patterns, and to perform specified actions upon lines or fields of lines which
+contain instances of those patterns.
+.IT Awk
+makes certain data selection and transformation operations easy to express;
+for example, the
+.IT awk
+program
+.sp
+.ce
+.ft 3
+length > 72
+.ft
+.sp
+prints all input lines whose length exceeds 72 characters;
+the program
+.ce
+.sp
+.ft 3
+NF % 2 == 0
+.ft R
+.sp
+prints all lines with an even number of fields;
+and the program
+.ce
+.sp
+.ft 3
+{ $1 = log($1); print }
+.ft R
+.sp
+replaces the first field of each line by its logarithm.
+.PP
+.IT Awk
+patterns may include arbitrary boolean combinations of regular expressions
+and of relational operators on strings, numbers, fields, variables, and array elements.
+Actions may include the same pattern-matching constructions as in patterns,
+as well as
+arithmetic and string expressions and assignments,
+.UL if-else ,
+.UL while ,
+.UL for
+statements,
+and multiple output streams.
+.PP
+This report contains a user's guide, a discussion of the design and implementation of
+.IT awk ,
+and some timing statistics.
+....It supersedes TM-77-1271-5, dated September 8, 1977.
+.AE
+.CS 6 1 7 0 1 4
+.if n .ls 2
+.nr PS 9
+.nr VS 11
+.NH
+Introduction
+.if t .2C
+.PP
+.IT Awk
+is a programming language designed to make
+many common
+information retrieval and text manipulation tasks
+easy to state and to perform.
+.PP
+The basic operation of
+.IT awk
+is to scan a set of input lines in order,
+searching for lines which match any of a set of patterns
+which the user has specified.
+For each pattern, an action can be specified;
+this action will be performed on each line that matches the pattern.
+.PP
+Readers familiar with the
+.UX
+program
+.IT grep\|
+.[
+unix program manual
+.]
+will recognize
+the approach, although in
+.IT awk
+the patterns may be more
+general than in
+.IT grep ,
+and the actions allowed are more involved than merely
+printing the matching line.
+For example, the
+.IT awk
+program
+.P1
+{print $3, $2}
+.P2
+prints the third and second columns of a table
+in that order.
+The program
+.P1
+$2 ~ /A\||B\||C/
+.P2
+prints all input lines with an A, B, or C in the second field.
+The program
+.P1
+$1 != prev     { print; prev = $1 }
+.P2
+prints all lines in which the first field is different
+from the previous first field.
+.NH 2
+Usage
+.PP
+The command
+.P1
+awk  program  [files]
+.P2
+executes the
+.IT awk
+commands in
+the string
+.UL program
+on the set of named files,
+or on the standard input if there are no files.
+The statements can also be placed in a file
+.UL pfile ,
+and executed by the command
+.P1
+awk  -f pfile  [files]
+.P2
+.NH 2
+Program Structure
+.PP
+An
+.IT awk
+program is a sequence of statements of the form:
+.P1
+.ft I
+       pattern { action }
+       pattern { action }
+       ...
+.ft 3
+.P2
+Each line of input
+is matched against
+each of the patterns in turn.
+For each pattern that matches, the associated action
+is executed.
+When all the patterns have been tested, the next line
+is fetched and the matching starts over.
+.PP
+Either the pattern or the action may be left out,
+but not both.
+If there is no action for a pattern,
+the matching line is simply
+copied to the output.
+(Thus a line which matches several patterns can be printed several times.)
+If there is no pattern for an action,
+then the action is performed for every input line.
+A line which matches no pattern is ignored.
+.PP
+Since patterns and actions are both optional,
+actions must be enclosed in braces
+to distinguish them from patterns.
+.NH 2
+Records and Fields
+.PP
+.IT Awk
+input is divided into
+``records'' terminated by a record separator.
+The default record separator is a newline,
+so by default
+.IT awk
+processes its input a line at a time.
+The number of the current record is available in a variable
+named
+.UL NR .
+.PP
+Each input record
+is considered to be divided into ``fields.''
+Fields are normally separated by
+white space \(em blanks or tabs \(em
+but the input field separator may be changed, as described below.
+Fields are referred to as
+.UL "$1, $2,"
+and so forth,
+where
+.UL $1
+is the first field,
+and
+.UL $0
+is the whole input record itself.
+Fields may be assigned to.
+The number of fields in the current record
+is available in a variable named
+.UL NF .
+.PP
+The variables
+.UL FS
+and
+.UL RS
+refer to the input field and record separators;
+they may be changed at any time to any single character.
+The optional command-line argument
+\f3\-F\fIc\fR
+may also be used to set
+.UL FS
+to the character
+.IT c .
+.PP
+If the record separator is empty,
+an empty input line is taken as the record separator,
+and blanks, tabs and newlines are treated as field separators.
+.PP
+The variable
+.UL FILENAME
+contains the name of the current input file.
+.NH 2
+Printing
+.PP
+An action may have no pattern,
+in which case the action is executed for
+all
+lines.
+The simplest action is to print some or all of a record;
+this is accomplished by the
+.IT awk
+command
+.UL print .
+The
+.IT awk
+program
+.P1
+{ print }
+.P2
+prints each record, thus copying the input to the output intact.
+More useful is to print a field or fields from each record.
+For instance, 
+.P1
+print $2, $1
+.P2
+prints the first two fields in reverse order.
+Items separated by a comma in the print statement will be separated by the current output field separator
+when output.
+Items not separated by commas will be concatenated,
+so
+.P1
+print $1 $2
+.P2
+runs the first and second fields together.
+.PP
+The predefined variables
+.UL NF
+and
+.UL NR
+can be used;
+for example
+.P1
+{ print NR, NF, $0 }
+.P2
+prints each record preceded by the record number and the number of fields.
+.PP
+Output may be diverted to multiple files;
+the program
+.P1
+{ print $1 >"foo1"; print $2 >"foo2" }
+.P2
+writes the first field,
+.UL $1 ,
+on the file
+.UL foo1 ,
+and the second field on file
+.UL foo2 .
+The
+.UL >>
+notation can also be used:
+.P1
+print $1 >>"foo"
+.P2
+appends the output to the file
+.UL foo .
+(In each case,
+the output files are
+created if necessary.)
+The file name can be a variable or a field as well as a constant;
+for example,
+.P1
+print $1 >$2
+.P2
+uses the contents of field 2 as a file name.
+.PP
+Naturally there is a limit on the number of output files;
+currently it is 10.
+.PP
+Similarly, output can be piped into another process
+(on
+.UC UNIX
+only); for instance,
+.P1
+print | "mail bwk"
+.P2
+mails the output to
+.UL bwk .
+.PP
+The variables
+.UL OFS
+and
+.UL ORS
+may be used to change the current
+output field separator and output
+record separator.
+The output record separator is
+appended to the output of the
+.UL print
+statement.
+.PP
+.IT Awk
+also provides the
+.UL printf
+statement for output formatting:
+.P1
+printf format expr, expr, ...
+.P2
+formats the expressions in the list
+according to the specification
+in
+.UL format
+and prints them.
+For example,
+.P1
+printf "%8.2f  %10ld\en", $1, $2
+.P2
+prints 
+.UL $1
+as a floating point number 8 digits wide,
+with two after the decimal point,
+and
+.UL $2
+as a 10-digit long decimal number,
+followed by a newline.
+No output separators are produced automatically;
+you must add them yourself,
+as in this example.
+The version of
+.UL printf
+is identical to that used with C.
+.[
+C programm language prentice hall 1978
+.]
+.NH 1
+Patterns
+.PP
+A pattern in front of an action acts as a selector
+that determines whether the action is to be executed.
+A variety of expressions may be used as patterns:
+regular expressions,
+arithmetic relational expressions,
+string-valued expressions,
+and arbitrary boolean
+combinations of these.
+.NH 2
+BEGIN and END
+.PP
+The special pattern
+.UL BEGIN
+matches the beginning of the input,
+before the first record is read.
+The pattern
+.UL END
+matches the end of the input,
+after the last record has been processed.
+.UL BEGIN
+and
+.UL END
+thus provide a way to gain control before and after processing,
+for initialization and wrapup.
+.PP
+As an example, the field separator
+can be set to a colon by
+.P1
+BEGIN  { FS = ":" }
+.ft I
+\&... rest of program ...
+.ft 3
+.P2
+Or the input lines may be counted by
+.P1
+END  { print NR }
+.P2
+If
+.UL BEGIN
+is present, it must be the first pattern;
+.UL END
+must be the last if used.
+.NH 2
+Regular Expressions
+.PP
+The simplest regular expression is a literal string of characters
+enclosed in slashes,
+like
+.P1
+/smith/
+.P2
+This
+is actually a complete
+.IT awk
+program which
+will print all lines which contain any occurrence
+of the name ``smith''.
+If a line contains ``smith''
+as part of a larger word,
+it will also be printed, as in
+.P1
+blacksmithing
+.P2
+.PP
+.IT Awk
+regular expressions include the regular expression
+forms found in
+the
+.UC UNIX
+text editor
+.IT ed\|
+.[
+unix program manual
+.]
+and
+.IT grep
+(without back-referencing).
+In addition,
+.IT awk
+allows
+parentheses for grouping, | for alternatives,
+.UL +
+for ``one or more'', and
+.UL ?
+for ``zero or one'',
+all as in
+.IT lex .
+Character classes
+may be abbreviated:
+.UL [a\-zA\-Z0\-9]
+is the set of all letters and digits.
+As an example,
+the
+.IT awk
+program
+.P1
+/[Aa]ho\||[Ww]einberger\||[Kk]ernighan/
+.P2
+will print all lines which contain any of the names
+``Aho,'' ``Weinberger'' or ``Kernighan,''
+whether capitalized or not.
+.PP
+Regular expressions
+(with the extensions listed above)
+must be enclosed in slashes,
+just as in
+.IT ed
+and
+.IT sed .
+Within a regular expression,
+blanks and the regular expression
+metacharacters are significant.
+To turn of the magic meaning
+of one of the regular expression characters,
+precede it with a backslash.
+An example is the pattern
+.P1
+/\|\e/\^.\^*\e//
+.P2
+which matches any string of characters
+enclosed in slashes.
+.PP
+One can also specify that any field or variable
+matches
+a regular expression (or does not match it) with the operators
+.UL ~
+and
+.UL !~ .
+The program
+.P1
+$1 ~ /[jJ]ohn/
+.P2
+prints all lines where the first field matches ``john'' or ``John.''
+Notice that this will also match ``Johnson'', ``St. Johnsbury'', and so on.
+To restrict it to exactly
+.UL [jJ]ohn ,
+use
+.P1
+$1 ~ /^[jJ]ohn$/
+.P2
+The caret ^ refers to the beginning
+of a line or field;
+the dollar sign
+.UL $
+refers to the end.
+.NH 2
+Relational Expressions
+.PP
+An
+.IT awk
+pattern can be a relational expression
+involving the usual relational operators
+.UL < ,
+.UL <= ,
+.UL == ,
+.UL != ,
+.UL >= ,
+and
+.UL > .
+An example is
+.P1
+$2 > $1 + 100
+.P2
+which selects lines where the second field
+is at least 100 greater than the first field.
+Similarly,
+.P1
+NF % 2 == 0
+.P2
+prints lines with an even number of fields.
+.PP
+In relational tests, if neither operand is numeric,
+a string comparison is made;
+otherwise it is numeric.
+Thus,
+.P1
+$1 >= "s"
+.P2
+selects lines that begin with an
+.UL s ,
+.UL t ,
+.UL u ,
+etc.
+In the absence of any other information,
+fields are treated as strings, so
+the program
+.P1
+$1 > $2
+.P2
+will perform a string comparison.
+.NH 2
+Combinations of Patterns
+.PP
+A pattern can be any boolean combination of patterns,
+using the operators
+.UL \||\||
+(or),
+.UL &&
+(and), and
+.UL !
+(not).
+For example,
+.P1
+$1 >= "s" && $1 < "t" && $1 != "smith"
+.P2
+selects lines where the first field begins with ``s'', but is not ``smith''.
+.UL &&
+and
+.UL \||\||
+guarantee that their operands
+will be evaluated
+from left to right;
+evaluation stops as soon as the truth or falsehood
+is determined.
+.NH 2
+Pattern Ranges
+.PP
+The ``pattern'' that selects an action may also
+consist of two patterns separated by a comma, as in
+.P1
+pat1, pat2     { ... }
+.P2
+In this case, the action is performed for each line between
+an occurrence of
+.UL pat1
+and the next occurrence of
+.UL pat2
+(inclusive).
+For example,
+.P1
+/start/, /stop/
+.P2
+prints all lines between
+.UL start
+and
+.UL stop ,
+while
+.P1
+NR == 100, NR == 200 { ... }
+.P2
+does the action for lines 100 through 200
+of the input.
+.NH 1
+Actions
+.PP
+An
+.IT awk
+action is a sequence of action statements
+terminated by newlines or semicolons.
+These action statements can be used to do a variety of
+bookkeeping and string manipulating tasks.
+.NH 2
+Built-in Functions
+.PP
+.IT Awk
+provides a ``length'' function
+to compute the length of a string of characters.
+This program prints each record,
+preceded by its length:
+.P1
+{print length, $0}
+.P2
+.UL length
+by itself is a ``pseudo-variable'' which
+yields the length of the current record;
+.UL length(argument)
+is a function which yields the length of its argument,
+as in
+the equivalent
+.P1
+{print length($0), $0}
+.P2
+The argument may be any expression.
+.PP
+.IT Awk
+also
+provides the arithmetic functions
+.UL sqrt ,
+.UL log ,
+.UL exp ,
+and
+.UL int ,
+for
+square root,
+base
+.IT e
+logarithm,
+exponential,
+and integer part of their respective arguments.
+.PP
+The name of one of these built-in functions,
+without argument or parentheses,
+stands for the value of the function on the
+whole record.
+The program
+.P1
+length < 10 || length > 20
+.P2
+prints lines whose length
+is less than 10 or greater
+than 20.
+.PP
+The function
+.UL substr(s,\ m,\ n)
+produces the substring of
+.UL s
+that begins at position
+.UL m
+(origin 1)
+and is at most
+.UL n
+characters long.
+If
+.UL n
+is omitted, the substring goes to the end of
+.UL s .
+The function
+.UL index(s1,\ s2)
+returns the position where the string
+.UL s2
+occurs in
+.UL s1 ,
+or zero if it does not.
+.PP
+The function
+.UL sprintf(f,\ e1,\ e2,\ ...)
+produces the value of the expressions
+.UL e1 ,
+.UL e2 ,
+etc.,
+in the
+.UL printf
+format specified by
+.UL f .
+Thus, for example,
+.P1
+x = sprintf("%8.2f %10ld", $1, $2)
+.P2
+sets
+.UL x
+to the string produced by formatting
+the values of
+.UL $1
+and
+.UL $2 .
+.NH 2
+Variables, Expressions, and Assignments
+.PP
+.IT Awk
+variables take on numeric (floating point)
+or string values according to context.
+For example, in
+.P1
+x = 1
+.P2
+.UL x
+is clearly a number, while in
+.P1
+x = "smith"
+.P2
+it is clearly a string.
+Strings are converted to numbers and
+vice versa whenever context demands it.
+For instance,
+.P1
+x = "3" + "4"
+.P2
+assigns 7 to
+.UL x .
+Strings which cannot be interpreted
+as numbers in a numerical context
+will generally have numeric value zero,
+but it is unwise to count on this behavior.
+.PP
+By default, variables (other than built-ins) are initialized to the null string,
+which has numerical value zero;
+this eliminates the need for most
+.UL BEGIN
+sections.
+For example, the sums of the first two fields can be computed by
+.P1
+       { s1 += $1; s2 += $2 }
+END    { print s1, s2 }
+.P2
+.PP
+Arithmetic is done internally in floating point.
+The arithmetic operators are
+.UL + ,
+.UL \- ,
+.UL \(** ,
+.UL / ,
+and
+.UL %
+(mod).
+The C increment
+.UL ++
+and
+decrement
+.UL \-\-
+operators are also available,
+and so are the assignment operators
+.UL += ,
+.UL \-= ,
+.UL *= ,
+.UL /= ,
+and
+.UL %= .
+These operators may all be used in expressions.
+.NH 2
+Field Variables
+.PP
+Fields in
+.IT awk
+share essentially all of the properties of variables _
+they may be used in arithmetic or string operations,
+and may be assigned to.
+Thus one can
+replace the first field with a sequence number like this:
+.P1
+{ $1 = NR; print }
+.P2
+or
+accumulate two fields into a third, like this:
+.P1
+{ $1 = $2 + $3; print $0 }
+.P2
+or assign a string to a field:
+.P1
+{ if ($3 > 1000)
+       $3 = "too big"
+  print
+}
+.P2
+which replaces the third field by ``too big'' when it is,
+and in any case prints the record.
+.PP
+Field references may be numerical expressions,
+as in
+.P1
+{ print $i, $(i+1), $(i+n) }
+.P2
+Whether a field is deemed numeric or string depends on context;
+in ambiguous cases like
+.P1
+if ($1 == $2) ...
+.P2
+fields are treated as strings.
+.PP
+Each input line is split into fields automatically as necessary.
+It is also possible to split any variable or string
+into fields:
+.P1
+n = split(s, array, sep)
+.P2
+splits the
+the string
+.UL s
+into
+.UL array[1] ,
+\&...,
+.UL array[n] .
+The number of elements found is returned.
+If the
+.UL sep
+argument is provided, it is used as the field separator;
+otherwise
+.UL FS
+is used as the separator.
+.NH 2
+String Concatenation
+.PP
+Strings may be concatenated.
+For example
+.P1
+length($1 $2 $3)
+.P2
+returns the length of the first three fields.
+Or in a
+.UL print
+statement,
+.P1
+print $1 " is " $2
+.P2
+prints
+the two fields separated by `` is ''.
+Variables and numeric expressions may also appear in concatenations.
+.NH 2
+Arrays
+.PP
+Array elements are not declared;
+they spring into existence by being mentioned.
+Subscripts may have
+.ul
+any
+non-null
+value, including non-numeric strings.
+As an example of a conventional numeric subscript,
+the statement
+.P1
+x[NR] = $0
+.P2
+assigns the current input record to
+the
+.UL NR -th
+element of the array
+.UL x .
+In fact, it is possible in principle (though perhaps slow)
+to process the entire input in a random order with the
+.IT awk
+program
+.P1
+       { x[NR] = $0 }
+END    { \fI... program ...\fP }
+.P2
+The first action merely records each input line in
+the array
+.UL x .
+.PP
+Array elements may be named by non-numeric values,
+which gives
+.IT awk
+a capability rather like the associative memory of
+Snobol tables.
+Suppose the input contains fields with values like
+.UL apple ,
+.UL orange ,
+etc.
+Then the program
+.P1
+/apple/        { x["apple"]++ }
+/orange/       { x["orange"]++ }
+END            { print x["apple"], x["orange"] }
+.P2
+increments counts for the named array elements,
+and prints them at the end of the input.
+.NH 2
+Flow-of-Control Statements
+.PP
+.IT Awk
+provides the basic flow-of-control statements
+.UL if-else ,
+.UL while ,
+.UL for ,
+and statement grouping with braces, as in C.
+We showed the
+.UL if
+statement in section 3.3 without describing it.
+The condition in parentheses is evaluated;
+if it is true, the statement following the
+.UL if
+is done.
+The
+.UL else
+part is optional.
+.PP
+The
+.UL while
+statement is exactly like that of C.
+For example, to print all input fields one per line,
+.P1
+i = 1
+while (i <= NF) {
+       print $i
+       ++i
+}
+.P2
+.PP
+The
+.UL for
+statement is also exactly that of C:
+.P1
+for (i = 1; i <= NF; i++)
+       print $i
+.P2
+does the same job as the
+.UL while
+statement above.
+.PP
+There is an alternate form of the
+.UL for
+statement which is suited for accessing the
+elements of an associative array:
+.P1
+for (i in array)
+       \fIstatement\f3
+.P2
+does
+.ul
+statement
+with 
+.UL i
+set in turn to each element of
+.UL array .
+The elements are accessed in an apparently random order.
+Chaos will ensue if 
+.UL i
+is altered, or if any new elements are
+accessed during the loop.
+.PP
+The expression in the condition part of an
+.UL if ,
+.UL while
+or
+.UL for
+can include relational operators like
+.UL < ,
+.UL <= ,
+.UL > ,
+.UL >= ,
+.UL ==
+(``is equal to''),
+and
+.UL !=
+(``not equal to'');
+regular expression matches with the match operators
+.UL ~
+and
+.UL !~ ;
+the logical operators
+.UL \||\|| ,
+.UL && ,
+and
+.UL ! ;
+and of course parentheses for grouping.
+.PP
+The
+.UL break
+statement causes an immediate exit
+from an enclosing
+.UL while
+or
+.UL for ;
+the
+.UL continue
+statement
+causes the next iteration to begin.
+.PP
+The statement
+.UL next
+causes
+.IT awk
+to skip immediately to
+the next record and begin scanning the patterns from the top.
+The statement
+.UL exit
+causes the program to behave as if the end of the input
+had occurred.
+.PP
+Comments may be placed in
+.IT awk
+programs:
+they begin with the character
+.UL #
+and end with the end of the line,
+as in
+.P1
+print x, y     # this is a comment
+.P2
+.NH
+Design
+.PP
+The
+.UX
+system
+already provides several programs that
+operate by passing input through a
+selection mechanism.
+.IT Grep ,
+the first and simplest, merely prints all lines which
+match a single specified pattern.
+.IT Egrep
+provides more general patterns, i.e., regular expressions
+in full generality;
+.IT fgrep
+searches for a set of keywords with a particularly fast algorithm.
+.IT Sed\|
+.[
+unix programm manual
+.]
+provides most of the editing facilities of
+the editor
+.IT ed  ,
+applied to a stream of input.
+None of these programs provides
+numeric capabilities,
+logical relations,
+or variables.
+.PP
+.IT Lex\|
+.[
+lesk lexical analyzer cstr
+.]
+provides general regular expression recognition capabilities,
+and, by serving as a C program generator,
+is essentially open-ended in its capabilities.
+The use of
+.IT lex ,
+however, requires a knowledge of C programming,
+and a
+.IT lex
+program must be compiled and loaded before use,
+which discourages its use for one-shot applications.
+.PP
+.IT Awk
+is an attempt
+to fill in another part of the matrix of possibilities.
+It
+provides general regular expression capabilities
+and an implicit input/output loop.
+But it also provides convenient numeric processing,
+variables,
+more general selection,
+and control flow in the actions.
+It
+does not require compilation or a knowledge of C.
+Finally,
+.IT awk
+provides
+a convenient way to access fields within lines;
+it is unique in this respect.
+.PP
+.IT Awk
+also tries to integrate strings and numbers
+completely,
+by treating all quantities as both string and numeric,
+deciding which representation is appropriate
+as late as possible.
+In most cases the user can simply ignore the differences.
+.PP
+Most of the effort in developing
+.I awk
+went into deciding what
+.I awk
+should or should not do
+(for instance, it doesn't do string substitution)
+and what the syntax should be
+(no explicit operator for concatenation)
+rather
+than on writing or debugging the code.
+We have tried
+to make the syntax powerful
+but easy to use and well adapted
+to scanning files.
+For example,
+the absence of declarations and implicit initializations,
+while probably a bad idea for a general-purpose programming language,
+is desirable in a language
+that is meant to be used for tiny programs
+that may even be composed on the command line.
+.PP
+In practice,
+.IT awk
+usage seems to fall into two broad categories.
+One is what might be called ``report generation'' \(em
+processing an input to extract counts,
+sums, sub-totals, etc.
+This also includes the writing of trivial
+data validation programs,
+such as verifying that a field contains only numeric information
+or that certain delimiters are properly balanced.
+The combination of textual and numeric processing is invaluable here.
+.PP
+A second area of use is as a data transformer,
+converting data from the form produced by one program
+into that expected by another.
+The simplest examples merely select fields, perhaps with rearrangements.
+.NH
+Implementation
+.PP
+The actual implementation of
+.IT awk
+uses the language development tools available
+on the
+.UC UNIX
+operating system.
+The grammar is specified with
+.IT yacc ;
+.[
+yacc johnson cstr
+.]
+the lexical analysis is done by
+.IT lex ;
+the regular expression recognizers are
+deterministic finite automata
+constructed directly from the expressions.
+An
+.IT awk
+program is translated into a 
+parse tree which is then directly executed
+by a simple interpreter.
+.PP
+.IT Awk
+was designed for ease of use rather than processing speed;
+the delayed evaluation of variable types
+and the necessity to break input
+into fields makes high speed difficult to achieve in any case.
+Nonetheless,
+the program has not proven to be unworkably slow.
+.PP
+Table I below shows the execution (user + system) time
+on a PDP-11/70 of
+the
+.UC UNIX
+programs
+.IT wc ,
+.IT grep ,
+.IT egrep ,
+.IT fgrep ,
+.IT sed ,
+.IT lex ,
+and
+.IT awk
+on the following simple tasks:
+.IP "\ \ 1."
+count the number of lines.
+.IP "\ \ 2."
+print all lines containing ``doug''.
+.IP "\ \ 3."
+print all lines containing ``doug'', ``ken'' or ``dmr''.
+.IP "\ \ 4."
+print the third field of each line.
+.IP "\ \ 5."
+print the third and second fields of each line, in that order.
+.IP "\ \ 6."
+append all lines containing ``doug'', ``ken'', and ``dmr''
+to files ``jdoug'', ``jken'', and ``jdmr'', respectively.
+.IP "\ \ 7."
+print each line prefixed by ``line-number\ :\ ''.
+.IP "\ \ 8."
+sum the fourth column of a table.
+.LP
+The program
+.IT wc
+merely counts words, lines and characters in its input;
+we have already mentioned the others.
+In all cases the input was a file containing
+10,000 lines
+as created by the
+command
+.IT "ls \-l" ;
+each line has the form
+.P1
+-rw-rw-rw- 1 ava 123 Oct 15 17:05 xxx
+.P2
+The total length of this input is
+452,960 characters.
+Times for
+.IT lex
+do not include compile or load.
+.PP
+As might be expected,
+.IT awk
+is not as fast as the specialized tools
+.IT wc ,
+.IT sed ,
+or the programs in the
+.IT grep
+family,
+but
+is faster than the more general tool
+.IT lex .
+In all cases, the tasks were
+about as easy to express as
+.IT awk
+programs
+as programs in these other languages;
+tasks involving fields were
+considerably easier to express as
+.IT awk
+programs.
+Some of the test programs are shown in
+.IT awk ,
+.IT sed
+and
+.IT lex .
+.[
+$LIST$
+.]
+.1C
+.TS
+center;
+c c c c c c c c c
+c c c c c c c c c
+c|n|n|n|n|n|n|n|n|.
+                               Task
+Program        1       2       3       4       5       6       7       8
+_
+\fIwc\fR       8.6
+\fIgrep\fR     11.7    13.1
+\fIegrep\fR    6.2     11.5    11.6
+\fIfgrep\fR    7.7     13.8    16.1
+\fIsed\fR      10.2    11.6    15.8    29.0    30.5    16.1
+\fIlex\fR      65.1    150.1   144.2   67.7    70.3    104.0   81.7    92.8
+\fIawk\fR      15.0    25.6    29.9    33.3    38.9    46.4    71.4    31.1
+_
+.TE
+.sp
+.ce
+\fBTable I.\fR  Execution Times of Programs. (Times are in sec.)
+.sp 2
+.2C
+.PP
+The programs for some of these jobs are shown below.
+The
+.IT lex
+programs are generally too long to show.
+.LP
+AWK:
+.LP
+.P1
+1.     END     {print NR}
+.P2
+.P1
+2.     /doug/
+.P2
+.P1
+3.     /ken|doug|dmr/
+.P2
+.P1
+4.     {print $3}
+.P2
+.P1
+5.     {print $3, $2}
+.P2
+.P1
+6.     /ken/   {print >"jken"}
+       /doug/  {print >"jdoug"}
+       /dmr/   {print >"jdmr"}
+.P2
+.P1
+7.     {print NR ": " $0}
+.P2
+.P1
+8.             {sum = sum + $4}
+       END     {print sum}
+.P2
+.LP
+SED:
+.LP
+.P1
+1.     $=
+.P2
+.P1
+2.     /doug/p
+.P2
+.P1
+3.     /doug/p
+       /doug/d
+       /ken/p
+       /ken/d
+       /dmr/p
+       /dmr/d
+.P2
+.P1
+4.     /[^ ]* [ ]*[^ ]* [ ]*\e([^ ]*\e) .*/s//\e1/p
+.P2
+.P1
+5.     /[^ ]* [ ]*\e([^ ]*\e) [ ]*\e([^ ]*\e) .*/s//\e2 \e1/p
+.P2
+.P1
+6.     /ken/w jken
+       /doug/w jdoug
+       /dmr/w jdmr
+.P2
+.LP
+LEX:
+.LP
+.P1
+1.     %{
+       int i;
+       %}
+       %%
+       \en     i++;
+       .       ;
+       %%
+       yywrap() {
+               printf("%d\en", i);
+       }
+.P2
+.P1
+2.     %%
+       ^.*doug.*$      printf("%s\en", yytext);
+       .       ;
+       \en     ;
+.P2
diff --git a/doc/7thEdMan/vol2/bc b/doc/7thEdMan/vol2/bc
new file mode 100644 (file)
index 0000000..58d839c
--- /dev/null
@@ -0,0 +1,1059 @@
+.RP
+.TL
+BC \- An Arbitrary Precision Desk-Calculator Language
+.AU
+Lorinda Cherry
+.AU
+Robert Morris
+.AI
+.MH
+.AB
+BC is a language and a compiler for doing arbitrary precision arithmetic
+on the PDP-11 under the
+.UX
+time-sharing
+system.  The output of the compiler is interpreted and executed by
+a collection of routines which can input, output, and do
+arithmetic on indefinitely large integers and on scaled fixed-point
+numbers.
+.PP
+These routines are themselves based on a dynamic storage allocator.
+Overflow does not occur until all available core storage
+is exhausted.
+.PP
+The language has a complete control structure as well as immediate-mode
+operation.  Functions can be defined and saved for later execution.
+.PP
+Two five hundred-digit numbers can be multiplied to give a
+thousand digit result in about ten seconds.
+.PP
+A small collection of library functions is also available,
+including sin, cos, arctan, log, exponential, and Bessel functions of
+integer order.
+.PP
+Some of the uses of this compiler are
+.IP \-
+to do computation with large integers,
+.IP \-
+to do computation accurate to many decimal places,
+.IP \-
+conversion of numbers from one base to another base.
+.AE
+.PP
+.SH
+Introduction
+.PP
+BC is a language and a compiler for doing arbitrary precision
+arithmetic on the
+.UX
+time-sharing system [1].
+The compiler was written to make conveniently available a
+collection of routines (called DC [5]) which are capable of doing
+arithmetic on integers of arbitrary size.  The compiler
+is by no means intended to provide a complete programming
+language.
+It is a minimal language facility.
+.PP
+There is a scaling provision that permits the
+use of decimal point notation.
+Provision is made for input and output in bases other than
+decimal.  Numbers can be converted from decimal to octal by
+simply setting the output base to equal 8.
+.PP
+The actual limit on the number of digits that can
+be handled depends on the amount of storage available on the machine.
+Manipulation of numbers with many hundreds of digits
+is possible even on the smallest versions of
+.UX .
+.PP
+The syntax of BC has been deliberately selected to agree
+substantially with the C language [2].  Those who
+are familiar with C will find few surprises in this language.
+.SH
+Simple Computations with Integers
+.PP
+The simplest kind of statement is an arithmetic expression
+on a line by itself.
+For instance, if you type in the line:
+.DS
+142857 + 285714
+.DE
+the program responds immediately with the line
+.DS
+428571
+.DE
+The operators \-, *, /, %, and ^ can also be used; they
+indicate subtraction, multiplication, division, remaindering, and
+exponentiation, respectively.  Division of integers produces an
+integer result truncated toward zero.
+Division by zero produces an error
+comment.
+.PP
+Any term in an expression may be prefixed by a minus sign to
+indicate that it is to be negated (the `unary' minus sign).
+The expression
+.DS
+7+\-3
+.DE
+is interpreted to mean that \-3 is to be added to 7.
+.PP
+More complex expressions with several operators and with
+parentheses are interpreted just as in
+Fortran, with ^ having the greatest binding
+power, then * and % and /, and finally + and \-.
+Contents of parentheses are evaluated before material
+outside the parentheses.
+Exponentiations are
+performed from right to left and the other operators
+from left to right.
+The two expressions
+.DS
+a^b^c  and  a^(b^c)
+.DE
+are equivalent, as are the two expressions
+.DS
+a*b*c  and  (a*b)*c
+.DE
+BC shares with Fortran and C the undesirable convention that
+.DS
+a/b*c  is equivalent to  (a/b)*c
+.DE
+.PP
+Internal storage registers to hold numbers have single lower-case
+letter names.  The value of an expression can be assigned to
+a register in the usual way.  The statement
+.DS
+x = x + 3
+.DE
+has the effect of increasing by three the value of the contents of the
+register named x.
+When, as in this case, the outermost operator is an =, the
+assignment is performed but the result is not printed.
+Only 26 of these named storage registers are available.
+.PP
+There is a built-in square root function whose
+result is truncated to an integer (but see scaling below).
+The lines
+.DS
+x = sqrt(191)
+x
+.DE
+produce the printed result
+.DS
+13
+.DE
+.SH
+Bases
+.PP
+There are special internal quantities, called `ibase' and `obase'.
+The contents of `ibase', initially set to 10,
+determines the base used for interpreting numbers read in.
+For example, the lines
+.DS
+ibase = 8
+11
+.DE
+will produce the output line
+.DS
+9
+.DE
+and you are all set up to do octal to decimal conversions.
+Beware, however of trying to change the input base back
+to decimal by typing
+.DS
+ibase = 10
+.DE
+Because the number 10 is interpreted as octal, this statement will
+have no effect.
+For those who deal in hexadecimal notation,
+the characters A\-F are permitted in numbers
+(no matter what base is in effect)
+and are
+interpreted as digits having values 10\-15 respectively.
+The statement
+.DS
+ibase = A
+.DE
+will change you back to decimal input base no matter what the
+current input base is.
+Negative and large positive input bases are
+permitted but useless.
+No mechanism has been provided for the input of arbitrary
+numbers in bases less than 1 and greater than 16.
+.PP
+The contents of `obase', initially set to 10, are used as the base for output
+numbers.  The lines
+.DS
+obase = 16
+1000
+.DE
+will produce the output line
+.DS
+3E8
+.DE
+which is to be interpreted as a 3-digit hexadecimal number.
+Very large output bases are permitted, and they are sometimes useful.
+For example, large numbers can be output in groups of five digits
+by setting `obase' to 100000.
+Strange (i.e. 1, 0, or negative) output bases are
+handled appropriately.
+.PP
+Very large numbers are split across lines with 70 characters per line.
+Lines which are continued end with \\.
+Decimal output conversion is practically instantaneous, but output
+of very large numbers (i.e., more than 100 digits) with other bases
+is rather slow.
+Non-decimal output conversion of
+a one hundred digit number takes about
+three seconds.
+.PP
+It is best to remember that `ibase' and `obase' have no effect
+whatever on the course of internal computation or
+on the evaluation of expressions, but only affect input and
+output conversion, respectively.
+.SH
+Scaling
+.PP
+A third special internal quantity called `scale' is
+used to determine the scale of calculated
+quantities.
+Numbers may have
+up to 99 decimal digits after the decimal point.
+This fractional part is retained in further computations.
+We refer to the number of digits after the decimal point of
+a number as its scale.
+.PP
+When two scaled numbers are combined by
+means of one of the arithmetic operations, the result
+has a scale determined by the following rules.  For
+addition and subtraction, the scale of the result is the larger
+of the scales of the two operands.  In this case,
+there is never any truncation of the result.
+For multiplications, the scale of the result is never
+less than the maximum of the two scales of the operands,
+never more than the sum of the scales of the operands
+and, subject to those two restrictions,
+the scale of the result is set equal to the contents of the internal
+quantity `scale'.
+The scale of a quotient is the contents of the internal
+quantity `scale'.  The scale of a remainder is
+the sum of the scales of the quotient and the divisor.
+The result of an exponentiation is scaled as if
+the implied multiplications were performed.
+An exponent must be an integer.
+The scale of a square root is set to the maximum of the scale
+of the argument and the contents of `scale'.
+.PP
+All of the internal operations are actually carried out in terms
+of integers, with digits being discarded when necessary.
+In every case where digits are discarded, truncation and
+not rounding is performed.
+.PP
+The contents of
+`scale' must be no greater than
+99 and no less than 0.  It is initially set to 0.
+In case you need more than 99 fraction digits, you may arrange
+your own scaling.
+.PP
+The internal quantities `scale', `ibase', and `obase' can be
+used in expressions just like other variables.
+The line
+.DS
+scale = scale + 1
+.DE
+increases the value of `scale' by one, and the line
+.DS
+scale
+.DE
+causes the current value of `scale' to be printed.
+.PP
+The value of `scale' retains its meaning as a
+number of decimal digits to be retained in internal
+computation even when `ibase' or `obase' are not equal to 10.
+The internal computations (which are still conducted in decimal,
+regardless of the bases) are performed to the specified number
+of decimal digits, never hexadecimal or octal or any
+other kind of digits.
+.SH
+Functions
+.PP
+The name of a function is a single lower-case letter.
+Function names are permitted to collide with simple
+variable names.
+Twenty-six different defined functions are permitted
+in addition to the twenty-six variable names.
+The line
+.DS
+       define a(x){
+.DE
+begins the definition of a function with one argument.
+This line must be followed by one or more statements,
+which make up the body of the function, ending
+with a right brace }.
+Return of control from a function occurs when a return
+statement is executed or when the end of the function is reached.
+The return statement can take either
+of the two forms
+.DS
+return
+return(x)
+.DE
+In the first case, the value of the function is 0, and in
+the second, the value of the expression in parentheses.
+.PP
+Variables used in the function can be declared as automatic
+by a statement of the form
+.DS
+auto x,y,z
+.DE
+There can be only one `auto' statement in a function and it must
+be the first statement in the definition.
+These automatic variables are allocated space and initialized
+to zero on entry to the function and thrown away on return.  The
+values of any variables with the same names outside the function
+are not disturbed.
+Functions may be called recursively and the automatic variables
+at each level of call are protected.
+The parameters named in a function definition are treated in
+the same way as the automatic variables of that function
+with the single exception that they are given a value
+on entry to the function.
+An example of a function definition is
+.DS
+       define a(x,y){
+               auto z
+               z = x*y
+               return(z)
+       }
+.DE
+The value of this function, when called, will be the
+product of its
+two arguments.
+.PP
+A function is called by the appearance of its name
+followed by a string of arguments enclosed in
+parentheses and separated by commas.
+The result
+is unpredictable if the wrong number of arguments is used.
+.PP
+Functions with no arguments are defined and called using
+parentheses with nothing between them: b().
+.PP
+If the function
+.ft I
+a
+.ft
+above has been defined, then the line
+.DS
+a(7,3.14)
+.DE
+would cause the result 21.98 to be printed and the line
+.DS
+x = a(a(3,4),5)
+.DE
+would cause the value of x to become 60.
+.SH
+Subscripted Variables
+.PP
+A single lower-case letter variable name
+followed by an expression in brackets is called a subscripted
+variable (an array element).
+The variable name is called the array name and the expression
+in brackets is called the subscript.
+Only one-dimensional arrays are
+permitted.  The names of arrays are permitted to
+collide with the names of simple variables and function names.
+Any fractional
+part of a subscript is discarded before use.
+Subscripts must be greater than or equal to zero and 
+less than or equal to 2047.
+.PP
+Subscripted variables may be freely used in expressions, in
+function calls, and in return statements.
+.PP
+An array name may be used as an argument to a function,
+or may be declared as automatic in
+a function definition by the use of empty brackets:
+.DS
+f(a[\|])
+define f(a[\|])
+auto a[\|]
+.DE
+When an array name is so used, the whole contents of the array
+are copied for the use of the function, and thrown away on exit
+from the function.
+Array names which refer to whole arrays cannot be used
+in any other contexts.
+.SH
+Control Statements
+.PP
+The `if', the `while', and the `for' statements
+may be used to alter the flow within programs or to cause iteration.
+The range of each of them is a statement or
+a compound statement consisting of a collection of
+statements enclosed in braces.
+They are written in the following way
+.DS
+if(relation) statement
+while(relation) statement
+for(expression1; relation; expression2) statement
+.DE
+or
+.DS
+if(relation) {statements}
+while(relation) {statements}
+for(expression1; relation; expression2) {statements}
+.DE
+.PP
+A relation in one of the control statements is an expression of the form
+.DS
+x>y
+.DE
+where  two expressions are related by one of the six relational
+operators <, >, <=, >=, ==, or !=.
+The relation ==
+stands for `equal to' and != stands for `not equal to'.
+The meaning of the remaining relational operators is
+clear.
+.PP
+BEWARE of using = instead of == in a relational.  Unfortunately,
+both of them are legal, so you will not get a diagnostic
+message, but = really will not do a comparison.
+.PP
+The `if' statement causes execution of its range
+if and only if the relation is true.
+Then control passes to the next statement in sequence.
+.PP
+The `while' statement causes execution of its range
+repeatedly as long as the relation
+is true.  The relation is tested before each execution
+of its range and if the relation
+is false, control passes to the next statement beyond the range
+of the while.
+.PP
+The `for' statement begins
+by executing `expression1'.  Then the relation is tested
+and, if true, the statements in the range of the `for' are executed.
+Then `expression2' is executed.  The relation is tested, and so on.
+The typical use of the `for' statement is for a controlled iteration,
+as in the statement
+.DS
+for(i=1; i<=10; i=i+1) i
+.DE
+which will print the integers from 1 to 10.
+Here are some examples of the use of the control statements.
+.DS
+define f(n){
+auto i, x
+x=1
+for(i=1; i<=n; i=i+1) x=x*i
+return(x)
+}
+.DE
+The line
+.DS
+       f(a)
+.DE
+will print
+.ft I
+a
+.ft
+factorial if
+.ft I
+a
+.ft
+is a positive integer.
+Here is the definition of a function which will
+compute values of the binomial coefficient
+(m and n are assumed to be positive integers).
+.DS
+define b(n,m){
+auto x, j
+x=1
+for(j=1; j<=m; j=j+1) x=x*(n\-j+1)/j
+return(x)
+}
+.DE
+The following function computes values of the exponential function
+by summing the appropriate series
+without regard for possible truncation errors:
+.DS
+scale = 20
+define e(x){
+       auto a, b, c, d, n
+       a = 1
+       b = 1
+       c = 1
+       d = 0
+       n = 1
+       while(1==1){
+               a = a*x
+               b = b*n
+               c = c + a/b
+               n = n + 1
+               if(c==d) return(c)
+               d = c
+       }
+}
+.DE
+.SH
+Some Details
+.PP
+There are some language features that every user should know
+about even if he will not use them.
+.PP
+Normally statements are typed one to a line.  It is also permissible
+to type several statements on a line separated by semicolons.
+.PP
+If an assignment statement is parenthesized, it then has
+a value and it can be used anywhere that an expression can.
+For example, the line
+.DS
+(x=y+17)
+.DE
+not only makes the indicated assignment, but also prints the
+resulting value.
+.PP
+Here is an example of a use of the value of an
+assignment statement even when it is not parenthesized.
+.DS
+x = a[i=i+1]
+.DE
+causes a value to be assigned to x and also increments i
+before it is used as a subscript.
+.PP
+The following constructs work in BC in exactly the same manner
+as they do in the C language.  Consult the appendix or the
+C manuals [2] for their exact workings.
+.DS
+.ta 2i
+x=y=z  is the same as  x=(y=z)
+x =+ y x = x+y
+x =\- y        x = x\-y
+x =* y x = x*y
+x =/ y x = x/y
+x =% y x = x%y
+x =^ y x = x^y
+x++    (x=x+1)\-1
+x\-\-  (x=x\-1)+1
+++x    x = x+1
+\-\-x  x = x\-1
+.DE
+Even if you don't intend to use the constructs,
+if you type one inadvertently, something correct but unexpected
+may happen.
+.PP
+WARNING!  In some of these constructions, spaces are
+significant.
+There is a real difference between
+x=\-y and x= \-y.
+The first replaces x by x\-y and the second by \-y.
+.SH
+Three Important Things
+.PP
+1.  To exit a BC program, type `quit'.
+.PP
+2. There is a comment convention identical to that of C and
+of PL/I.  Comments begin with `/*' and end with `*/'.
+.PP
+3. There is a library of math functions which may be obtained by
+typing at command level
+.DS
+bc \-l
+.DE
+This command will load a set of library functions
+which, at the time of writing, consists of sine (named `s'),
+cosine (`c'), arctangent (`a'), natural logarithm (`l'),
+exponential (`e') and Bessel functions of integer order (`j(n,x)').  Doubtless more functions will be added
+in time.
+The library sets the scale to 20.  You can reset it to something
+else if you like.
+The design of these mathematical library routines
+is discussed elsewhere [3].
+.PP
+If you type
+.DS
+bc file ...
+.DE
+BC will read and execute the named file or files before accepting
+commands from the keyboard.  In this way, you may load your
+favorite programs and function definitions.
+.SH
+Acknowledgement
+.PP
+The compiler is written in YACC [4]; its original
+version  was written by S. C. Johnson.
+.SH
+References
+.IP [1]
+K. Thompson and D. M. Ritchie,
+.ft I
+UNIX Programmer's Manual,
+.ft
+Bell Laboratories,
+1978.
+.IP [2]
+B. W. Kernighan and
+D. M. Ritchie,
+.ft I
+The C Programming Language,
+.ft
+Prentice-Hall, 1978.
+.IP [3]
+R. Morris,
+.ft I
+A Library of Reference Standard Mathematical Subroutines,
+.ft
+Bell Laboratories internal memorandum, 1975.
+.IP [4]
+S. C. Johnson,
+.ft I
+YACC \(em Yet Another Compiler-Compiler.
+.ft
+Bell Laboratories Computing Science Technical Report #32, 1978.
+.IP [5]
+R. Morris and L. L. Cherry,
+.ft I
+DC \- An Interactive Desk Calculator.
+.ft
+.LP
+.bp
+.ft B
+.DS C
+Appendix
+.DE
+.ft
+.NH
+Notation
+.PP
+In the following pages syntactic categories are in \fIitalics\fP;
+literals are in \fBbold\fP; material in brackets [\|] is optional.
+.NH
+Tokens
+.PP
+Tokens consist of keywords, identifiers, constants, operators,
+and separators.
+Token separators may be blanks, tabs or comments.
+Newline characters or semicolons separate statements.
+.NH 2
+Comments
+.PP
+Comments are introduced by the characters /* and terminated by
+*/.
+.NH 2
+Identifiers
+.PP
+There are three kinds of identifiers \- ordinary identifiers, array identifiers
+and function identifiers.
+All three types consist of single lower-case letters.
+Array identifiers are followed by square brackets, possibly
+enclosing an expression describing a subscript.
+Arrays are singly dimensioned and may contain up to 2048
+elements.
+Indexing begins at zero so an array may be indexed from 0 to 2047.
+Subscripts are truncated to integers.
+Function identifiers are followed by parentheses, possibly enclosing arguments.
+The three types of identifiers do not conflict;
+a program can have a variable named \fBx\fP,
+an array named \fBx\fP and a function named \fBx\fP, all of which are separate and
+distinct.
+.NH 2
+Keywords
+.PP
+The following are reserved keywords:
+.ft B
+.ta .5i 1.0i
+.nf
+       ibase   if
+       obase   break
+       scale   define
+       sqrt    auto
+       length  return
+       while   quit
+       for
+.fi
+.ft
+.NH 2
+Constants
+.PP
+Constants consist of arbitrarily long numbers
+with an optional decimal point.
+The hexadecimal digits \fBA\fP\-\fBF\fP are also recognized as digits with
+values 10\-15, respectively.
+.NH 1
+Expressions
+.PP
+The value of an expression is printed unless the main
+operator is an assignment.
+Precedence is the same as the order
+of presentation here, with highest appearing first.
+Left or right associativity, where applicable, is
+discussed with each operator.
+.bp
+.NH 2
+Primitive expressions
+.NH 3
+Named expressions
+.PP
+Named expressions are
+places where values are stored.
+Simply stated,
+named expressions are legal on the left
+side of an assignment.
+The value of a named expression is the value stored in the place named.
+.NH 4
+\fIidentifiers\fR
+.PP
+Simple identifiers are named expressions.
+They have an initial value of zero.
+.NH 4
+\fIarray-name\fP\|[\|\fIexpression\fP\|]
+.PP
+Array elements are named expressions.
+They have an initial value of zero.
+.NH 4
+\fBscale\fR, \fBibase\fR and \fBobase\fR
+.PP
+The internal registers
+\fBscale\fP, \fBibase\fP and \fBobase\fP are all named expressions.
+\fBscale\fP is the number of digits after the decimal point to be
+retained in arithmetic operations.
+\fBscale\fR has an initial value of zero.
+\fBibase\fP and \fBobase\fP are the input and output number
+radix respectively.
+Both \fBibase\fR and \fBobase\fR have initial values of 10.
+.NH 3
+Function calls
+.NH 4
+\fIfunction-name\fB\|(\fR[\fIexpression\fR\|[\fB,\|\fIexpression\|\fR.\|.\|.\|]\|]\fB)
+.PP
+A function call consists of a function name followed by parentheses
+containing a comma-separated list of
+expressions, which are the function arguments.
+A whole array passed as an argument is specified by the
+array name followed by empty square brackets.
+All function arguments are passed by
+value.
+As a result, changes made to the formal parameters have
+no effect on the actual arguments.
+If the function terminates by executing a return
+statement, the value of the function is
+the value of the expression in the parentheses of the return
+statement or is zero if no expression is provided
+or if there is no return statement.
+.NH 4
+sqrt\|(\|\fIexpression\fP\|)
+.PP
+The result is the square root of the expression.
+The result is truncated in the least significant decimal place.
+The scale of the result is
+the scale of the expression or the
+value of
+.ft B
+scale,
+.ft
+whichever is larger.
+.NH 4
+length\|(\|\fIexpression\fP\|)
+.PP
+The result is the total number of significant decimal digits in the expression.
+The scale of the result is zero.
+.NH 4
+scale\|(\|\fIexpression\fP\|)
+.PP
+The result is the scale of the expression.
+The scale of the result is zero.
+.NH 3
+Constants
+.PP
+Constants are primitive expressions.
+.NH 3
+Parentheses
+.PP
+An expression surrounded by parentheses is
+a primitive expression.
+The parentheses are used to alter the
+normal precedence.
+.NH 2
+Unary operators
+.PP
+The unary operators
+bind right to left.
+.NH 3
+\-\|\fIexpression\fP
+.PP
+The result is the negative of the expression.
+.NH 3
+++\|\fInamed-expression\fP
+.PP
+The named expression is
+incremented by one.
+The result is the value of the named expression after
+incrementing.
+.NH 3
+\-\-\|\fInamed-expression\fP
+.PP
+The named expression is
+decremented by one.
+The result is the value of the named expression after
+decrementing.
+.NH 3
+\fInamed-expression\fP\|++
+.PP
+The named expression is
+incremented by one.
+The result is the value of the named expression before
+incrementing.
+.NH 3
+\fInamed-expression\fP\|\-\-
+.PP
+The named expression is
+decremented by one.
+The result is the value of the named expression before
+decrementing.
+.NH 2
+Exponentiation operator
+.PP
+The exponentiation operator binds right to left.
+.NH 3
+\fIexpression\fP ^ \fIexpression\fP
+.PP
+The result is the first
+expression raised to the power of the
+second expression.
+The second expression must be an integer.
+If \fIa\fP
+is the scale of the left expression
+and \fIb\fP is the absolute value
+of the right expression,
+then the scale of the result is:
+.PP
+min\|(\|\fIa\(mub\fP,\|max\|(\|\fBscale\fP,\|\fIa\fP\|)\|)
+.NH 2
+Multiplicative operators
+.PP
+The operators *, /, % bind left to right.
+.NH 3
+\fIexpression\fP * \fIexpression\fP
+.PP
+The result is the product
+of the two expressions.
+If \fIa\fP and \fIb\fP are the
+scales of the two expressions,
+then the scale of the result is:
+.PP
+min\|(\|\fIa+b\fP,\|max\|(\|\fBscale\fP,\|\fIa\fP,\|\fIb\fP\|)\|)
+.NH 3
+\fIexpression\fP / \fIexpression\fP
+.PP
+The result is the quotient of the two expressions.
+The scale of the result is the value of \fBscale\fR.
+.NH 3
+\fIexpression\fP % \fIexpression\fP
+.PP
+The % operator produces the remainder of the division
+of the two expressions.
+More precisely,
+\fIa\fP%\fIb\fP is \fIa\fP\-\fIa\fP/\fIb\fP*\fIb\fP.
+.PP
+The scale of the result is the sum of the scale of
+the divisor and the value of
+.ft B
+scale
+.ft
+.NH 2
+Additive operators
+.PP
+The additive operators bind left to right.
+.NH 3
+\fIexpression\fP + \fIexpression\fP
+.PP
+The result is the sum of the two expressions.
+The scale of the result is
+the maximun of the scales of the expressions.
+.NH 3
+\fIexpression\fP \- \fIexpression\fP
+.PP
+The result is the difference of the two expressions.
+The scale of the result is the
+maximum of the scales of the expressions.
+.NH 2
+assignment operators
+.PP
+The assignment operators bind right to left.
+.NH 3
+\fInamed-expression\fP = \fIexpression\fP
+.PP
+This expression results in assigning the value of the expression
+on the right
+to the named expression on the left.
+.NH 3
+\fInamed-expression\fP =+ \fIexpression\fP
+.NH 3
+\fInamed-expression\fP =\- \fIexpression\fP
+.NH 3
+\fInamed-expression\fP =* \fIexpression\fP
+.NH 3
+\fInamed-expression\fP =/ \fIexpression\fP
+.NH 3
+\fInamed-expression\fP =% \fIexpression\fP
+.NH 3
+\fInamed-expression\fP =^ \fIexpression\fP
+.PP
+The result of the above expressions is equivalent
+to ``named expression = named expression OP expression'',
+where OP is the operator after the = sign.
+.NH 1
+Relations
+.PP
+Unlike all other operators, the relational operators
+are only valid as the object of an \fBif\fP, \fBwhile\fP,
+or inside a \fBfor\fP statement.
+.NH 2
+\fIexpression\fP < \fIexpression\fP
+.NH 2
+\fIexpression\fP > \fIexpression\fP
+.NH 2
+\fIexpression\fP <= \fIexpression\fP
+.NH 2
+\fIexpression\fP >= \fIexpression\fP
+.NH 2
+\fIexpression\fP == \fIexpression\fP
+.NH 2
+\fIexpression\fP != \fIexpression\fP
+.NH 1
+Storage classes
+.PP
+There are only two storage classes in BC, global and automatic
+(local).
+Only identifiers that are to be local to a function need be 
+declared with the \fBauto\fP command.
+The arguments to a function
+are local to the function.
+All other identifiers are assumed to be global
+and available to all functions.
+All identifiers, global and local, have initial values
+of zero.
+Identifiers declared as \fBauto\fP are allocated on entry to the function 
+and released on returning from the function.
+They therefore do not retain values between function calls.
+\fBauto\fP arrays are specified by the array name followed by empty square brackets.
+.PP
+Automatic variables in BC do not work in exactly the same way
+as in either C or PL/I.  On entry to a function, the old values of
+the names that appear as parameters and as automatic
+variables are pushed onto a stack.  
+Until return is made from the function, reference to these
+names refers only to the new values.
+.NH 1
+Statements
+.PP
+Statements must be separated by semicolon or newline.
+Except where altered by control statements, execution
+is sequential.
+.NH 2
+Expression statements
+.PP
+When a statement is an expression, unless
+the main operator is an assignment, the value
+of the expression is printed, followed by a newline character.
+.NH 2
+Compound statements
+.PP
+Statements may be grouped together and used when one statement is expected
+by surrounding them with { }.
+.NH 2
+Quoted string statements
+.PP
+"any string"
+.sp .5
+This statement prints the string inside the quotes.
+.NH 2
+If statements
+.sp .5
+\fBif\|(\|\fIrelation\fB\|)\|\fIstatement\fR
+.PP
+The substatement is executed if the relation is true.
+.NH 2
+While statements
+.sp .5
+\fBwhile\|(\|\fIrelation\fB\|)\|\fIstatement\fR
+.PP
+The statement is executed while the relation
+is true.
+The test occurs before each execution of the statement.
+.NH 2
+For statements
+.sp .5
+\fBfor\|(\|\fIexpression\fB; \fIrelation\fB; \fIexpression\fB\|)\|\fIstatement\fR
+.PP
+The for statement is the same as
+.nf
+.ft I
+       first-expression
+       \fBwhile\|(\fPrelation\|\fB) {\fP
+               statement
+               last-expression
+       }
+.ft R
+.fi
+.PP
+All three expressions must be present.
+.NH 2
+Break statements
+.sp .5
+\fBbreak\fP
+.PP
+\fBbreak\fP causes termination of a \fBfor\fP or \fBwhile\fP statement.
+.NH 2
+Auto statements
+.sp .5
+\fBauto \fIidentifier\fR\|[\|\fB,\fIidentifier\fR\|]
+.PP
+The auto statement causes the values of the identifiers to be pushed down.
+The identifiers can be ordinary identifiers or array identifiers.
+Array identifiers are specified by following the array name by empty square
+brackets.
+The auto statement must be the first statement
+in a function definition.
+.NH 2
+Define statements
+.sp .5
+.nf
+\fBdefine(\|\fR[\fIparameter\|\fR[\fB\|,\|\fIparameter\|.\|.\|.\|\fR]\|]\|\fB)\|{\fI
+       statements\|\fB}\fR
+.fi
+.PP
+The define statement defines a function.
+The parameters may
+be ordinary identifiers or array names.
+Array names must be followed by empty square brackets.
+.NH 2
+Return statements
+.sp .5
+\fBreturn\fP
+.sp .5
+\fBreturn(\fI\|expression\|\fB)\fR
+.PP
+The return statement causes termination of a function,
+popping of its auto variables, and
+specifies the result of the function.
+The first form is equivalent to \fBreturn(0)\fR.
+The result of the function is the result of the expression
+in parentheses.
+.NH 2
+Quit
+.PP
+The quit statement stops execution of a BC program and returns
+control to UNIX when it is first encountered.
+Because it is not treated as an executable statement,
+it cannot be used
+in a function definition or in an 
+.ft B
+if, for,
+.ft
+or
+.ft B
+while
+.ft
+statement.
diff --git a/doc/7thEdMan/vol2/beginners.bun b/doc/7thEdMan/vol2/beginners.bun
new file mode 100644 (file)
index 0000000..2010613
--- /dev/null
@@ -0,0 +1,2666 @@
+# To unbundle, run this file
+echo u.mac
+sed 's/.//' >u.mac <<'//GO.SYSIN DD u.mac'
+-.tr |\(bv
+-.de IT
+-.if n .ul
+-\%\&\\$3\f2\\$1\fR\&\\$2
+-..
+-.de UL
+-.lg 0
+-.if n .ul
+-\%\&\\$3\f3\\$1\fR\&\\$2
+-.lg
+-..
+-.de UC
+-\\$3\s-1\\$1\s0\\$2
+-..
+-.de P1
+-.DS I .4i
+-.nf
+-.lg 0
+-.if n .ls 1
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ps -\\n(dP
+-.if t .vs -\\n(dP
+-.nr P \\n(.s
+-.nr S \\n(.s+1
+-.nr s \\n(.s-1
+-.nr t 5*33u   \" width in 9 point CW
+-.if t .ta 1u*\\ntu 2u*\\ntu 3u*\\ntu 4u*\\ntu 5u*\\ntu 6u*\\ntu 7u*\\ntu 8u*\\ntu 9u*\\ntu 10u*\\ntu 11u*\\ntu 12u*\\ntu 13u*\\ntu 14u*\\ntu
+-.ft 3
+-.tr _\(ul
+-.tr -\-
+-.lg 0
+-..
+-.de P2
+-.ps \\n(PS
+-.vs \\n(VSp
+-.nr P \\n(PS
+-.nr S \\n(PS+1
+-.nr s \\n(PS-1
+-.ft R
+-.if n .ls 2
+-.fi
+-.DE
+-.tr --
+-.tr ''
+-.lg
+-..
+-.nr PI .2i
+//GO.SYSIN DD u.mac
+echo u0
+sed 's/.//' >u0 <<'//GO.SYSIN DD u0'
+-...TM 78-1273-8
+-...ND October 2, 1978
+-...old TM -74-1273-18, October 29, 1974
+-.RP
+-.TL
+-UNIX For Beginners \(em
+-Second Edition
+-.AU
+-Brian W. Kernighan
+-.AI
+-.MH
+-.AB
+-.PP
+-This paper is meant to help
+-new users get started on
+-the
+-.UX
+-operating system.
+-It includes:
+-.IP "\ \(bu"
+-basics needed for day-to-day use of the system \(em
+-typing commands, correcting typing mistakes, logging in and out,
+-mail, inter-terminal communication,
+-the file system, printing files,
+-redirecting I/O, pipes, and the shell.
+-.IP "\ \(bu"
+-document preparation \(em
+-a brief discussion of the major formatting programs
+-and macro packages,
+-hints on preparing documents,
+-and capsule descriptions of some supporting software.
+-.IP "\ \(bu"
+-.UC UNIX
+-programming \(em
+-using the editor, programming the shell, programming in C,
+-other languages and tools.
+-.IP "\ \(bu"
+-An annotated
+-.UC UNIX
+-bibliography.
+-.AE
+//GO.SYSIN DD u0
+echo u1
+sed 's/.//' >u1 <<'//GO.SYSIN DD u1'
+-.nr PS 9
+-.if t .nr VS 11
+-.if n .ls 2
+-.if t .2C
+-.nr PI .25i
+-.SH
+-INTRODUCTION
+-.PP
+-From the user's point of view,
+-the
+-.UC UNIX
+-operating system
+-is easy
+-to learn and use,
+-and presents few of the usual impediments
+-to getting the job done.
+-It is hard, however, for the beginner
+-to know where to start,
+-and how to make the best use 
+-of the facilities available.
+-The purpose of this introduction
+-is to help new users
+-get used to the main ideas of 
+-the
+-.UC UNIX
+-system
+-and start making effective use of it quickly.
+-.PP
+-You should have a couple of other documents with you
+-for easy reference as you read this one.
+-The most important is
+-.ul
+-The
+-.ul
+-.UC UNIX
+-.IT Programmer's
+-.IT Manual \|;
+-it's often easier to tell you to read about something
+-in the manual
+-than to repeat its contents here.
+-The other useful document is
+-.ul
+-A Tutorial Introduction to the
+-.ul
+-.UC UNIX
+-.ul
+-Text Editor,
+-which will tell you how to use the editor
+-to get text \(em
+-programs, data, documents \(em
+-into the computer.
+-.PP
+-A word of warning:
+-the
+-.UC UNIX
+-system
+-has become quite popular,
+-and there are several major variants
+-in widespread use.
+-Of course details also change with time.
+-So although the basic structure of 
+-.UC UNIX
+-and how to use it is common to all versions,
+-there will certainly be a few things
+-which are different on your system from
+-what is described here.
+-We have tried to minimize the problem,
+-but be aware of it.
+-In cases of doubt,
+-this paper describes Version 7 
+-.UC UNIX .
+-.PP
+-This paper has five sections:
+-.IP "\ \ 1."
+-Getting Started:
+-How to log in,
+-how to type,
+-what to do about mistakes in typing,
+-how to log out.
+-Some of this is dependent on which
+-system
+-you log into
+-(phone numbers, for example)
+-and what terminal you use,
+-so this section must necessarily be supplemented
+-by local information.
+-.IP "\ \ 2."
+-Day-to-day Use:
+-Things you need every day to use
+-the system
+-effectively:
+-generally useful commands;
+-the file system.
+-.IP "\ \ 3."
+-Document Preparation:
+-Preparing manu\%scripts is one of the most common uses
+-for
+-.UC UNIX
+-systems.
+-This section contains advice,
+-but not
+-extensive instructions on any
+-of the formatting tools.
+-.IP "\ \ 4."
+-Writing Programs:
+-.UC UNIX
+-is an excellent system for developing programs.
+-This section talks about some of the tools,
+-but again is not a tutorial in any of the programming languages
+-provided by the system.
+-.IP "\ \ 5."
+-A
+-.UC UNIX
+-Reading List.
+-An annotated bibliography of 
+-documents that new users should be aware of.
+-.SH
+-I.  GETTING STARTED
+-.SH
+-Logging In
+-.PP
+-You must have a 
+-.UC UNIX
+-login name, which you can get from
+-whoever administers your system.
+-You also need to know the phone number,
+-unless your system uses permanently connected terminals.
+-The
+-.UC UNIX
+-system
+-is capable of dealing with a wide variety of terminals:
+-Terminet 300's; Execuport, TI and similar
+-portables;
+-video (CRT) terminals like the HP2640, etc.;
+-high-priced graphics terminals like the Tektronix 4014;
+-plotting terminals like those from GSI and DASI;
+-and even the venerable
+-Teletype in its various forms.
+-But note:
+-.UC UNIX
+-is strongly oriented towards devices with 
+-.ul
+-lower case.
+-If your terminal produces only upper case (e.g., model 33 Teletype, some video and portable terminals),
+-life will be so difficult that you should look for another
+-terminal.
+-.PP
+-Be sure to set the switches appropriately on your device.
+-Switches that might need to be adjusted include the speed,
+-upper/lower case mode,
+-full duplex, even parity, and any others
+-that local wisdom advises.
+-Establish a connection using whatever
+-magic is needed for your terminal;
+-this may involve dialing a telephone call or merely flipping a switch.
+-In either case,
+-.UC UNIX
+-should type
+-.UL login: '' ``
+-at you.
+-If it types garbage, you may be at the wrong speed;
+-check the switches.
+-If that fails,
+-push the ``break'' or ``interrupt'' key a few times, slowly.
+-If that fails to produce a login message, consult a guru.
+-.PP
+-When you get a
+-.UL login:
+-message,
+-type your
+-login name
+-.ul
+-in lower case.
+-Follow it by a 
+-.UC RETURN ;
+-the system will not do anything until you type a
+-.UC RETURN .
+-If a password is required,
+-you will be asked for it,
+-and (if possible)
+-printing will be turned off while you type it.
+-Don't forget
+-.UC RETURN .
+-.PP
+-The culmination of your login efforts is a
+-``prompt character,''
+-a single character that indicates that
+-the system
+-is ready to accept commands from you.
+-The prompt character is usually a 
+-dollar sign
+-.UL $
+-or a
+-percent sign
+-.UL % .
+-(You may also get a message of the day just before the
+-prompt character, or a notification that you have mail.)
+-.SH
+-Typing Commands
+-.PP
+-Once you've seen the prompt character, you can type commands,
+-which are
+-requests that
+-the system
+-do something.
+-Try typing
+-.P1
+-date
+-.P2
+-followed by 
+-.UC RETURN.
+-You should get back something like
+-.P1
+-Mon Jan 16 14:17:10 EST 1978
+-.P2
+-Don't forget the
+-.UC RETURN
+-after the command,
+-or nothing will happen.
+-If you think you're being ignored,
+-type a
+-.UC RETURN ;
+-something should happen.
+-.UC RETURN
+-won't be mentioned
+-again,
+-but don't forget it \(em
+-it has to be there
+-at the end of each line.
+-.PP
+-Another command you might try is
+-.UL who ,
+-which tells you everyone who is currently logged in:
+-.P1
+-who
+-.P2
+-gives something like
+-.P1
+-.ta .5i 1i
+-mb    tty01   Jan 16    09:11
+-ski   tty05   Jan 16    09:33
+-gam   tty11   Jan 16    13:07
+-.P2
+-The time is when the user logged in;
+-``ttyxx'' is the system's idea of what terminal
+-the user is on.
+-.PP
+-If you make a mistake typing the command name,
+-and refer to a non-existent command,
+-you will be told.
+-For example, if you type
+-.P1
+-whom
+-.P2
+-you will be told 
+-.P1
+-whom: not found
+-.P2
+-Of course, if you inadvertently type the name of some other command,
+-it will run,
+-with more or less mysterious results.
+-.SH
+-Strange Terminal Behavior
+-.PP
+-Sometimes you can get into a state
+-where your terminal acts strangely.
+-For example,
+-each letter may be typed twice,
+-or the
+-.UC RETURN
+-may not cause a line feed
+-or a return to the left margin.
+-You can often fix this by logging out and logging back in.
+-Or you can read the description of the command
+-.UL stty
+-in section I of the manual.
+-To get intelligent treatment of
+-tab characters
+-(which are much used in
+-.UC UNIX )
+-if your terminal doesn't have tabs,
+-type the command
+-.P1
+-stty \-tabs
+-.P2
+-and the system will convert each tab into the right number
+-of blanks for you.
+-If your terminal does have computer-settable tabs,
+-the command
+-.UL tabs
+-will set the stops correctly for you.
+-.SH
+-Mistakes in Typing
+-.PP
+-If you make a typing mistake, and see it before
+-.UC RETURN
+-has been typed,
+-there are two ways to recover.
+-The sharp-character
+-.UL #
+-erases the last character typed;
+-in fact successive uses of
+-.UL #
+-erase characters back to
+-the beginning of the line (but not beyond).
+-So if you type badly, you can correct as you go:
+-.P1
+-dd#atte##e
+-.P2
+-is the same as
+-.UL date .
+-.PP
+-The at-sign
+-.UL @
+-erases all of the characters
+-typed so far
+-on the current input line,
+-so if the line is irretrievably fouled up, type an
+-.UL @
+-and start the line over.
+-.PP
+-What if you must enter a sharp or at-sign
+-as part of the text?
+-If you precede either
+-.UL #
+-or
+-.UL @
+-by a backslash
+-.UL \e ,
+-it loses its erase meaning.
+-So to enter a sharp or at-sign in something, type
+-.UL \e# 
+-or
+-.UL \e@ .
+-The system will always echo a newline at you after your at-sign,
+-even if preceded by a backslash.
+-Don't worry \(em
+-the at-sign has been recorded.
+-.PP
+-To erase a backslash,
+-you have to type two sharps or two at-signs, as in
+-.UL \e## .
+-The backslash is used extensively in
+-.UC UNIX
+-to indicate that the following character is in some way special.
+-.SH
+-Read-ahead
+-.PP
+-.UC UNIX
+-has full read-ahead,
+-which means that you can type as fast as you want,
+-whenever you want,
+-even when some command is typing at you.
+-If you type during output,
+-your input characters will appear intermixed with the output characters,
+-but they will be stored away
+-and interpreted in the correct order.
+-So you can type several commands one after another without
+-waiting for the first to finish or even begin.
+-.SH
+-Stopping a Program
+-.PP
+-You can stop most programs by
+-typing the character
+-.UC DEL '' ``
+-(perhaps called ``delete'' or ``rubout'' on your terminal).
+-The ``interrupt'' or ``break'' key found on most terminals
+-can also be used.
+-In a few programs, like the text editor,
+-.UC DEL
+-stops whatever the program is doing but leaves you in that program.
+-Hanging up the phone will stop most programs.
+-.SH
+-Logging Out
+-.PP
+-The easiest way to log out is to hang up the phone.
+-You can also type
+-.P1
+-login
+-.P2
+-and let someone else use the terminal you were on.
+-It is usually not sufficient just to turn off the terminal.
+-Most
+-.UC UNIX
+-systems
+-do not use a time-out mechanism, so you'll be
+-there forever unless you hang up.
+-.SH
+-Mail
+-.PP
+-When you log in, you may sometimes get the message
+-.P1
+-You have mail.
+-.P2
+-.UC UNIX
+-provides a postal system so you can
+-communicate with
+-other users of the system.
+-To read your mail,
+-type the command
+-.P1
+-mail
+-.P2
+-Your mail will be printed,
+-one message at a time,
+-most recent message first.
+-After each message,
+-.UL mail
+-waits for you to say what to do with it.
+-The two basic responses are
+-.UL d ,
+-which deletes the message,
+-and
+-.UC RETURN ,
+-which does not
+-(so it will still be there the next time you read your mailbox).
+-Other responses are described in the manual.
+-(Earlier versions of
+-.UL mail
+-do not process one message at a time,
+-but are otherwise similar.)
+-.PP
+-How do you send mail to someone else?
+-Suppose it is to go to ``joe'' (assuming ``joe'' is someone's login name).
+-The easiest way is this:
+-.P1
+-mail joe
+-.ft I
+-now type in the text of the letter
+-on as many lines as you like ...
+-After the last line of the letter
+-type the character ``control-d'',
+-that is, hold down ``control'' and type
+-a letter ``d''.
+-.P2
+-And that's it.
+-The ``control-d'' sequence, often called ``EOF'' for end-of-file, is used throughout 
+-the system
+-to mark the end of input from a terminal,
+-so you might as well get used to it.
+-.PP
+-For practice, send mail to yourself.
+-(This isn't as strange as it might sound \(em
+-mail to oneself is a handy reminder mechanism.)
+-.PP
+-There are other ways to send mail \(em
+-you can send a previously prepared letter,
+-and you can mail to a number of people all at once.
+-For more details see
+-.UL mail (1).
+-(The notation
+-.UL mail (1)
+-means the command 
+-.UL mail
+-in section 1
+-of the
+-.ul
+-.UC UNIX
+-.ul
+-.IT Programmer's
+-.IT Manual .)
+-.SH
+-Writing to other users
+-.PP
+-At some point, 
+-out of the blue will come a message
+-like
+-.P1
+-Message from joe tty07...
+-.P2
+-accompanied by a startling beep.
+-It means that Joe wants to talk to you,
+-but unless you take explicit action you won't be able to talk back.
+-To respond,
+-type the command
+-.P1
+-write joe
+-.P2
+-This establishes a two-way communication path.
+-Now whatever Joe types on his terminal will appear on yours
+-and vice versa.
+-The path is slow, rather like talking to the moon.
+-(If you are in the middle of something, you have to
+-get to a state where you can type a command.
+-Normally, whatever program you are running has to terminate or be terminated.
+-If you're editing, you can escape temporarily from the editor \(em
+-read the editor tutorial.)
+-.PP
+-A protocol is needed to keep what you type from getting
+-garbled up with what Joe types. 
+-Typically it's like this:
+-.P1
+-.tr --
+-.fi
+-.ft R
+-Joe types
+-.UL write
+-.UL smith
+-and waits.
+-.br
+-Smith types
+-.UL write
+-.UL joe
+-and waits.
+-.br
+-Joe now types his message
+-(as many lines as he likes).
+-When he's ready for a reply, he
+-signals it by typing
+-.UL (o) ,
+-which
+-stands for ``over''.
+-.br
+-Now Smith types a reply, also
+-terminated by
+-.UL (o) .
+-.br
+-This cycle repeats until
+-someone gets tired; he then
+-signals his intent to quit with
+-.UL (oo) ,
+-for ``over
+-and out''.
+-.br
+-To terminate
+-the conversation, each side must
+-type a ``control-d'' character alone
+-on a line. (``Delete'' also works.)
+-When the other person types his ``control-d'',
+-you will get the message
+-.UL EOF
+-on your terminal.
+-.P2
+-.PP
+-If you write to someone who isn't logged in,
+-or who doesn't want to be disturbed,
+-you'll be told.
+-If the target is logged in but doesn't answer
+-after a decent interval,
+-simply type ``control-d''.
+-.SH
+-On-line Manual
+-.PP
+-The 
+-.ul
+-.UC UNIX
+-.ul
+-Programmer's Manual
+-is typically kept on-line.
+-If you get stuck on something,
+-and can't find an expert to assist you,
+-you can print on your terminal some manual section that might help.
+-This is also useful for getting the most up-to-date
+-information on a command.
+-To print a manual section, type
+-``man command-name''.
+-Thus to read up on the 
+-.UL who
+-command,
+-type
+-.P1
+-man who
+-.P2
+-and, of course,
+-.P1
+-man man
+-.P2
+-tells all about the
+-.UL man
+-command.
+-.SH
+-Computer Aided Instruction
+-.PP
+-Your
+-.UC UNIX
+-system may have available
+-a program called
+-.UL learn ,
+-which provides computer aided instruction on
+-the file system and basic commands,
+-the editor,
+-document preparation,
+-and even C programming.
+-Try typing the command
+-.P1
+-learn
+-.P2
+-If 
+-.UL learn
+-exists on your system,
+-it will tell you what to do from there.
+//GO.SYSIN DD u1
+echo u2
+sed 's/.//' >u2 <<'//GO.SYSIN DD u2'
+-.SH
+-II.  DAY-TO-DAY USE
+-.SH
+-Creating Files \(em The Editor
+-.PP
+-If you have to type a paper or a letter or a program,
+-how do you get the information stored in the machine?
+-Most of these tasks are done with
+-the
+-.UC UNIX
+-``text editor''
+-.UL ed .
+-Since
+-.UL ed
+-is thoroughly documented in 
+-.UL ed (1) 
+-and explained in
+-.ul
+-A Tutorial Introduction to the UNIX Text Editor,
+-we won't spend any time here describing how to use it.
+-All we want it for right now is to make some
+-.ul
+-files.
+-(A file is just a collection of information stored in the machine,
+-a simplistic but adequate definition.)
+-.PP
+-To create a file 
+-called
+-.UL junk
+-with some text in it, do the following:
+-.P1
+-.ta .65i
+-ed junk       \fR(invokes the text editor)\f3
+-a     \fR(command to ``ed'', to add text)\f3
+-.ft I
+-now type in
+-whatever text you want ...
+-.ft 3
+-\&.   \fR(signals the end of adding text)\f3
+-.P2
+-The ``\f3.\fR'' that signals the end of adding text must be
+-at the beginning of a line by itself.
+-Don't forget it,
+-for until it is typed,
+-no other
+-.UL ed
+-commands will be recognized \(em
+-everything you type will be treated as text to be added.
+-.PP
+-At this point you can do various editing operations
+-on the text you typed in, such as correcting spelling mistakes,
+-rearranging paragraphs and the like.
+-Finally, you must write the information you have typed
+-into a file with the editor command
+-.UL w :
+-.P1
+-w
+-.P2
+-.UL ed
+-will respond with the number of characters it wrote
+-into the file 
+-.UL junk .
+-.PP
+-Until the
+-.UL w
+-command,
+-nothing is stored permanently,
+-so if you hang up and go home
+-the information is lost.\(dg
+-.FS
+-\(dg This is not strictly true \(em
+-if you hang up while editing, the data you were
+-working on is saved in a file called
+-.UL ed.hup ,
+-which you can continue with at your next session.
+-.FE
+-But after
+-.UL w
+-the information is there permanently;
+-you can re-access it any time by typing
+-.P1
+-ed junk
+-.P2
+-Type a
+-.UL q
+-command
+-to quit the editor.
+-(If you try to quit without writing,
+-.UL ed
+-will print a
+-.UL ?
+-to remind you.
+-A second
+-.UL q
+-gets you out regardless.)
+-.PP
+-Now create a second file called 
+-.UL temp
+-in the same manner.
+-You should now have two files,
+-.UL junk
+-and
+-.UL temp .
+-.SH
+-What files are out there?
+-.PP
+-The
+-.UL ls
+-(for ``list'') command lists the names
+-(not contents)
+-of any of the files that
+-.UC UNIX
+-knows about.
+-If you type
+-.P1
+-ls
+-.P2
+-the response will be
+-.P1
+-junk
+-temp
+-.P2
+-which are indeed the two files just created.
+-The names are sorted into alphabetical order automatically,
+-but other variations are possible.
+-For example,
+-the command
+-.P1
+-ls -t
+-.P2
+-causes the files to be listed in the order in which they were last changed,
+-most recent first.
+-The
+-.UL \-l
+-option gives a ``long'' listing:
+-.P1
+-ls -l
+-.P2
+-will produce something like
+-.P1
+--rw-rw-rw-  1 bwk   41 Jul 22 2:56 junk
+--rw-rw-rw-  1 bwk   78 Jul 22 2:57 temp
+-.P2
+-The date and time are of the last change to the file.
+-The 41 and 78 are the number of characters
+-(which should agree with the numbers you got from
+-.UL ed ).
+-.UL bwk
+-is the owner of the file, that is, the person
+-who created it.
+-The
+-.UL \-rw\-rw\-rw\- 
+-tells who has permission to read and write the file,
+-in this case everyone.
+-.PP
+-Options can be combined:
+-.UL ls\ \-lt
+-gives the same thing as
+-.UL ls\ \-l ,
+-but sorted into time order.
+-You can also name the files you're interested in,
+-and 
+-.UL ls
+-will list the information about them only.
+-More details can be found in 
+-.UL ls (1).
+-.PP
+-The use of optional arguments that begin with a minus sign,
+-like
+-.UL \-t
+-and
+-.UL \-lt ,
+-is a common convention for
+-.UC UNIX
+-programs.
+-In general, if a program accepts such optional arguments,
+-they precede any filename arguments.
+-It is also vital that you separate the various arguments with spaces:
+-.UL ls\-l
+-is not the same as
+-.UL ls\ \ \-l .
+-.SH
+-Printing Files
+-.PP
+-Now that you've got a file of text,
+-how do you print it so people can look at it?
+-There are a host of programs that do that,
+-probably more than are needed.
+-.PP
+-One simple thing is to use the editor,
+-since printing is often done just before making changes anyway.
+-You can say
+-.P1
+-ed junk
+-1,$p
+-.P2
+-.UL ed
+-will reply with the count of the characters in 
+-.UL junk
+-and then print all the lines in the file.
+-After you learn how to use the editor,
+-you can be selective about the parts you print.
+-.PP
+-There are times when it's not feasible to use the editor for printing.
+-For example, there is a limit on how big a file
+-.UL ed
+-can handle
+-(several thousand lines).
+-Secondly, 
+-it
+-will only print one file at a time,
+-and sometimes you want to print several, one after another.
+-So here are a couple of alternatives.
+-.PP
+-First is
+-.UL cat ,
+-the simplest of all the printing programs.
+-.UL cat
+-simply prints on the terminal the contents of all the files
+-named in a list.
+-Thus
+-.P1
+-cat junk
+-.P2
+-prints one file, and
+-.P1
+-cat junk temp
+-.P2
+-prints two.
+-The files are simply concatenated (hence the name
+-.UL cat '') ``
+-onto the terminal.
+-.PP
+-.UL pr
+-produces formatted printouts of files.
+-As with 
+-.UL cat ,
+-.UL pr
+-prints all the files named in a list.
+-The difference is that it produces 
+-headings with date, time, page number and file name
+-at the top of each page,
+-and
+-extra lines to skip over the fold in the paper.
+-Thus,
+-.P1
+-pr junk temp
+-.P2
+-will print
+-.UL junk
+-neatly,
+-then skip to the top of a new page and print
+-.UL temp
+-neatly.
+-.PP
+-.UL pr
+-can also produce multi-column output:
+-.P1
+-pr -3 junk 
+-.P2
+-prints
+-.UL junk
+-in 3-column format.
+-You can use any reasonable number in place of ``3''
+-and 
+-.UL pr
+-will do its best.
+-.UL pr
+-has other capabilities as well;
+-see
+-.UL pr (1).
+-.PP
+-It should be noted that
+-.UL pr
+-is
+-.ul
+-not
+-a formatting program in the sense of shuffling lines around
+-and justifying margins.
+-The true formatters are
+-.UL nroff
+-and
+-.UL troff ,
+-which we will get to in the section on document preparation.
+-.PP
+-There are also programs that print files
+-on a high-speed printer.
+-Look in your manual under
+-.UL opr
+-and
+-.UL lpr .
+-Which to use depends on
+-what equipment is attached to your machine.
+-.SH
+-Shuffling Files About
+-.PP
+-Now that you have some files in the file system
+-and some experience in printing them,
+-you can try bigger things.
+-For example,
+-you can move a file from one place to another
+-(which amounts to giving it a new name),
+-like this:
+-.P1
+-mv junk precious
+-.P2
+-This means that what used to be ``junk'' is now ``precious''.
+-If you do an
+-.UL ls
+-command now,
+-you will get
+-.P1
+-precious
+-temp
+-.P2
+-Beware that if you move a file to another one
+-that already exists,
+-the already existing contents are lost forever.
+-.PP
+-If you want
+-to make a
+-.ul
+-copy
+-of a file (that is, to have two versions of something),
+-you can use the 
+-.UL cp
+-command:
+-.P1
+-cp precious temp1
+-.P2
+-makes a duplicate copy of 
+-.UL precious
+-in
+-.UL temp1 .
+-.PP
+-Finally, when you get tired of creating and moving
+-files,
+-there is a command to remove files from the file system,
+-called
+-.UL rm .
+-.P1
+-rm temp temp1
+-.P2
+-will remove both of the files named.
+-.PP
+-You will get a warning message if one of the named files wasn't there,
+-but otherwise
+-.UL rm ,
+-like most
+-.UC UNIX
+-commands,
+-does its work silently.
+-There is no prompting or chatter,
+-and error messages are occasionally curt.
+-This terseness is sometimes disconcerting
+-to new\%comers,
+-but experienced users find it desirable.
+-.SH
+-What's in a Filename
+-.PP
+-So far we have used filenames without ever saying what's
+-a legal name,
+-so it's time for a couple of rules.
+-First, filenames are limited to 14 characters,
+-which is enough to be descriptive.
+-Second, although you can use almost any character
+-in a filename,
+-common sense says you should stick to ones that are visible,
+-and that you should probably avoid characters that might be used
+-with other meanings.
+-We have already seen, for example,
+-that in the
+-.UL ls
+-command,
+-.UL ls\ \-t
+-means to list in time order.
+-So if you had a file whose name
+-was
+-.UL \-t ,
+-you would have a tough time listing it by name.
+-Besides the minus sign, there are other characters which
+-have special meaning.
+-To avoid pitfalls,
+-you would do well to 
+-use only letters, numbers and the period
+-until you're familiar with the situation.
+-.PP
+-On to some more positive suggestions.
+-Suppose you're typing a large document
+-like a book.
+-Logically this divides into many small pieces,
+-like chapters and perhaps sections.
+-Physically it must be divided too,
+-for 
+-.UL ed
+-will not handle really big files.
+-Thus you should type the document as a number of files.
+-You might have a separate file for each chapter,
+-called
+-.P1
+-chap1
+-chap2
+-.ft R
+-etc...
+-.P2
+-Or, if each chapter were broken into several files, you might have
+-.P1
+-chap1.1
+-chap1.2
+-chap1.3
+-\&...
+-chap2.1
+-chap2.2
+-\&...
+-.P2
+-You can now tell at a glance where a particular file fits into the whole.
+-.PP
+-There are advantages to a systematic naming convention which are not obvious
+-to the novice
+-.UC UNIX 
+-user.
+-What if you wanted to print the whole book?
+-You could say
+-.P1
+-pr chap1.1 chap1.2 chap1.3 ......
+-.P2
+-but you would get tired pretty fast, and would probably even make mistakes.
+-Fortunately, there is a shortcut.
+-You can say
+-.P1
+-pr chap*
+-.P2
+-The
+-.UL *
+-means ``anything at all,''
+-so this translates into ``print all files
+-whose names begin with 
+-.UL chap '',
+-listed in alphabetical order.
+-.PP
+-This shorthand notation
+-is not a property of the
+-.UL pr
+-command, by the way.
+-It is system-wide, a service of the program
+-that interprets commands
+-(the ``shell,''
+-.UL sh (1)).
+-Using that fact, you can see how to list the names of the files in the book:
+-.P1
+-ls chap*
+-.P2
+-produces
+-.P1
+-chap1.1
+-chap1.2
+-chap1.3
+-\&...
+-.P2
+-The
+-.UL *
+-is not limited to the last position in a filename \(em
+-it can be anywhere
+-and can occur several times.
+-Thus
+-.P1
+-rm *junk* *temp*
+-.P2
+-removes all files that contain
+-.UL junk
+-or
+-.UL temp
+-as any part of their name.
+-As a special case,
+-.UL *
+-by itself matches every filename,
+-so
+-.P1
+-pr *
+-.P2
+-prints all your files
+-(alphabetical order),
+-and
+-.P1
+-rm *
+-.P2
+-removes
+-.ul
+-all files.
+-(You had better be
+-.IT  very 
+-sure that's what you wanted to say!)
+-.PP
+-The
+-.UL *
+-is not 
+-the only pattern-matching feature available.
+-Suppose you want to print only chapters 1 through 4 and 9.
+-Then you can say
+-.P1
+-pr chap[12349]*
+-.P2
+-The
+-.UL [...]
+-means to match any of the characters inside the brackets.
+-A range of consecutive letters or digits can be abbreviated,
+-so you can also do this 
+-with
+-.P1
+-pr chap[1-49]*
+-.P2
+-Letters can also be used within brackets:
+-.UL [a\-z]
+-matches any character in the range
+-.UL a
+-through
+-.UL z .
+-.PP
+-The
+-.UL ?
+-pattern matches any single character,
+-so
+-.P1
+-ls ?
+-.P2
+-lists all files which have single-character names,
+-and
+-.P1
+-ls -l chap?.1
+-.P2
+-lists information about the first file of each chapter
+-.UL chap1.1 \&, (
+-.UL chap2.1 ,
+-etc.).
+-.PP
+-Of these niceties,
+-.UL *
+-is certainly the most useful,
+-and you should get used to it.
+-The others are frills, but worth knowing.
+-.PP
+-If you should ever have to turn off the special meaning
+-of
+-.UL * ,
+-.UL ? ,
+-etc.,
+-enclose the entire argument in single quotes,
+-as in
+-.P1
+-ls \(fm?\(fm
+-.P2
+-We'll see some more examples of this shortly.
+-.SH
+-What's in a Filename, Continued
+-.PP
+-When you first made that file called
+-.UL junk ,
+-how did 
+-the system
+-know that there wasn't another
+-.UL junk
+-somewhere else,
+-especially since the person in the next office is also
+-reading this tutorial?
+-The answer is that generally each user 
+-has a private
+-.IT directory ,
+-which contains only the files that belong to him.
+-When you log in, you are ``in'' your directory.
+-Unless you take special action,
+-when you create a new file,
+-it is made in the directory that you are currently in;
+-this is most often your own directory,
+-and thus the file is unrelated to any other file of the same name
+-that might exist in someone else's directory.
+-.PP
+-The set of all files
+-is organized into a (usually big) tree,
+-with your files located several branches into the tree.
+-It is possible for you to ``walk'' around this tree,
+-and to find any file in the system, by starting at the root
+-of the tree and walking along the proper set of branches.
+-Conversely, you can start where you are and walk toward the root.
+-.PP
+-Let's try the latter first.
+-The basic tools is the command
+-.UL pwd
+-(``print working directory''),
+-which prints the name of the directory you are currently in.
+-.PP
+-Although the details will vary according to the system you are on,
+-if you give the
+-command
+-.UL pwd ,
+-it will print something like
+-.P1
+-/usr/your\(hyname
+-.P2
+-This says that you are currently in the directory
+-.UL your-name ,
+-which is in turn in the directory
+-.UL /usr ,
+-which is in turn in the root directory
+-called by convention just
+-.UL / .
+-(Even if it's not called
+-.UL /usr
+-on your system,
+-you will get something analogous.
+-Make the corresponding changes and read on.)
+-.PP
+-If you now type
+-.P1
+-ls /usr/your\(hyname
+-.P2
+-you should get exactly the same list of file names
+-as you get from a plain
+-.UL ls  :
+-with no arguments,
+-.UL ls
+-lists the contents of the current directory;
+-given the name of a directory,
+-it lists the contents of that directory.
+-.PP
+-Next, try
+-.P1
+-ls /usr
+-.P2
+-This should print a long series of names,
+-among which is your own login name
+-.UL your-name .
+-On many systems, 
+-.UL usr
+-is a directory that contains the directories
+-of all the normal users of the system,
+-like you.
+-.PP
+-The next step is to try
+-.P1
+-ls /
+-.P2
+-You should get a response something like this
+-(although again the details may be different):
+-.P1
+-bin
+-dev
+-etc
+-lib
+-tmp
+-usr
+-.P2
+-This is a collection of the basic directories of files
+-that
+-the system
+-knows about;
+-we are at the root of the tree.
+-.PP
+-Now try
+-.P1
+-cat /usr/your\(hyname/junk
+-.P2
+-(if
+-.UL junk
+-is still around in your directory).
+-The name
+-.P1
+-/usr/your\(hyname/junk
+-.P2
+-is called the
+-.UL pathname
+-of the file that
+-you normally think of as ``junk''.
+-``Pathname'' has an obvious meaning:
+-it represents the full name of the path you have to follow from the root
+-through the tree of directories to get to a particular file.
+-It is a universal rule in
+-the
+-.UC UNIX
+-system
+-that anywhere you can use an ordinary filename,
+-you can use a pathname.
+-.PP
+-Here is a picture which may make this clearer:
+-.P1 1
+-.ft R
+-.if t .vs 9p
+-.if t .tr /\(sl
+-.if t .tr ||
+-.ce 100
+-(root)
+-/ | \e
+-/  |  \e
+-/   |   \e
+-  bin    etc    usr    dev   tmp 
+-/ | \e   / | \e   / | \e   / | \e   / | \e
+-/  |  \e
+-/   |   \e
+-adam  eve   mary
+-/        /   \e        \e
+-             /     \e       junk
+-junk temp
+-.ce 0
+-.br
+-.tr //
+-.P2
+-.LP
+-Notice that Mary's
+-.UL junk
+-is unrelated to Eve's.
+-.PP
+-This isn't too exciting if all the files of interest are in your own
+-directory, but if you work with someone else
+-or on several projects concurrently,
+-it becomes handy indeed.
+-For example, your friends can print your book by saying
+-.P1
+-pr /usr/your\(hyname/chap*
+-.P2
+-Similarly, you can find out what files your neighbor has
+-by saying
+-.P1
+-ls /usr/neighbor\(hyname
+-.P2
+-or make your own copy of one of his files by
+-.P1
+-cp /usr/your\(hyneighbor/his\(hyfile yourfile
+-.P2
+-.PP
+-If your neighbor doesn't want you poking around in his files,
+-or vice versa,
+-privacy can be arranged.
+-Each file and directory has read-write-execute permissions for the owner,
+-a group, and everyone else,
+-which can be set
+-to control access.
+-See
+-.UL ls (1)
+-and
+-.UL chmod (1)
+-for details.
+-As a matter of observed fact,
+-most users most of the time find openness of more
+-benefit than privacy.
+-.PP
+-As a final experiment with pathnames, try
+-.P1
+-ls /bin /usr/bin
+-.P2
+-Do some of the names look familiar?
+-When you run a program, by typing its name after the prompt character,
+-the system simply looks for a file of that name.
+-It normally looks first in your directory
+-(where it typically doesn't find it),
+-then in
+-.UL /bin
+-and finally in
+-.UL /usr/bin .
+-There is nothing magic about commands like
+-.UL cat
+-or
+-.UL ls ,
+-except that they have been collected into a couple of places to be easy to find and administer.
+-.PP
+-What if you work regularly with someone else on common information
+-in his directory?
+-You could just log in as your friend each time you want to,
+-but you can also say
+-``I want to work on his files instead of my own''.
+-This is done by changing the directory that you are
+-currently in:
+-.P1
+-cd /usr/your\(hyfriend
+-.P2
+-(On some systems,
+-.UL cd
+-is spelled
+-.UL chdir .)
+-Now when you use a filename in something like
+-.UL cat
+-or
+-.UL pr ,
+-it refers to the file in your friend's directory.
+-Changing directories doesn't affect any permissions associated
+-with a file \(em
+-if you couldn't access a file from your own directory,
+-changing to another directory won't alter that fact.
+-Of course,
+-if you forget what directory you're in, type
+-.P1
+-pwd
+-.P2
+-to find out.
+-.PP
+-It is usually convenient to arrange your own files
+-so that all the files related to one thing are in a directory separate
+-from other projects.
+-For example, when you write your book, you might want to keep all the text
+-in a directory called
+-.UL book .
+-So make one with
+-.P1
+-mkdir book
+-.P2
+-then go to it with
+-.P1
+-cd book
+-.P2
+-then start typing chapters.
+-The book is now found in (presumably)
+-.P1
+-/usr/your\(hyname/book
+-.P2
+-To remove the directory
+-.UL book ,
+-type
+-.P1
+-rm book/*
+-rmdir book
+-.P2
+-The first command removes all files from the directory;
+-the second
+-removes the empty directory.
+-.PP
+-You can go up one level in the tree of files 
+-by saying
+-.P1
+-cd ..
+-.P2
+-.UL .. '' ``
+-is the name of the parent of whatever directory you are currently in.
+-For completeness,
+-.UL . '' ``
+-is an alternate name
+-for the directory you are in.
+-.SH
+-Using Files instead of the Terminal
+-.PP
+-Most of the commands we have seen so far produce output
+-on the terminal;
+-some, like the editor, also take their input from the terminal.
+-It is universal in
+-.UC UNIX
+-systems
+-that the terminal can be replaced by a file
+-for either or both of input and output.
+-As one example,
+-.P1
+-ls
+-.P2
+-makes a list of files on your terminal.
+-But if you say
+-.P1
+-ls >filelist
+-.P2
+-a list of your files will be placed in the file
+-.UL filelist
+-(which
+-will be created if it doesn't already exist,
+-or overwritten if it does).
+-The symbol
+-.UL >
+-means ``put the output on the following file,
+-rather than on the terminal.''
+-Nothing is produced on the terminal.
+-As another example, you could combine
+-several files into one by capturing the output of
+-.UL cat
+-in a file:
+-.P1
+-cat f1 f2 f3 >temp
+-.P2
+-.PP
+-The symbol
+-.UL >>
+-operates very much like
+-.UL >
+-does,
+-except that it means
+-``add to the end of.''
+-That is,
+-.P1
+-cat f1 f2 f3 >>temp
+-.P2
+-means to concatenate
+-.UL f1 ,
+-.UL f2 
+-and
+-.UL f3
+-to the end of whatever is already in
+-.UL temp ,
+-instead of overwriting the existing contents.
+-As with
+-.UL > ,
+-if 
+-.UL temp
+-doesn't exist, it will be created for you.
+-.PP
+-In a similar way, the symbol
+-.UL <
+-means to take the input
+-for a program from the following file,
+-instead of from the terminal.
+-Thus, you could make up a script of commonly used editing commands
+-and put them into a file called
+-.UL script .
+-Then you can run the script on a file by saying
+-.P1
+-ed file <script
+-.P2
+-As another example, you can use
+-.UL ed
+-to prepare a letter in file
+-.UL let ,
+-then send it to several people with
+-.P1
+-mail adam eve mary joe <let
+-.P2
+-.SH
+-Pipes
+-.PP
+-One of the novel contributions of
+-the
+-.UC UNIX
+-system
+-is the idea of a
+-.ul
+-pipe.
+-A pipe is simply a way to connect the output of one program
+-to the input of another program,
+-so the two run as a sequence of processes \(em
+-a pipeline.
+-.PP
+-For example,
+-.P1
+-pr f g h
+-.P2
+-will print the files
+-.UL f ,
+-.UL g ,
+-and
+-.UL h ,
+-beginning each on a new page.
+-Suppose you want
+-them run together instead.
+-You could say
+-.P1
+-cat f g h >temp
+-pr <temp
+-rm temp
+-.P2
+-but this is more work than necessary.
+-Clearly what we want is to take the output of
+-.UL cat
+-and
+-connect it to the input of
+-.UL pr .
+-So let us use a pipe:
+-.P1
+-cat f g h | pr
+-.P2
+-The vertical bar 
+-.UL |
+-means to
+-take the output from
+-.UL cat ,
+-which would normally have gone to the terminal,
+-and put it into
+-.UL pr
+-to be neatly formatted.
+-.PP
+-There are many other examples of pipes.
+-For example,
+-.P1
+-ls | pr -3
+-.P2
+-prints a list of your files in three columns.
+-The program
+-.UL wc
+-counts the number of lines, words and characters in
+-its input, and as we saw earlier,
+-.UL who
+-prints a list of currently-logged on people,
+-one per line.
+-Thus
+-.P1
+-who | wc
+-.P2
+-tells how many people are logged on.
+-And of course
+-.P1
+-ls | wc
+-.P2
+-counts your files.
+-.PP
+-Any program
+-that reads from the terminal
+-can read from a pipe instead;
+-any program that writes on the terminal can drive
+-a pipe.
+-You can have as many elements in a pipeline as you wish.
+-.PP
+-Many
+-.UC UNIX
+-programs are written so that they will take their input from one or more files
+-if file arguments are given;
+-if no arguments are given they will read from the terminal,
+-and thus can be used in pipelines.
+-.UL pr
+-is one example:
+-.P1
+-pr -3 a b c
+-.P2
+-prints files
+-.UL a ,
+-.UL b
+-and
+-.UL c
+-in order in three columns.
+-But in
+-.P1
+-cat a b c | pr -3
+-.P2
+-.UL pr
+-prints the information coming down the pipeline,
+-still in
+-three columns.
+-.SH
+-The Shell
+-.PP
+-We have already mentioned once or twice the mysterious
+-``shell,''
+-which is in fact
+-.UL sh (1).
+-The shell is the program that interprets what you type as
+-commands and arguments.
+-It also looks after translating
+-.UL * ,
+-etc.,
+-into lists of filenames,
+-and
+-.UL < ,
+-.UL > ,
+-and
+-.UL |
+-into changes of input and output streams.
+-.PP
+-The shell has other capabilities too.
+-For example, you can run two programs with one command line
+-by separating the commands with a semicolon;
+-the shell recognizes the semicolon and
+-breaks the line into two commands.
+-Thus
+-.P1
+-date; who
+-.P2
+-does both commands before returning with a prompt character.
+-.PP
+-You can also have more than one program running
+-.ul
+-simultaneously
+-if you wish.
+-For example, if you are doing something time-consuming,
+-like the editor script
+-of an earlier section,
+-and you don't want to wait around for the results before starting something else,
+-you can say
+-.P1
+-ed file <script &
+-.P2
+-The ampersand at the end of a command line
+-says ``start this command running,
+-then take further commands from the terminal immediately,''
+-that is,
+-don't wait for it to complete.
+-Thus the script will begin,
+-but you can do something else at the same time.
+-Of course, to keep the output from interfering
+-with what you're doing on the terminal,
+-it would be better to say
+-.P1
+-ed file <script >script.out &
+-.P2
+-which saves the output lines in a file
+-called
+-.UL script.out .
+-.PP
+-When you initiate a command with
+-.UL & ,
+-the system
+-replies with a number
+-called the process number,
+-which identifies the command in case you later want
+-to stop it.
+-If you do, you can say
+-.P1
+-kill process\(hynumber
+-.P2
+-If you forget the process number,
+-the command
+-.UL ps
+-will tell you about everything you have running.
+-(If you are desperate,
+-.UL kill\ 0
+-will kill all your processes.)
+-And if you're curious about other people,
+-.UL ps\ a
+-will tell you about
+-.ul
+-all
+-programs that are currently running.
+-.PP
+-You can say
+-.P1 1
+-(command\(hy1; command\(hy2; command\(hy3) &
+-.P2
+-to start three commands in the background,
+-or you can start a background pipeline with
+-.P1
+-command\(hy1 | command\(hy2 &
+-.P2
+-.PP
+-Just as you can tell the editor
+-or some similar program to take its input
+-from a file instead of from the terminal,
+-you can tell the shell to read a file
+-to get commands.
+-(Why not? The shell, after all, is just a program,
+-albeit a clever one.)
+-For instance, suppose you want to set tabs on
+-your terminal, and find out the date
+-and who's on the system every time you log in.
+-Then you can put the three necessary commands
+-.UL tabs , (
+-.UL date ,
+-.UL who )
+-into a file, let's call it
+-.UL startup ,
+-and then run it with
+-.P1
+-sh startup
+-.P2
+-This says to run the shell with the file
+-.UL startup
+-as input.
+-The effect is as if you had typed 
+-the contents of
+-.UL startup
+-on the terminal.
+-.PP
+-If this is to be a regular thing,
+-you can eliminate the 
+-need to type
+-.UL sh :
+-simply type, once only, the command
+-.P1
+-chmod +x startup
+-.P2
+-and thereafter you need only say
+-.P1
+-startup
+-.P2
+-to run the sequence of commands.
+-The
+-.UL chmod (1)
+-command marks the file executable;
+-the shell recognizes this and runs it as a sequence of commands.
+-.PP
+-If you want 
+-.UL startup
+-to run automatically every time you log in,
+-create a file in your login directory called
+-.UL .profile ,
+-and place in it the line
+-.UL startup .
+-When the shell first gains control when you log in,
+-it looks for the 
+-.UL .profile
+-file and does whatever commands it finds in it.
+-We'll get back to the shell in the section
+-on programming.
+//GO.SYSIN DD u2
+echo u3
+sed 's/.//' >u3 <<'//GO.SYSIN DD u3'
+-.sp
+-.SH
+-III. DOCUMENT PREPARATION
+-.PP
+-.UC UNIX
+-systems are used extensively for document preparation.
+-There are two major 
+-formatting
+-programs,
+-that is,
+-programs that produce a text with
+-justified right margins, automatic page numbering and titling,
+-automatic hyphenation,
+-and the like.
+-.UL nroff
+-is designed to produce output on terminals and
+-line-printers.
+-.UL troff
+-(pronounced ``tee-roff'')
+-instead drives a phototypesetter,
+-which produces very high quality output
+-on photographic paper.
+-This paper was formatted with
+-.UL troff .
+-.SH
+-Formatting Packages
+-.PP
+-The basic idea of
+-.UL nroff 
+-and 
+-.UL troff
+-is that the text to be formatted contains within it
+-``formatting commands'' that indicate in detail
+-how the formatted text is to look.
+-For example, there might be commands that specify how long
+-lines are, whether to use single or double spacing,
+-and what running titles to use on each page.
+-.PP
+-Because
+-.UL nroff
+-and
+-.UL troff
+-are relatively hard to learn to use effectively,
+-several
+-``packages'' of canned formatting requests are available
+-to let you specify
+-paragraphs, running titles, footnotes, multi-column output,
+-and so on, with little effort
+-and without having to learn
+-.UL nroff
+-and
+-.UL troff .
+-These packages take a modest effort to learn,
+-but the rewards for using them are so great
+-that it is time well spent.
+-.PP
+-In this section,
+-we will provide a hasty look at the ``manuscript'' 
+-package known as
+-.UL \-ms .
+-Formatting requests typically consist of a period and two upper-case letters,
+-such as
+-.UL .TL ,
+-which is used to introduce a title,
+-or
+-.UL .PP
+-to begin a new paragraph.
+-.PP
+-A document is typed so it looks something like this:
+-.P1
+-\&.TL
+-title of document
+-\&.AU
+-author name
+-\&.SH
+-section heading
+-\&.PP
+-paragraph ...
+-\&.PP
+-another paragraph ...
+-\&.SH
+-another section heading
+-\&.PP
+-etc.
+-.P2
+-The lines that begin with a period are the formatting requests.
+-For example,
+-.UL .PP
+-calls for starting a new paragraph.
+-The precise meaning of
+-.UL .PP
+-depends on what output device is being used
+-(typesetter or terminal, for instance),
+-and on what publication the document will appear in.
+-For example,
+-.UL \-ms
+-normally assumes that a paragraph is preceded by a space
+-(one line in
+-.UL nroff ,
+-\(12 line in
+-.UL troff ),
+-and the first word is indented.
+-These rules can be changed if you like,
+-but they are changed by changing the interpretation
+-of
+-.UL .PP ,
+-not by re-typing the document.
+-.PP
+-To actually produce a document in standard format
+-using
+-.UL \-ms ,
+-use the command
+-.P1
+-troff -ms files ...
+-.P2
+-for the typesetter, and
+-.P1
+-nroff -ms files ...
+-.P2
+-for a terminal.
+-The
+-.UL \-ms
+-argument tells
+-.UL troff
+-and
+-.UL nroff
+-to use the manuscript package of formatting requests.
+-.PP
+-There are several similar packages;
+-check with a local expert to determine which ones
+-are in common use on your machine.
+-.SH
+-Supporting Tools
+-.PP
+-In addition to the basic formatters,
+-there is
+-a host of supporting programs
+-that help with document preparation.
+-The list in the next few paragraphs
+-is far from complete,
+-so browse through the manual
+-and check with people around you for other possibilities.
+-.PP
+-.UL eqn
+-and
+-.UL neqn
+-let you integrate mathematics
+-into the text of a document,
+-in an easy-to-learn language that closely resembles the way
+-you would speak it aloud.
+-For example, the
+-.UL eqn
+-input
+-.P1
+-sum from i=0 to n x sub i ~=~ pi over 2
+-.P2
+-produces the output
+-.EQ
+-sum from i=0 to n x sub i ~=~ pi over 2
+-.EN
+-.PP
+-The program
+-.UL tbl
+-provides an analogous service for preparing tabular material;
+-it does all the computations necessary to align complicated columns
+-with elements of varying widths.
+-.PP
+-.UL refer
+-prepares bibliographic citations from a data base,
+-in whatever style is defined by the formatting package.
+-It looks after all the details of numbering references in sequence,
+-filling in page and volume numbers,
+-getting the author's initials and the journal name right,
+-and so on.
+-.PP
+-.UL spell
+-and
+-.UL typo
+-detect possible spelling mistakes in a document.
+-.UL spell
+-works by comparing the words in your document
+-to a dictionary,
+-printing those that are not in the dictionary.
+-It knows enough about English spelling to detect plurals and the like,
+-so it does a very good job.
+-.UL typo
+-looks for words which are ``unusual'',
+-and prints those.
+-Spelling mistakes tend to be more unusual,
+-and thus show up early when the most unusual words
+-are printed first.
+-.PP
+-.UL grep
+-looks through a set of files for lines
+-that contain a particular text pattern 
+-(rather like the editor's context search does,
+-but on a bunch of files).
+-For example,
+-.P1
+-grep \(fming$\(fm chap*
+-.P2
+-will find all lines that end with
+-the letters
+-.UL ing
+-in the files
+-.UL chap* .
+-(It is almost always a good practice to put single quotes around
+-the pattern you're searching for,
+-in case it contains characters like
+-.UL *
+-or
+-.UL $
+-that have a special meaning to the shell.)
+-.UL grep
+-is often useful for finding out in which of a set of files
+-the misspelled words detected by
+-.UL spell
+-are actually located.
+-.PP
+-.UL diff
+-prints a list of the differences between
+-two files,
+-so you can compare
+-two versions of something automatically
+-(which certainly beats proofreading by hand).
+-.PP
+-.UL wc
+-counts the words, lines and characters in a set of files.
+-.UL tr
+-translates characters into other characters;
+-for example it will convert upper to lower case and vice versa.
+-This translates upper into lower:
+-.P1
+-tr A-Z a-z <input >output
+-.P2
+-.PP
+-.UL sort
+-sorts files in a variety of ways;
+-.UL cref
+-makes cross-references;
+-.UL ptx
+-makes a permuted index
+-(keyword-in-context listing).
+-.UL sed
+-provides many of the editing facilities
+-of
+-.UL ed ,
+-but can apply them to arbitrarily long inputs.
+-.UL awk
+-provides the ability to do both pattern matching and numeric computations,
+-and to conveniently process fields within lines.
+-These programs are for more advanced users,
+-and they are not limited to document preparation.
+-Put them on your list of things to learn about.
+-.PP
+-Most of these programs are either independently documented
+-(like
+-.UL eqn
+-and
+-.UL tbl ),
+-or are sufficiently simple that the description in
+-the
+-.ul 2
+-.UC UNIX
+-Programmer's Manual
+-is adequate explanation.
+-.SH
+-Hints for Preparing Documents
+-.PP
+-Most documents go through several versions (always more than you expected) before they
+-are finally finished.
+-Accordingly, you should do whatever possible to make
+-the job of changing them easy.
+-.PP
+-First, when you do the purely mechanical operations of typing,
+-type so that subsequent editing will be easy.
+-Start each sentence on a new line.
+-Make lines short,
+-and break lines at natural places,
+-such as after commas and semicolons,
+-rather than randomly.
+-Since most people change documents by rewriting phrases
+-and adding, deleting and rearranging sentences,
+-these precautions simplify any editing
+-you have to do later.
+-.PP
+-Keep the individual files of a document down
+-to modest size,
+-perhaps ten to fifteen thousand characters.
+-Larger files edit more slowly,
+-and of course if you make a dumb mistake
+-it's better to have clobbered a small file than a big one.
+-Split into files at natural boundaries in the document,
+-for the same reasons that you start each sentence
+-on a new line.
+-.PP
+-The second aspect of making change easy
+-is to not commit yourself to formatting details too early.
+-One of the advantages of formatting packages like
+-.UL \-ms
+-is that they permit you to delay decisions
+-to the last possible moment.
+-Indeed,
+-until a document is printed,
+-it is not even decided whether it will be typeset
+-or put on a line printer.
+-.PP
+-As a rule of thumb, for all but the most trivial jobs,
+-you should type a document in terms of a set of requests
+-like
+-.UL .PP ,
+-and then define them appropriately,
+-either by using one of the canned packages
+-(the better way)
+-or by defining your own
+-.UL nroff
+-and
+-.UL troff
+-commands.
+-As long as you have entered the text in some systematic way,
+-it can always be cleaned up and re-formatted
+-by a judicious combination of
+-editing commands and request definitions.
+//GO.SYSIN DD u3
+echo u4
+sed 's/.//' >u4 <<'//GO.SYSIN DD u4'
+-.SH
+-IV.  PROGRAMMING
+-.PP
+-There will be no attempt made to teach any of
+-the programming languages available
+-but a few words of advice are in order.
+-One of the reasons why the
+-.UC UNIX
+-system is a productive programming environment
+-is that there is already a rich set of tools available,
+-and facilities like pipes, I/O redirection,
+-and the capabilities of the shell
+-often make it possible to do a job
+-by pasting together programs that already exist
+-instead of writing from scratch.
+-.SH
+-The Shell
+-.PP
+-The pipe mechanism lets you fabricate quite complicated operations
+-out of spare parts that already exist.
+-For example,
+-the first draft of the
+-.UL  spell 
+-program was (roughly)
+-.P1
+-.ta .6i 1.2i
+-cat ...       \f2collect the files\f3
+-| tr ...      \f2put each word on a new line\f3
+-| tr ...      \f2delete punctuation, etc.\f3
+-| sort        \f2into dictionary order\f3
+-| uniq        \f2discard duplicates\f3
+-| comm        \f2print words in text\f3
+-      \f2  but not in dictionary\f3
+-.P2
+-More pieces have been added subsequently,
+-but this goes a long way
+-for such a small effort.
+-.PP
+-The editor can be made to do things that would normally
+-require special programs on other systems.
+-For example, to list the first and last lines of each of a
+-set of files, such as a book,
+-you could laboriously type
+-.P1
+-ed
+-e chap1.1
+-1p
+-$p
+-e chap1.2
+-1p
+-$p
+-.ft R
+-etc.
+-.P2
+-But you can do the job much more easily.
+-One way is to type
+-.P1
+-ls chap* >temp
+-.P2
+-to get the list of filenames into a file.
+-Then edit this file to make the necessary
+-series of editing commands
+-(using the global commands of
+-.UL ed ),
+-and write it into
+-.UL script .
+-Now the command
+-.P1
+-ed <script
+-.P2
+-will produce
+-the same output as the laborious hand typing.
+-Alternately
+-(and more easily),
+-you can use the fact that the shell will perform loops,
+-repeating a set of commands over and over again
+-for a set of arguments:
+-.P1
+-for i in chap*
+-do
+-      ed $i <script
+-done
+-.P2
+-This sets the shell variable
+-.UL i
+-to each file name in turn,
+-then does the command.
+-You can type this command at the terminal,
+-or put it in a file for later execution.
+-.SH
+-Programming the Shell
+-.PP
+-An option often overlooked by newcomers
+-is that the shell is itself a programming language,
+-with variables,
+-control flow
+-.UL if-else , (
+-.UL while ,
+-.UL for ,
+-.UL case ),
+-subroutines,
+-and interrupt handling.
+-Since
+-there are
+-many building-block programs,
+-you can sometimes avoid writing a new program
+-merely by piecing together some of the building blocks
+-with shell command files.
+-.PP
+-We will not go into any details here;
+-examples and rules can be found in
+-.ul
+-An Introduction to the
+-.ul
+-.UC UNIX
+-.IT Shell ,
+-by S. R. Bourne.
+-.SH
+-Programming in C
+-.PP
+-If you are undertaking anything substantial,
+-C is the only reasonable choice of programming language:
+-everything in
+-the
+-.UC UNIX
+-system
+-is tuned to it.
+-The
+-system
+-itself
+-is written in C,
+-as are most of the programs that run on it.
+-It is also a easy language to use
+-once you get started.
+-C is introduced and fully described in
+-.ul
+-The C Programming Language
+-by
+-B. W. Kernighan and D. M. Ritchie
+-(Prentice-Hall, 1978).
+-Several sections of the manual
+-describe the system interfaces, that is,
+-how you do I/O
+-and similar functions.
+-Read
+-.ul
+-UNIX Programming
+-for more complicated things.
+-.PP
+-Most input and output in C is best handled with the 
+-standard I/O library,
+-which provides a set of I/O functions
+-that exist in compatible form on most machines
+-that have C compilers.
+-In general, it's wisest to confine the system interactions
+-in a program to the facilities provided by this library.
+-.PP
+-C programs that don't depend too much on special features of 
+-.UC UNIX
+-(such as pipes)
+-can be moved to other computers that have C compilers.
+-The list of such machines grows daily;
+-in addition to the original
+-.UC PDP -11,
+-it currently includes
+-at least
+-Honeywell 6000,
+-IBM 370,
+-Interdata 8/32,
+-Data General Nova and Eclipse,
+-HP 2100,
+-Harris /7,
+-VAX 11/780,
+-SEL 86,
+-and
+-Zilog Z80.
+-Calls to the standard I/O library will work on all of these machines.
+-.PP
+-There are a number of supporting programs that go with C.
+-.UL lint
+-checks C programs for potential portability problems,
+-and detects errors such as mismatched argument types
+-and uninitialized variables.
+-.PP
+-For larger programs
+-(anything whose source is on more than one file)
+-.UL make
+-allows you to specify the dependencies among the source files
+-and the processing steps needed to make a new version;
+-it then checks the times that the pieces were last changed
+-and does the minimal amount of recompiling
+-to create a consistent updated version.
+-.PP
+-The debugger
+-.UL adb
+-is useful for digging through the dead bodies
+-of C programs,
+-but is rather hard to learn to use effectively.
+-The most effective debugging tool is still
+-careful thought, coupled with judiciously placed
+-print statements.
+-.PP
+-The C compiler provides a limited instrumentation service,
+-so you can find out
+-where programs spend their time and what parts are worth optimizing.
+-Compile the routines with the
+-.UL \-p
+-option;
+-after the test run, use
+-.UL prof
+-to print an execution profile.
+-The command
+-.UL time
+-will give you the gross run-time statistics
+-of a program, but they are not super accurate or reproducible.
+-.SH
+-Other Languages
+-.PP
+-If you 
+-.ul
+-have
+-to use Fortran,
+-there are two possibilities.
+-You might consider
+-Ratfor,
+-which gives you the decent control structures
+-and free-form input that characterize C,
+-yet lets you write code that
+-is still portable to other environments.
+-Bear in mind that
+-.UC UNIX
+-Fortran
+-tends to produce large and relatively slow-running
+-programs.
+-Furthermore, supporting software like
+-.UL adb ,
+-.UL prof ,
+-etc., are all virtually useless with Fortran programs.
+-There may also be a Fortran 77 compiler on your system.
+-If so,
+-this is a viable alternative to 
+-Ratfor,
+-and has the non-trivial advantage that it is compatible with C
+-and related programs.
+-(The Ratfor processor
+-and C tools
+-can be used with Fortran 77 too.)
+-.PP
+-If your application requires you to translate
+-a language into a set of actions or another language,
+-you are in effect building a compiler,
+-though probably a small one.
+-In that case,
+-you should be using
+-the
+-.UL yacc
+-compiler-compiler, 
+-which helps you develop a compiler quickly.
+-The
+-.UL lex
+-lexical analyzer generator does the same job
+-for the simpler languages that can be expressed as regular expressions.
+-It can be used by itself,
+-or as a front end to recognize inputs for a
+-.UL yacc -based
+-program.
+-Both
+-.UL yacc
+-and
+-.UL lex
+-require some sophistication to use,
+-but the initial effort of learning them
+-can be repaid many times over in programs
+-that are easy to change later on.
+-.PP
+-Most
+-.UC UNIX
+-systems also make available other languages,
+-such as
+-Algol 68, APL, Basic, Lisp, Pascal, and Snobol.
+-Whether these are useful depends largely on the local environment:
+-if someone cares about the language and has worked on it,
+-it may be in good shape.
+-If not, the odds are strong that it
+-will be more trouble than it's worth.
+//GO.SYSIN DD u4
+echo u5
+sed 's/.//' >u5 <<'//GO.SYSIN DD u5'
+-.SH
+-V.  UNIX READING LIST
+-.SH
+-General:
+-.LP
+-K. L. Thompson and D. M. Ritchie,
+-.IT The
+-.ul
+-.UC UNIX
+-.ul
+-Programmer's Manual,
+-Bell Laboratories, 1978.
+-Lists commands,
+-system routines and interfaces, file formats,
+-and some of the maintenance procedures.
+-You can't live without this,
+-although you will probably only need to read section 1.
+-.LP
+-.ul
+-Documents for Use with the
+-.ul
+-.UC UNIX
+-.ul
+-Time-sharing System.
+-Volume 2 of the Programmer's Manual.
+-This contains more extensive descriptions
+-of major commands,
+-and tutorials and reference manuals.
+-All of the papers listed below are in it,
+-as are descriptions of most of the programs
+-mentioned above.
+-.LP
+-D. M. Ritchie and K. L. Thompson,
+-``The
+-.UC UNIX
+-Time-sharing System,''
+-CACM, July 1974.
+-An overview of the system,
+-for people interested in operating systems.
+-Worth reading by anyone who programs.
+-Contains a remarkable number of one-sentence observations
+-on how to do things right.
+-.LP
+-The Bell System Technical Journal
+-(BSTJ)
+-Special Issue on 
+-.UC UNIX ,
+-July/August, 1978,
+-contains many papers describing recent developments,
+-and some retrospective material.
+-.LP
+-The 2nd International Conference on Software Engineering
+-(October, 1976)
+-contains several 
+-papers describing the use of the
+-Programmer's Workbench
+-.UC PWB ) (
+-version of
+-.UC UNIX .
+-.SH
+-Document Preparation:
+-.LP
+-B. W. Kernighan,
+-``A Tutorial Introduction to the
+-.UC UNIX
+-Text Editor''
+-and
+-``Advanced Editing on
+-.UC UNIX ,''
+-Bell Laboratories, 1978.
+-Beginners need the introduction;
+-the advanced material will help you get the most
+-out of the editor.
+-.LP
+-M. E. Lesk,
+-``Typing Documents on
+-.UC UNIX ,''
+-Bell Laboratories, 1978.
+-Describes the
+-.UL \-ms
+-macro package, which isolates the novice
+-from the vagaries of
+-.UL nroff
+-and
+-.UL troff ,
+-and takes care of most formatting situations.
+-If this specific package isn't available on your system,
+-something similar probably is.
+-The most likely alternative is the
+-.UC PWB/UNIX
+-macro package
+-.UL \-mm ;
+-see your local guru if you use
+-.UC PWB/UNIX .
+-.LP
+-B. W. Kernighan and L. L. Cherry,
+-``A System for Typesetting Mathematics,''
+-Bell Laboratories Computing Science Tech. Rep. 17.
+-.LP
+-M. E. Lesk,
+-``Tbl \(em A Program to Format Tables,''
+-Bell Laboratories CSTR 49, 1976.
+-.LP
+-J. F. Ossanna, Jr.,
+-``NROFF/TROFF User's Manual,''
+-Bell Laboratories CSTR 54, 1976.
+-.UL troff
+-is the basic formatter used by
+-.UL \-ms ,
+-.UL eqn
+-and
+-.UL tbl .
+-The reference manual is indispensable
+-if you are going to write or maintain these
+-or similar programs.
+-But start with:
+-.LP
+-B. W. Kernighan,
+-``A TROFF Tutorial,''
+-Bell Laboratories, 1976.
+-An attempt to unravel the intricacies of
+-.UL troff .
+-.SH
+-Programming:
+-.LP
+-B. W. Kernighan and D. M. Ritchie,
+-.ul
+-The C Programming Language,
+-Prentice-Hall, 1978.
+-Contains a tutorial introduction,
+-complete discussions of all language features,
+-and the reference manual.
+-.LP
+-B. W. Kernighan and D. M. Ritchie,
+-.UC UNIX \& ``
+-Programming,''
+-Bell Laboratories, 1978.
+-Describes how to interface with the system from C programs:
+-I/O calls, signals, processes.
+-.LP
+-S. R. Bourne,
+-``An Introduction to the
+-.UC UNIX
+-Shell,''
+-Bell Laboratories, 1978.
+-An introduction and reference manual for the Version 7 shell.
+-Mandatory reading if you intend to make effective use
+-of the programming power
+-of this shell.
+-.LP
+-S. C. Johnson,
+-``Yacc \(em Yet Another Compiler-Compiler,''
+-Bell Laboratories CSTR 32, 1978.
+-.LP
+-M. E. Lesk,
+-``Lex \(em A Lexical Analyzer Generator,''
+-Bell Laboratories CSTR 39, 1975.
+-.LP
+-S. C. Johnson,
+-``Lint, a C Program Checker,''
+-Bell Laboratories CSTR 65, 1977.
+-.LP
+-S. I. Feldman,
+-``MAKE \(em A Program for Maintaining Computer Programs,''
+-Bell Laboratories CSTR 57, 1977.
+-.LP
+-J. F. Maranzano and S. R. Bourne,
+-``A Tutorial Introduction to ADB,''
+-Bell Laboratories CSTR 62, 1977.
+-An introduction to a powerful but complex debugging tool.
+-.LP
+-S. I. Feldman and P. J. Weinberger,
+-``A Portable Fortran 77 Compiler,''
+-Bell Laboratories, 1978.
+-A full Fortran 77 for
+-.UC UNIX
+-systems.
+//GO.SYSIN DD u5
diff --git a/doc/7thEdMan/vol2/cacm.bun b/doc/7thEdMan/vol2/cacm.bun
new file mode 100644 (file)
index 0000000..d85107c
--- /dev/null
@@ -0,0 +1,2038 @@
+# To unbundle, run this file
+echo p.mac
+sed 's/.//' >p.mac <<'//GO.SYSIN DD p.mac'
+-.de P1
+-.DS
+-..
+-.de P2
+-.DE
+-..
+-.de UL
+-.lg 0
+-.if n .ul
+-\%\&\\$3\f3\\$1\fR\&\\$2
+-.lg
+-..
+-.de UC
+-\&\\$3\s-1\\$1\\s0\&\\$2
+-..
+-.de IT
+-.lg 0
+-.if n .ul
+-\%\&\\$3\f2\\$1\fR\&\\$2
+-.lg
+-..
+-.de SP
+-.sp \\$1
+-..
+//GO.SYSIN DD p.mac
+echo p1
+sed 's/.//' >p1 <<'//GO.SYSIN DD p1'
+-.ds n \s+2
+-.hw above-mentioned
+-.ds s \s-2
+-.ds m \v'-.3'.\v'.3'
+-.TL
+-The UNIX
+-Time-Sharing System\f1\s10\v'-.2n'*\v'.2n'\s0\fP
+-.AU
+-D. M. Ritchie and K. Thompson
+-.AB
+-.FS
+-* Copyright 1974,
+-Association for Computing Machinery, Inc.,
+-reprinted by permission.
+-This is a revised version of an article
+-that appeared in Communications of the \*sACM\*n,
+-.IT 17 ,
+-No. 7 (July 1974), pp. 365-375.
+-That article was a
+-revised version of a paper presented
+-at the Fourth \*sACM\*n Symposium on Operating
+-Systems Principles,
+-\*sIBM\*n Thomas J. Watson Research Center,
+-Yorktown Heights,
+-New York,
+-October 15-17, 1973.
+-.FE
+-.UX
+-is a general-purpose, multi-user, interactive
+-operating system for the larger Digital Equipment Corporation
+-\*sPDP\*n-11 and
+-the Interdata 8/32 computers.
+-It offers a number of features
+-seldom found even in larger operating
+-systems, including
+-.IP i
+-A hierarchical file system incorporating
+-demountable volumes,
+-.IP ii
+-Compatible file, device, and inter-process I/O,
+-.IP iii
+-The ability to initiate asynchronous processes,
+-.IP iv
+-System command language selectable on a per-user basis,
+-.IP v
+-Over 100 subsystems including a dozen languages,
+-.IP vi
+-High degree of portability.
+-.LP
+-This paper discusses the nature
+-and implementation of the file system
+-and of the user command interface.
+-.AE
+-.NH
+-INTRODUCTION
+-.PP
+-There have been four versions of
+-the
+-.UX
+-time-sharing system.
+-.hy 12
+-The earliest (circa 1969-70) ran on
+-the Digital Equipment Corporation \*sPDP\*n-7 and -9 computers.
+-The second version ran on the unprotected
+-\*sPDP\*n-11/20 computer.
+-The third incorporated multiprogramming and ran
+-on the \*sPDP\*n-11/34, /40, /45, /60, and /70 computers;
+-it is the one described in the previously published version
+-of this paper, and is also the most widely used today.
+-.hy 14
+-This paper describes only the
+-fourth, current
+-system that runs on the \*sPDP\*n-11/70 and the
+-Interdata 8/32 computers.
+-In fact, the differences among the various systems is
+-rather small;
+-most of the revisions made to the originally published version of this
+-paper,
+-aside from those concerned with style,
+-had to do with details of the implementation of the file system.
+-.PP
+-Since
+-\*sPDP\*n-11
+-.UX
+-became operational
+-in February, 1971,
+-over 600 installations have been put into service.
+-Most of them are engaged in applications such as
+-computer science education,
+-the preparation and formatting of documents
+-and other textual material,
+-the collection and processing of trouble data
+-from various switching machines within the Bell System,
+-and recording and checking telephone service
+-orders.
+-Our own installation is used mainly for research
+-in operating systems, languages,
+-computer networks,
+-and other topics in computer science, and also for
+-document preparation.
+-.PP
+-Perhaps the most important achievement of
+-.UX
+-is to demonstrate
+-that
+-a powerful operating system for interactive use
+-need not be expensive either in equipment or in human
+-effort:
+-it
+-can run on hardware costing as little as $40,000, and
+-less than two man-years were spent on the main system
+-software.
+-We hope, however, that users find
+-that the
+-most important characteristics of the system
+-are its simplicity, elegance, and ease of use.
+-.PP
+-Besides the operating system proper, some major programs
+-available under
+-.UX
+-are
+-.DS
+-.nf
+-C compiler
+-Text editor based on \*sQED\*n
+-.[
+-qed lampson
+-.]
+-Assembler, linking loader, symbolic debugger
+-Phototypesetting and equation setting programs
+-.[
+-cherry kernighan typesetting mathematics cacm
+-.]
+-.[
+-kernighan lesk ossanna document preparation bstj
+-%Q This issue
+-.]
+-.fi
+-.in +3n
+-.ll -5n
+-.ti -3n
+-Dozens of languages including
+-Fortran 77, Basic, Snobol, \*sAPL\*n, Algol 68, M6, \*sTMG\*n, Pascal
+-.in
+-.ll
+-.DE
+-There is a host of maintenance, utility, recreation and novelty programs,
+-all written locally.
+-The
+-.UX
+-user community, which numbers in the thousands,
+-has contributed many more programs and languages.
+-It is worth noting that the system is totally self-supporting.
+-All
+-.UX
+-software is maintained on
+-the
+-system;
+-likewise, this paper and all other
+-documents
+-in this issue
+-were generated and formatted by the
+-.UX
+-editor and text formatting
+-programs.
+-.SH
+-II. HARDWARE AND SOFTWARE ENVIRONMENT
+-.PP
+-The \*sPDP\*n-11/70 on which the Research
+-.UX
+-system is installed is a 16-bit
+-word (8-bit byte) computer with 768K bytes of core memory;
+-the system kernel
+-occupies 90K bytes
+-about equally divided between code
+-and data tables.
+-This system, however, includes a very large number of
+-device drivers
+-and enjoys a generous allotment
+-of space for I/O buffers and system tables;
+-a minimal system capable of running the software
+-mentioned above can
+-require as little as 96K bytes
+-of core altogether.
+-There are even larger installations;
+-see the description of the
+-\*sPWB/UNIX\*n systems,
+-.[
+-dolotta mashey workbench software engineering
+-.]
+-.[
+-dolotta haight mashey workbench bstj
+-%Q This issue
+-.]
+-for example.
+-There are also much smaller, though somewhat restricted,
+-versions of the system.
+-.[
+-lycklama microprocessor bstj
+-%Q This issue
+-.]
+-.PP
+-Our own \*sPDP\*n-11 has two
+-200-Mb moving-head disks
+-for file system storage and swapping.
+-There are 20 variable-speed
+-communications interfaces
+-attached to 300- and 1200-baud data sets,
+-and an additional 12 communication lines
+-hard-wired to 9600-baud terminals and
+-satellite computers.
+-There are also several 2400- and 4800-baud
+-synchronous communication interfaces
+-used for machine-to-machine file transfer.
+-Finally, there is a variety
+-of miscellaneous
+-devices including
+-nine-track magnetic tape,
+-a line printer,
+-a voice synthesizer,
+-a phototypesetter,
+-a digital switching network,
+-and a chess machine.
+-.PP
+-The preponderance of
+-.UX
+-software is written in the
+-abovementioned C language.
+-.[
+-c programming language kernighan ritchie prentice-hall
+-.]
+-Early versions of the operating system were written in assembly language,
+-but during the summer of 1973, it was rewritten in C.
+-The size of the new system was about one-third greater
+-than that of the old.
+-Since the new system not only became much easier to
+-understand and to modify but also
+-included
+-many functional improvements,
+-including multiprogramming and the ability to
+-share reentrant code among several user programs,
+-we consider this increase in size quite acceptable.
+-.SH
+-III. THE FILE SYSTEM
+-.PP
+-The most important role of
+-the system
+-is to provide
+-a file system.
+-From the point of view of the user, there
+-are three kinds of files: ordinary disk files,
+-directories, and special files.
+-.SH
+-3.1 Ordinary files
+-.PP
+-A file
+-contains whatever information the user places on it,
+-for example, symbolic or binary
+-(object) programs.
+-No particular structuring is expected by the system.
+-A file of text consists simply of a string
+-of characters, with lines demarcated by the newline character.
+-Binary programs are sequences of words as
+-they will appear in core memory when the program
+-starts executing.
+-A few user programs manipulate files with more
+-structure;
+-for example, the assembler generates, and the loader
+-expects, an object file in a particular format.
+-However,
+-the structure of files is controlled by
+-the programs that use them, not by the system.
+-.SH
+-3.2 Directories
+-.PP
+-Directories provide
+-the mapping between the names of files
+-and the files themselves, and thus
+-induce a structure on the file system as a whole.
+-Each user has a directory of his own files;
+-he may also create subdirectories to contain
+-groups of files conveniently treated together.
+-A directory behaves exactly like an ordinary file except that it
+-cannot be written on by unprivileged programs, so that the system
+-controls the contents of directories.
+-However, anyone with
+-appropriate permission may read a directory just like any other file.
+-.PP
+-The system maintains several directories
+-for its own use.
+-One of these is the
+-.UL root
+-directory.
+-All files in the system can be found by tracing
+-a path through a chain of directories
+-until the desired file is reached.
+-The starting point for such searches is often the
+-.UL root .
+-Other system directories contain all the programs provided
+-for general use; that is, all the
+-.IT commands .
+-As will be seen, however, it is by no means necessary
+-that a program reside in one of these directories for it
+-to be executed.
+-.PP
+-Files are named by sequences of 14 or
+-fewer characters.
+-When the name of a file is specified to the
+-system, it may be in the form of a
+-.IT path
+-.IT name ,
+-which
+-is a sequence of directory names separated by slashes, ``/\^'',
+-and ending in a file name.
+-If the sequence begins with a slash, the search begins in the
+-root directory.
+-The name
+-.UL /alpha/beta/gamma
+-causes the system to search
+-the root for directory
+-.UL alpha ,
+-then to search
+-.UL alpha
+-for
+-.UL beta ,
+-finally to find
+-.UL gamma
+-in
+-.UL beta .
+-.UL \&gamma
+-may be an ordinary file, a directory, or a special
+-file.
+-As a limiting case, the name ``/\^'' refers to the root itself.
+-.PP
+-A path name not starting with ``/\^'' causes the system to begin the
+-search in the user's current directory.
+-Thus, the name
+-.UL alpha/beta
+-specifies the file named
+-.UL beta
+-in
+-subdirectory
+-.UL alpha
+-of the current
+-directory.
+-The simplest kind of name, for example,
+-.UL alpha ,
+-refers to a file that itself is found in the current
+-directory.
+-As another limiting case, the null file name refers
+-to the current directory.
+-.PP
+-The same non-directory file may appear in several directories under
+-possibly different names.
+-This feature is called
+-.IT linking ;
+-a directory entry for a file is sometimes called a link.
+-The
+-.UX
+-system
+-differs from other systems in which linking is permitted
+-in that all links to a file have equal status.
+-That is, a file does not exist within a particular directory;
+-the directory entry for a file consists merely
+-of its name and a pointer to the information actually
+-describing the file.
+-Thus a file exists independently of any
+-directory entry, although in practice a file is made to
+-disappear along with the last link to it.
+-.PP
+-Each directory always has at least two entries.
+-The name
+-``\|\fB.\|\fP'' in each directory refers to the directory itself.
+-Thus a program
+-may read the current directory under the name ``\fB\|.\|\fP'' without knowing
+-its complete path name.
+-The name ``\fB\|.\|.\|\fP'' by convention refers to the parent of the
+-directory in which it appears, that is, to the directory in which
+-it was created.
+-.PP
+-The directory structure is constrained to have the form
+-of a rooted tree.
+-Except for the special entries ``\|\fB\|.\|\fP'' and ``\fB\|.\|.\|\fP'', each directory
+-must appear as an entry in exactly one other directory, which is its
+-parent.
+-The reason for this is to simplify the writing of programs
+-that visit subtrees of the directory structure, and more
+-important, to avoid the separation of portions of the hierarchy.
+-If arbitrary links to directories were permitted, it would
+-be quite difficult to detect when the last connection from
+-the root to a directory was severed.
+-.SH
+-3.3 Special files
+-.PP
+-Special files constitute the most unusual feature of the
+-.UX
+-file system.
+-Each supported I/O device
+-is associated with at least one such file.
+-Special files are read and written just like ordinary
+-disk files, but requests to read or write result in activation of the associated
+-device.
+-An entry for each special file resides in directory
+-.UL /dev ,
+-although a link may be made to one of these files
+-just as it may to an ordinary file.
+-Thus, for example,
+-to write on a magnetic tape
+-one may write on the file
+-.UL /dev/mt .
+-Special files exist for each communication line, each disk,
+-each tape drive,
+-and for physical main memory.
+-Of course,
+-the active disks
+-and the memory special file are protected from
+-indiscriminate access.
+-.PP
+-There is a threefold advantage in treating
+-I/O devices this way:
+-file and device I/O
+-are as similar as possible;
+-file and device names have the same
+-syntax and meaning, so that
+-a program expecting a file name
+-as a parameter can be passed a device
+-name; finally,
+-special files are subject to the same
+-protection mechanism as regular files.
+-.SH
+-3.4 Removable file systems
+-.PP
+-Although the root of the file system is always stored on the same
+-device,
+-it is not necessary that the entire file system hierarchy
+-reside on this device.
+-There is a
+-.UL mount
+-system request with two arguments:
+-the name of an existing ordinary file, and the name of a special
+-file whose associated
+-storage volume (e.g., a disk pack) should have the structure
+-of an independent file system
+-containing its own directory hierarchy.
+-The effect of
+-.UL mount
+-is to cause
+-references to the heretofore ordinary file
+-to refer instead to the root directory
+-of the file system on the removable volume.
+-In effect,
+-.UL mount
+-replaces a leaf of the hierarchy tree (the ordinary file)
+-by a whole new subtree (the hierarchy stored on the
+-removable volume).
+-After the
+-.UL mount ,
+-there is virtually no distinction
+-between files on the removable volume and those in the
+-permanent file system.
+-In our installation, for example,
+-the root directory resides
+-on a small partition of one of
+-our disk drives,
+-while the other drive,
+-which contains the user's files,
+-is mounted by the system initialization
+-sequence.
+-A mountable file system is generated by
+-writing on its corresponding special file.
+-A utility program is available to create
+-an empty file system,
+-or one may simply copy an existing file system.
+-.PP
+-There is only one exception to the rule of identical
+-treatment of files on different devices:
+-no link may exist between one file system hierarchy and
+-another.
+-This restriction is enforced so as to avoid
+-the elaborate bookkeeping
+-that would otherwise be required to assure removal of the links
+-whenever the removable volume is dismounted.
+-.SH
+-3.5 Protection
+-.PP
+-Although the access control scheme
+-is quite simple, it has some unusual features.
+-Each user of the system is assigned a unique
+-user identification number.
+-When a file is created, it is marked with
+-the user \*sID\*n of its owner.
+-Also given for new files
+-is a set of ten protection bits.
+-Nine of these specify
+-independently read, write, and execute permission
+-for the
+-owner of the file,
+-for other members of his group,
+-and for all remaining users.
+-.PP
+-If the tenth bit is on, the system
+-will temporarily change the user identification
+-(hereafter, user \*sID\*n)
+-of the current user to that of the creator of the file whenever
+-the file is executed as a program.
+-This change in user \*sID\*n is effective only
+-during the execution of the program that calls for it.
+-The set-user-\*sID\*n feature provides
+-for privileged programs that may use files
+-inaccessible to other users.
+-For example, a program may keep an accounting file
+-that should neither be read nor changed
+-except by the program itself.
+-If the set-user-\*sID\*n bit is on for the
+-program, it may access the file although
+-this access might be forbidden to other programs
+-invoked by the given program's user.
+-Since the actual user \*sID\*n
+-of the invoker of any program
+-is always available,
+-set-user-\*sID\*n programs
+-may take any measures desired to satisfy themselves
+-as to their invoker's credentials.
+-This mechanism is used to allow users to execute
+-the carefully written
+-commands
+-that call privileged system entries.
+-For example, there is a system entry
+-invokable only by the ``super-user'' (below)
+-that creates
+-an empty directory.
+-As indicated above, directories are expected to
+-have entries for ``\fB\|.\|\fP'' and ``\fB\|.\|.\|\fP''.
+-The command which creates a directory
+-is owned by the super-user
+-and has the set-user-\*sID\*n bit set.
+-After it checks its invoker's authorization to
+-create the specified directory,
+-it creates it and makes the entries
+-for ``\fB\|.\|\fP'' and ``\fB\|.\|.\|\fP''.
+-.PP
+-Because anyone may set the set-user-\*sID\*n
+-bit on one of his own files,
+-this mechanism is generally
+-available without administrative intervention.
+-For example,
+-this protection scheme easily solves the \*sMOO\*n
+-accounting problem posed by ``Aleph-null.''
+-.[
+-aleph null software practice
+-.]
+-.PP
+-The system recognizes one particular user \*sID\*n (that of the ``super-user'') as
+-exempt from the usual constraints on file access; thus (for example),
+-programs may be written to dump and reload the file
+-system without
+-unwanted interference from the protection
+-system.
+//GO.SYSIN DD p1
+echo p2
+sed 's/.//' >p2 <<'//GO.SYSIN DD p2'
+-.SH
+-3.6 I/O calls
+-.PP
+-The system calls to do I/O are designed to eliminate
+-the differences between the various devices and styles of
+-access.
+-There is no distinction between ``random''
+-and ``sequential'' I/O, nor is any logical record size imposed
+-by the system.
+-The size of an ordinary file is determined
+-by the number of bytes written on it;
+-no predetermination of the size of a file is necessary
+-or possible.
+-.PP
+-To illustrate the essentials of I/O,
+-some of the basic calls are
+-summarized below
+-in an anonymous language that will
+-indicate the required parameters without getting into the
+-underlying
+-complexities.
+-Each call to the system may potentially result in an error
+-return, which for simplicity is not represented
+-in the calling sequence.
+-.PP
+-To read or write a file assumed to exist already, it must
+-be opened by the following call:
+-.P1
+-filep = open\|(\|name, flag\|)
+-.P2
+-where
+-.UL name
+-indicates the name of the file.
+-An arbitrary path name may be given.
+-The
+-.UL flag
+-argument indicates whether the file is to be read, written,
+-or ``updated,'' that is, read and written simultaneously.
+-.PP
+-The returned value
+-.UL filep
+-is called a
+-.IT "file descriptor" .
+-It is a small integer used to identify the file
+-in subsequent calls to read, write,
+-or otherwise manipulate the file.
+-.PP
+-To create a new file or completely rewrite an old one,
+-there is a
+-.UL create
+-system call that
+-creates the given file if it does not exist,
+-or truncates it to zero length
+-if it does exist;
+-.UL create
+-also opens the new file for writing
+-and, like
+-.UL open ,
+-returns a file descriptor.
+-.PP
+-The file system maintains no locks visible to the user, nor is there any
+-restriction on the number of users who may have a file
+-open for reading or writing.
+-Although it is possible for the contents of a file
+-to become scrambled when two users write on it simultaneously,
+-in practice difficulties do not arise.
+-We take the view that locks are neither
+-necessary nor sufficient, in our environment,
+-to prevent interference between users of the same file.
+-They are unnecessary because we are not
+-faced with large, single-file data bases
+-maintained by independent processes.
+-They are insufficient because
+-locks in the ordinary sense, whereby
+-one user is prevented from writing on a file that another
+-user is reading,
+-cannot prevent confusion
+-when, for example, both users are editing
+-a file with an editor that makes
+-a copy of the file being edited.
+-.PP
+-There are, however,
+-sufficient internal interlocks to maintain
+-the logical consistency of the file system
+-when two users engage simultaneously in
+-activities such as writing on
+-the same file,
+-creating files in the same directory,
+-or deleting each other's open files.
+-.PP
+-Except as indicated below, reading and writing
+-are sequential.
+-This means that if a particular
+-byte in the file was the last byte written (or read),
+-the next I/O call implicitly refers to the
+-immediately following byte.
+-For each open file there is a pointer, maintained
+-inside the system,
+-that indicates the next byte to be read
+-or written.
+-If
+-.IT n
+-bytes are read or written, the pointer advances
+-by
+-.IT n
+-bytes.
+-.PP
+-Once a file is open, the following calls
+-may be used:
+-.P1
+-n = read\|(\|filep, buffer, count\|)
+-n = write\|(\|filep, buffer, count\|)
+-.P2
+-Up to
+-.UL count
+-bytes are transmitted between the file specified
+-by
+-.UL filep
+-and the byte array
+-specified by
+-.UL buffer .
+-The returned value
+-.UL n
+-is the number of bytes actually transmitted.
+-In the
+-.UL write
+-case,
+-.UL n
+-is the same as
+-.UL count
+-except under exceptional conditions, such as I/O errors or
+-end of physical medium on special files;
+-in a
+-.UL read ,
+-however,
+-.UL n
+-may without error be less than
+-.UL count .
+-If the read pointer is so near the end of the
+-file that reading
+-.UL count
+-characters
+-would cause reading beyond the end, only sufficient
+-bytes are transmitted to reach the end of the
+-file;
+-also, typewriter-like terminals
+-never return more than one line of input.
+-When a
+-.UL read
+-call returns with
+-.UL n
+-equal
+-to zero, the end of the file has been reached.
+-For disk files this occurs when the read pointer
+-becomes equal to the current
+-size of the file.
+-It is possible to generate an end-of-file
+-from a terminal by use of an escape
+-sequence that depends on the device used.
+-.PP
+-Bytes written affect only those parts of a file implied by
+-the position of the write pointer and the
+-count; no other part of the file
+-is changed.
+-If the last byte lies beyond the end of the file, the
+-file is made to grow as needed.
+-.PP
+-To do random (direct-access) I/O
+-it is only necessary to move the read or write pointer
+-to the appropriate location in the file.
+-.P1
+-location = lseek\|(\|filep, offset, base\|)
+-.P2
+-The pointer
+-associated with
+-.UL filep
+-is moved to a position
+-.UL offset
+-bytes from the beginning of the file, from the current position
+-of the pointer, or from the end of the file,
+-depending on
+-.UL base.
+-.UL \&offset
+-may be negative.
+-For some devices (e.g., paper
+-tape and
+-terminals) seek calls are
+-ignored.
+-The actual offset from the beginning of the file
+-to which the pointer was moved is returned
+-in
+-.UL location .
+-.PP
+-There are several additional system entries
+-having to do with I/O and with the file
+-system that will not be discussed.
+-For example:
+-close a file,
+-get the status of a file,
+-change the protection mode or the owner
+-of a file,
+-create a directory,
+-make a link to an existing file,
+-delete a file.
+-.SH
+-IV. IMPLEMENTATION OF THE FILE SYSTEM
+-.PP
+-As mentioned in Section 3.2 above, a directory entry contains
+-only a name for the associated file and a pointer to the
+-file itself.
+-This pointer is an integer called the
+-.IT i-number
+-(for index number)
+-of the file.
+-When the file is accessed,
+-its i-number is used as an index into
+-a system table (the
+-.IT i-list \|)
+-stored in a known
+-part of the device on which
+-the directory resides.
+-The entry found thereby (the file's
+-.IT i-node \|)
+-contains
+-the description of the file:
+-.IP i
+-the user and group-\*sID\*n of its owner
+-.IP ii
+-its protection bits
+-.IP iii
+-the physical disk or tape addresses for the file contents
+-.IP iv
+-its size
+-.IP v
+-time of creation, last use, and last modification
+-.IP vi
+-the number of links to the file, that is, the number of times it appears in a directory
+-.IP vii
+-a code indicating whether the file is a directory, an ordinary file, or a special file.
+-.LP
+-The purpose of an
+-.UL open
+-or
+-.UL create
+-system call is to turn the path name given by the user
+-into an i-number
+-by searching the explicitly or implicitly named directories.
+-Once a file is open,
+-its device, i-number, and read/write pointer are stored in a system table
+-indexed by the file descriptor returned by the
+-.UL open
+-or
+-.UL create .
+-Thus, during a subsequent
+-call to read or write the
+-file,
+-the descriptor
+-may be easily related to the information necessary to access the file.
+-.PP
+-When a new file is created,
+-an i-node is allocated for it and a directory entry is made
+-that contains the name of the file and the i-node
+-number.
+-Making a link to an existing file involves
+-creating a directory entry with the new name,
+-copying the i-number from the original file entry,
+-and incrementing the link-count field of the i-node.
+-Removing (deleting) a file is done by
+-decrementing the
+-link-count of the i-node specified by its directory entry
+-and erasing the directory entry.
+-If the link-count drops to 0,
+-any disk blocks in the file
+-are freed and the i-node is de-allocated.
+-.PP
+-The space on all disks that
+-contain a file system is divided into a number of
+-512-byte
+-blocks logically addressed from 0 up to a limit that
+-depends on the device.
+-There is space in the i-node of each file for 13 device addresses.
+-For nonspecial files,
+-the first 10 device addresses point at the first
+-10 blocks of the file.
+-If the file is larger than 10 blocks,
+-the 11 device address points to an
+-indirect block containing up to 128 addresses
+-of additional blocks in the file.
+-Still larger files use the twelfth device address
+-of the i-node to point to
+-a double-indirect block naming
+-128 indirect blocks,
+-each
+-pointing to 128 blocks of the file.
+-If required,
+-the thirteenth device address is
+-a triple-indirect block.
+-Thus files may conceptually grow to
+-[\|(10+128+128\u\s62\s0\d+128\u\s63\s0\d)\*m512\|] bytes.
+-Once opened,
+-bytes numbered below 5120 can be read with a single
+-disk access;
+-bytes in the range 5120 to 70,656
+-require two accesses;
+-bytes in the range 70,656
+-to 8,459,264
+-require three accesses;
+-bytes from there to the
+-largest file
+-(1,082,201,088)
+-require four accesses.
+-In practice,
+-a device cache mechanism
+-(see below)
+-proves effective in eliminating
+-most of the indirect fetches.
+-.PP
+-The foregoing discussion applies to ordinary files.
+-When an I/O request is made to a file whose i-node indicates that it
+-is special,
+-the last 12 device address words are immaterial,
+-and the first specifies
+-an internal
+-.IT "device name" ,
+-which is interpreted as a pair of numbers
+-representing,
+-respectively, a device type
+-and subdevice number.
+-The device type indicates which
+-system routine will deal with I/O on that device;
+-the subdevice number selects, for example, a disk drive
+-attached to a particular controller or one of several
+-similar terminal interfaces.
+-.PP
+-In this environment, the implementation of the
+-.UL mount
+-system call (Section 3.4) is quite straightforward.
+-.UL \&mount
+-maintains a system table whose
+-argument is the i-number and device name of the
+-ordinary file specified
+-during the
+-.UL mount ,
+-and whose corresponding value is the
+-device name of the indicated special file.
+-This table is searched for each i-number/device pair
+-that turns up while a path name is being scanned
+-during an
+-.UL open
+-or
+-.UL create ;
+-if a match is found,
+-the i-number is replaced by the i-number of the root
+-directory
+-and the device name is replaced by the table value.
+-.PP
+-To the user, both reading and writing of files appear to
+-be synchronous and unbuffered.
+-That is, immediately after
+-return from a
+-.UL read
+-call the data are available; conversely,
+-after a
+-.UL write
+-the user's workspace may be reused.
+-In fact, the system maintains a rather complicated
+-buffering mechanism that reduces greatly the number
+-of I/O operations required to access a file.
+-Suppose a
+-.UL write
+-call is made specifying transmission
+-of a single byte.
+-The system
+-will search its buffers to see
+-whether the affected disk block currently resides in main memory;
+-if not, it will be read in from the device.
+-Then the affected byte is replaced in the buffer and an
+-entry is made in a list of blocks to be written.
+-The return from the
+-.UL write
+-call may then take place,
+-although the actual I/O may not be completed until a later time.
+-Conversely, if a single byte is read, the system determines
+-whether the secondary storage block in which the byte is located is already
+-in one of the system's buffers; if so, the byte can be returned immediately.
+-If not, the block is read into a buffer and the byte picked out.
+-.PP
+-The system recognizes when
+-a program has
+-made accesses to
+-sequential blocks of a file,
+-and asynchronously
+-pre-reads the next block.
+-This significantly reduces
+-the running time of most programs
+-while adding little to
+-system overhead.
+-.PP
+-A program that reads or writes files in units of 512 bytes
+-has an advantage over a program that reads or writes
+-a single byte at a time, but the gain is not immense;
+-it comes mainly from the avoidance of system overhead.
+-If a program is used rarely or does
+-no great volume of I/O, it may quite reasonably
+-read and write in units as small as it wishes.
+-.PP
+-The notion of the i-list is an unusual feature
+-of
+-.UX .
+-In practice, this method of organizing the file system
+-has proved quite reliable and easy to deal with.
+-To the system itself, one of its strengths is
+-the fact that each file has a short, unambiguous name
+-related in a simple way to the protection, addressing,
+-and other information needed to access the file.
+-It also permits a quite simple and rapid
+-algorithm for checking the consistency of a file system,
+-for example, verification
+-that the portions of each device containing useful information
+-and those free to be allocated are disjoint and together
+-exhaust the space on the device.
+-This algorithm is independent
+-of the directory hierarchy, because it need only scan
+-the linearly organized i-list.
+-At the same time the notion of the i-list induces certain
+-peculiarities not found in other file system organizations.
+-For example, there is the question of who is to be charged
+-for the space a file occupies,
+-because all directory entries for a file have equal status.
+-Charging the owner of a file is unfair in general,
+-for one user may create a file, another may link to
+-it, and the first user may delete the file.
+-The first user is still the owner of the
+-file, but it should be charged
+-to the second user.
+-The simplest reasonably fair algorithm
+-seems to be to spread the charges
+-equally among users who have links to a file.
+-Many installations
+-avoid the
+-issue by not charging any fees at all.
+//GO.SYSIN DD p2
+echo p3
+sed 's/.//' >p3 <<'//GO.SYSIN DD p3'
+-.SH
+-V. PROCESSES AND IMAGES
+-.PP
+-An
+-.IT image
+-is a computer execution environment.
+-It includes a memory image,
+-general register values,
+-status of open files,
+-current directory and the like.
+-An image is the current state of a pseudo-computer.
+-.PP
+-A
+-.IT process
+-is the execution of an image.
+-While the processor is executing on behalf of a process,
+-the image must reside in main memory;
+-during the execution of other processes it remains in main memory
+-unless the appearance of an active, higher-priority
+-process
+-forces it to be swapped out to the disk.
+-.PP
+-The user-memory part of an image is divided into three logical segments.
+-The program text segment begins at location 0 in the virtual address space.
+-During execution, this segment is write-protected
+-and a single copy of it is shared among
+-all processes executing the same program.
+-At the first hardware protection byte boundary above the program text segment in the
+-virtual address space begins a non-shared, writable data segment,
+-the size of which may be extended by a system call.
+-Starting at the highest
+-address in the virtual address space is a stack segment,
+-which automatically grows downward
+-as the stack pointer fluctuates.
+-.SH
+-5.1 Processes
+-.PP
+-Except while
+-the system
+-is bootstrapping itself into operation, a new
+-process can come into existence only
+-by use of the
+-.UL fork
+-system call:
+-.P1
+-processid = fork\|(\|\|)\|
+-.P2
+-When
+-.UL fork
+-is executed, the process
+-splits into two independently executing processes.
+-The two processes have independent
+-copies of the original memory image,
+-and share all open files.
+-The new processes differ only in that one is considered
+-the parent process:
+-in the parent,
+-the returned
+-.UL processid
+-actually identifies the child process
+-and is never 0,
+-while in the child,
+-the returned value is always 0.
+-.PP
+-Because the values returned by
+-.UL fork
+-in the parent and child process are distinguishable,
+-each process may determine whether
+-it is the parent or child.
+-.SH
+-5.2 Pipes
+-.PP
+-Processes may communicate
+-with related processes using the same system
+-.UL read
+-and
+-.UL write
+-calls that are used for file-system I/O.
+-The call:
+-.P1
+-filep = pipe\|(\|\|)\|
+-.P2
+-returns a file descriptor
+-.UL filep
+-and
+-creates an inter-process channel called a
+-.IT pipe .
+-This channel, like other open files, is passed from parent to child process in
+-the image by the
+-.UL fork
+-call.
+-A
+-.UL read
+-using a pipe file descriptor
+-waits until another process writes using the
+-file descriptor for the same pipe.
+-At this point, data are passed between the images of the
+-two processes.
+-Neither process need know that a pipe,
+-rather than an ordinary file,
+-is involved.
+-.PP
+-Although
+-inter-process communication
+-via pipes is a quite valuable tool
+-(see Section 6.2),
+-it is not a completely general
+-mechanism,
+-because the pipe must be set up by a common ancestor
+-of the processes involved.
+-.SH
+-5.3 Execution of programs
+-.PP
+-Another major system primitive
+-is invoked by
+-.P1
+-execute\|(\|file, arg\*s\d1\u\*n, arg\*s\d2\u\*n, .\|.\|. , arg\*s\dn\u\*n\|)\|
+-.P2
+-which requests the system to read in and execute the program
+-named by
+-.UL file ,
+-passing it string arguments
+-.UL arg\v'.3'\*s1\*n\v'-.3'\| ,
+-.UL arg\v'.3'\*s2\*n\v'-.3'\| ,
+-.UL .\|.\|.\|\| ,
+-.UL arg\v'.3'\*sn\*n\v'-.3' .
+-All the code and data in the process invoking
+-.UL execute
+-is replaced from the
+-.UL file ,
+-but
+-open files, current directory, and
+-inter-process relationships are unaltered.
+-Only if the call fails, for example
+-because
+-.UL file
+-could not be found or because
+-its execute-permission bit was not set, does a return
+-take place from the
+-.UL execute
+-primitive;
+-it resembles a ``jump'' machine instruction
+-rather than a subroutine call.
+-.SH
+-5.4 Process synchronization
+-.PP
+-Another process control system call:
+-.P1
+-processid = wait\|(\|status\|)\|
+-.P2
+-causes its caller to suspend
+-execution until one of its children has completed execution.
+-Then
+-.UL wait
+-returns the
+-.UL processid
+-of the terminated process.
+-An error return is taken if the calling process has no
+-descendants.
+-Certain status from the child process
+-is also available.
+-.SH
+-5.5 Termination
+-.PP
+-Lastly:
+-.P1
+-exit\|(\|status\|)\|
+-.P2
+-terminates a process,
+-destroys its image,
+-closes its open files,
+-and generally obliterates it.
+-The parent is notified through
+-the
+-.UL wait
+-primitive,
+-and
+-.UL status
+-is made available
+-to it.
+-Processes may also terminate as a result of
+-various illegal actions or user-generated signals
+-(Section VII below).
+//GO.SYSIN DD p3
+echo p4
+sed 's/.//' >p4 <<'//GO.SYSIN DD p4'
+-.SH
+-VI. THE SHELL
+-.PP
+-For most users,
+-communication with
+-the system
+-is carried on with the
+-aid of a program called the \&shell.
+-The \&shell is a
+-command-line interpreter: it reads lines typed by the user and
+-interprets them as requests to execute
+-other programs.
+-(The \&shell is described fully elsewhere,
+-.[
+-bourne shell bstj
+-%Q This issue
+-.]
+-so this section will discuss only the theory of its operation.)
+-In simplest form, a command line consists of the command
+-name followed by arguments to the command, all separated
+-by spaces:
+-.P1
+-command arg\*s\d1\u\*n arg\*s\d2\u\*n .\|.\|. arg\*s\dn\u\*n
+-.P2
+-The \&shell splits up the command name and the arguments into
+-separate strings.
+-Then a file with name
+-.UL command
+-is sought;
+-.UL command
+-may be a path name including the ``/'' character to
+-specify any file in the system.
+-If
+-.UL command
+-is found, it is brought into
+-memory and executed.
+-The arguments
+-collected by the \&shell are accessible
+-to the command.
+-When the command is finished, the \&shell
+-resumes its own execution, and indicates its readiness
+-to accept another command by typing a prompt character.
+-.PP
+-If file
+-.UL command
+-cannot be found,
+-the \&shell generally prefixes a string 
+-such as
+-.UL /\|bin\|/
+-to
+-.UL command
+-and
+-attempts again to find the file.
+-Directory
+-.UL /\|bin
+-contains commands
+-intended to be generally used.
+-(The sequence of directories to be searched
+-may be changed by user request.)
+-.SH
+-6.1 Standard I/O
+-.PP
+-The discussion of I/O in Section III above seems to imply that
+-every file used by a program must be opened or created by the program in
+-order to get a file descriptor for the file.
+-Programs executed by the \&shell, however, start off with
+-three open files with file descriptors
+-0, 1, and 2.
+-As such a program begins execution, file 1 is open for writing,
+-and is best understood as the standard output file.
+-Except under circumstances indicated below, this file
+-is the user's terminal.
+-Thus programs that wish to write informative
+-information ordinarily use file descriptor 1.
+-Conversely, file 0 starts off open for reading, and programs that
+-wish to read messages typed by the user
+-read this file.
+-.PP
+-The \&shell is able to change the standard assignments of
+-these file descriptors from the
+-user's terminal printer and keyboard.
+-If one of the
+-arguments to a command is prefixed by ``>'', file descriptor
+-1 will, for the duration of the command, refer to the
+-file named after the ``>''.
+-For example:
+-.P1
+-ls
+-.P2
+-ordinarily lists, on the typewriter, the names of the files in the current
+-directory.
+-The command:
+-.P1
+-ls >there
+-.P2
+-creates a file called
+-.UL there
+-and places the listing there.
+-Thus the argument
+-.UL >there
+-means
+-``place output on
+-.UL there .''
+-On the other hand:
+-.P1
+-ed
+-.P2
+-ordinarily enters the editor, which takes requests from the
+-user via his keyboard.
+-The command
+-.P1
+-ed <script
+-.P2
+-interprets
+-.UL script
+-as a file of editor commands;
+-thus
+-.UL <script
+-means ``take input from
+-.UL script .''
+-.PP
+-Although the file name following ``<'' or ``>'' appears
+-to be an argument to the command, in fact it is interpreted
+-completely by the \&shell and is not passed to the
+-command at all.
+-Thus no special coding to handle I/O redirection is needed within each
+-command; the command need merely use the standard file
+-descriptors 0 and 1 where appropriate.
+-.PP
+-File descriptor 2 is, like file 1,
+-ordinarily associated with the terminal output stream.
+-When an output-diversion request with ``>'' is specified,
+-file 2 remains attached to the terminal, so that commands
+-may produce diagnostic messages that
+-do not silently end up in the output file.
+-.SH
+-6.2 Filters
+-.PP
+-An extension of the standard I/O notion is used
+-to direct output from one command to
+-the input of another.
+-A sequence of commands separated by
+-vertical bars causes the \&shell to
+-execute all the commands simultaneously and to arrange
+-that the standard output of each command
+-be delivered to the standard input of
+-the next command in the sequence.
+-Thus in the command line:
+-.P1
+-ls | pr \(mi2 | opr
+-.P2
+-.UL ls
+-lists the names of the files in the current directory;
+-its output is passed to
+-.UL pr ,
+-which
+-paginates its input with dated headings.
+-(The argument ``\(mi2'' requests
+-double-column output.)
+-Likewise, the output from
+-.UL pr
+-is input to
+-.UL opr ;
+-this command spools its input onto a file for off-line
+-printing.
+-.PP
+-This procedure could have been carried out
+-more clumsily by:
+-.P1
+-ls >temp1
+-pr \(mi2 <temp1 >temp2
+-opr <temp2
+-.P2
+-followed by removal of the temporary files.
+-In the absence of the ability
+-to redirect output and input,
+-a still clumsier method would have been to
+-require the
+-.UL ls
+-command
+-to accept user requests to paginate its output,
+-to print in multi-column format, and to arrange
+-that its output be delivered off-line.
+-Actually it would be surprising, and in fact
+-unwise for efficiency reasons,
+-to expect authors of
+-commands such as
+-.UL ls
+-to provide such a wide variety of output options.
+-.PP
+-A program
+-such as
+-.UL pr
+-which copies its standard input to its standard output
+-(with processing)
+-is called a
+-.IT filter .
+-Some filters that we have found useful
+-perform
+-character transliteration,
+-selection of lines according to a pattern,
+-sorting of the input,
+-and encryption and decryption.
+-.SH
+-6.3 Command separators; multitasking
+-.PP
+-Another feature provided by the \&shell is relatively straightforward.
+-Commands need not be on different lines; instead they may be separated
+-by semicolons:
+-.P1
+-ls; ed
+-.P2
+-will first list the contents of the current directory, then enter
+-the editor.
+-.PP
+-A related feature is more interesting.
+-If a command is followed
+-by ``\f3&\f1,'' the \&shell will not wait for the command to finish before
+-prompting again; instead, it is ready immediately
+-to accept a new command.
+-For example:
+-.bd 3
+-.P1
+-as source >output &
+-.P2
+-causes
+-.UL source
+-to be assembled, with diagnostic
+-output going to
+-.UL output ;
+-no matter how long the
+-assembly takes, the \&shell returns immediately.
+-When the \&shell does not wait for
+-the completion of a command,
+-the identification number of the
+-process running that command is printed.
+-This identification may be used to
+-wait for the completion of the command or to
+-terminate it.
+-The ``\f3&\f1'' may be used
+-several times in a line:
+-.P1
+-as source >output & ls >files &
+-.P2
+-does both the assembly and the listing in the background.
+-In these examples, an output file
+-other than the terminal was provided; if this had not been
+-done, the outputs of the various commands would have been
+-intermingled.
+-.PP
+-The \&shell also allows parentheses in the above operations.
+-For example:
+-.P1
+-(\|date; ls\|) >x &
+-.P2
+-writes the current date and time followed by
+-a list of the current directory onto the file
+-.UL x .
+-The \&shell also returns immediately for another request.
+-.SH 1
+-6.4 The \&shell as a command; command files
+-.PP
+-The \&shell is itself a command, and may be called recursively.
+-Suppose file
+-.UL tryout
+-contains the lines:
+-.P1
+-as source
+-mv a.out testprog
+-testprog
+-.P2
+-The
+-.UL mv
+-command causes the file
+-.UL a.out
+-to be renamed
+-.UL testprog.
+-.UL \&a.out
+-is the (binary) output of the assembler, ready to be executed.
+-Thus if the three lines above were typed on the keyboard,
+-.UL source
+-would be assembled, the resulting program renamed
+-.UL testprog ,
+-and
+-.UL testprog
+-executed.
+-When the lines are in
+-.UL tryout ,
+-the command:
+-.P1
+-sh <tryout
+-.P2
+-would cause the \&shell
+-.UL sh
+-to execute the commands
+-sequentially.
+-.PP
+-The \&shell has further capabilities, including the
+-ability to substitute parameters
+-and
+-to construct argument lists from a specified
+-subset of the file names in a directory.
+-It also provides general conditional and looping constructions.
+-.SH 1
+-6.5 Implementation of the \&shell
+-.PP
+-The outline of the operation of the \&shell can now be understood.
+-Most of the time, the \&shell
+-is waiting for the user to type a command.
+-When the
+-newline character ending the line
+-is typed, the \&shell's
+-.UL read
+-call returns.
+-The \&shell analyzes the command line, putting the
+-arguments in a form appropriate for
+-.UL execute .
+-Then
+-.UL fork
+-is called.
+-The child process, whose code
+-of course is still that of the \&shell, attempts
+-to perform an
+-.UL execute
+-with the appropriate arguments.
+-If successful, this will bring in and start execution of the program whose name
+-was given.
+-Meanwhile, the other process resulting from the
+-.UL fork ,
+-which is the
+-parent process,
+-.UL wait s
+-for the child process to die.
+-When this happens, the \&shell knows the command is finished, so
+-it types its prompt and reads the keyboard to obtain another
+-command.
+-.PP
+-Given this framework, the implementation of background processes
+-is trivial; whenever a command line contains ``\f3&\f1,''
+-the \&shell merely refrains from waiting for the process
+-that it created
+-to execute the command.
+-.PP
+-Happily, all of this mechanism meshes very nicely with
+-the notion of standard input and output files.
+-When a process is created by the
+-.UL fork
+-primitive, it
+-inherits not only the memory image of its parent
+-but also all the files currently open in its parent,
+-including those with file descriptors 0, 1, and 2.
+-The \&shell, of course, uses these files to read command
+-lines and to write its prompts and diagnostics, and in the ordinary case
+-its children\(emthe command programs\(eminherit them automatically.
+-When an argument with ``<'' or ``>'' is given, however, the
+-offspring process, just before it performs
+-.UL execute,
+-makes the standard I/O
+-file descriptor (0 or 1, respectively) refer to the named file.
+-This is easy
+-because, by agreement,
+-the smallest unused file descriptor is assigned
+-when a new file is
+-.UL open ed
+-(or
+-.UL create d);
+-it is only necessary to close file 0 (or 1)
+-and open the named file.
+-Because the process in which the command program runs simply terminates
+-when it is through, the association between a file
+-specified after ``<'' or ``>'' and file descriptor 0 or 1 is ended
+-automatically when the process dies.
+-Therefore
+-the \&shell need not know the actual names of the files
+-that are its own standard input and output, because it need
+-never reopen them.
+-.PP
+-Filters are straightforward extensions
+-of standard I/O redirection with pipes used
+-instead of files.
+-.PP
+-In ordinary circumstances, the main loop of the \&shell never
+-terminates.
+-(The main loop includes the
+-branch of the return from
+-.UL fork
+-belonging to the
+-parent process; that is, the branch that does a
+-.UL wait ,
+-then
+-reads another command line.)
+-The one thing that causes the \&shell to terminate is
+-discovering an end-of-file condition on its input file.
+-Thus, when the \&shell is executed as a command with
+-a given input file, as in:
+-.P1
+-sh <comfile
+-.P2
+-the commands in
+-.UL comfile
+-will be executed until
+-the end of
+-.UL comfile
+-is reached; then the instance of the \&shell
+-invoked by
+-.UL sh
+-will terminate.
+-Because this \&shell process
+-is the child of another instance of the \&shell, the
+-.UL wait
+-executed in the latter will return, and another
+-command may then be processed.
+-.SH
+-6.6 Initialization
+-.PP
+-The instances of the \&shell to which users type
+-commands are themselves children of another process.
+-The last step in the initialization of
+-the system
+-is the creation of
+-a single process and the invocation (via
+-.UL execute )
+-of a program called
+-.UL init .
+-The role of
+-.UL init
+-is to create one process
+-for each terminal channel.
+-The various subinstances of
+-.UL init
+-open the appropriate terminals
+-for input and output
+-on files 0, 1, and 2,
+-waiting, if necessary, for carrier to be established on dial-up lines.
+-Then a message is typed out requesting that the user log in.
+-When the user types a name or other identification,
+-the appropriate instance of
+-.UL init
+-wakes up, receives the log-in
+-line, and reads a password file.
+-If the user's name is found, and if
+-he is able to supply the correct password,
+-.UL init
+-changes to the user's default current directory, sets
+-the process's user \*sID\*n to that of the person logging in, and performs
+-an
+-.UL execute
+-of the \&shell.
+-At this point, the \&shell is ready to receive commands
+-and the logging-in protocol is complete.
+-.PP
+-Meanwhile, the mainstream path of
+-.UL init
+-(the parent of all
+-the subinstances of itself that will later become \&shells)
+-does a
+-.UL wait .
+-If one of the child processes terminates, either
+-because a \&shell found an end of file or because a user
+-typed an incorrect name or password, this path of
+-.UL init
+-simply recreates the defunct process, which in turn reopens the appropriate
+-input and output files and types another log-in message.
+-Thus a user may log out simply by typing the end-of-file
+-sequence to the \&shell.
+-.SH
+-6.7 Other programs as \&shell
+-.PP
+-The \&shell as described above is designed to allow users
+-full access to the facilities of the system, because it will
+-invoke the execution of any program
+-with appropriate protection mode.
+-Sometimes, however, a different interface to the system
+-is desirable, and this feature is easily arranged for.
+-.PP
+-Recall that after a user has successfully logged in by supplying
+-a name and password,
+-.UL init
+-ordinarily invokes the \&shell
+-to interpret command lines.
+-The user's entry
+-in the password file may contain the name
+-of a program to be invoked after log-in instead of the \&shell.
+-This program is free to interpret the user's messages
+-in any way it wishes.
+-.PP
+-For example, the password file entries
+-for users of a secretarial editing system
+-might
+-specify that the
+-editor
+-.UL ed
+-is to be used instead of the \&shell.
+-Thus when users of the editing system log in, they are inside the editor and
+-can begin work immediately; also, they can be prevented from
+-invoking
+-programs not intended for their use.
+-In practice, it has proved desirable to allow a temporary
+-escape from the editor
+-to execute the formatting program and other utilities.
+-.PP
+-Several of the games (e.g., chess, blackjack, 3D tic-tac-toe)
+-available on
+-the system
+-illustrate
+-a much more severely restricted environment.
+-For each of these, an entry exists
+-in the password file specifying that the appropriate game-playing
+-program is to be invoked instead of the \&shell.
+-People who log in as a player
+-of one of these games find themselves limited to the
+-game and unable to investigate the (presumably more interesting)
+-offerings of
+-the
+-.UX
+-system
+-as a whole.
+//GO.SYSIN DD p4
+echo p5
+sed 's/.//' >p5 <<'//GO.SYSIN DD p5'
+-.SH
+-VII. TRAPS
+-.PP
+-The \*sPDP\*n-11 hardware detects a number of program faults,
+-such as references to non-existent memory, unimplemented instructions,
+-and odd addresses used where an even address is required.
+-Such faults cause the processor to trap to a system routine.
+-Unless other arrangements have been made,
+-an illegal action causes the system
+-to terminate the process and to write its
+-image
+-on file
+-.UL core
+-in the current directory.
+-A debugger can be used to determine
+-the state of the program at the time of the fault.
+-.PP
+-Programs that are looping, that produce unwanted output, or about which
+-the user has second thoughts may be halted by the use of the
+-.UL interrupt
+-signal, which is generated by typing the ``delete''
+-character.
+-Unless special action has been taken, this
+-signal simply causes the program to cease execution
+-without producing a
+-.UL core
+-file.
+-There is also a
+-.UL quit
+-signal
+-used to force an image file to be produced.
+-Thus programs that loop unexpectedly may be
+-halted and the remains inspected without prearrangement.
+-.PP
+-The hardware-generated faults
+-and the interrupt and quit signals
+-can, by request, be either ignored or caught by a process.
+-For example,
+-the \&shell ignores quits to prevent
+-a quit from logging the user out.
+-The editor catches interrupts and returns
+-to its command level.
+-This is useful for stopping long printouts
+-without losing work in progress (the editor
+-manipulates a copy of the file it is editing).
+-In systems without floating-point hardware,
+-unimplemented instructions are caught
+-and floating-point instructions are
+-interpreted.
+-.SH
+-VIII. PERSPECTIVE
+-.PP
+-Perhaps paradoxically,
+-the success of
+-the
+-.UX
+-system
+-is largely due to the fact that it was not
+-designed to meet any
+-predefined objectives.
+-The first version was written when one of us
+-(Thompson),
+-dissatisfied with the available computer facilities,
+-discovered a little-used \*sPDP\*n-7
+-and set out to create a more
+-hospitable environment.
+-This (essentially personal) effort was
+-sufficiently successful
+-to gain the interest of the other author
+-and several colleagues,
+-and later to justify the acquisition
+-of the \*sPDP\*n-11/20, specifically to support
+-a text editing and formatting system.
+-When in turn the 11/20 was outgrown,
+-the system
+-had proved useful enough to persuade management to
+-invest in the \*sPDP\*n-11/45,
+-and later in the
+-\*sPDP\*n-11/70 and Interdata 8/32 machines,
+-upon which it developed to its present form.
+-Our goals throughout the effort,
+-when articulated at all, have always been to build
+-a comfortable relationship with the machine
+-and to explore ideas and inventions in operating systems
+-and other software.
+-We have not been faced with the need to satisfy someone
+-else's requirements,
+-and for this freedom we are grateful.
+-.PP
+-Three considerations that influenced the design of
+-.UX
+-are visible in retrospect.
+-.PP
+-First:
+-because we are programmers,
+-we naturally designed the system to make it easy to
+-write, test, and run programs.
+-The most important expression of our desire for
+-programming convenience
+-was that the system
+-was arranged for interactive use,
+-even though the original version only
+-supported one user.
+-We believe that a properly designed
+-interactive system is much more
+-productive
+-and satisfying to use than a ``batch'' system.
+-Moreover, such a system is rather easily
+-adaptable to noninteractive use, while the converse is not true.
+-.PP
+-Second:
+-there have always been fairly severe size constraints
+-on the system and its software.
+-Given the partially antagonistic desires for reasonable efficiency and
+-expressive power,
+-the size constraint has encouraged
+-not only economy, but also a certain elegance of design.
+-This may be a thinly disguised version of the ``salvation
+-through suffering'' philosophy,
+-but in our case it worked.
+-.PP
+-Third: nearly from the start, the system was able to, and did, maintain itself.
+-This fact is more important than it might seem.
+-If designers of a system are forced to use that system,
+-they quickly become aware of its functional and superficial deficiencies
+-and are strongly motivated to correct them before it is too late.
+-Because all source programs were always available
+-and easily modified on-line,
+-we were willing to revise and rewrite the system and its software
+-when new ideas were invented, discovered,
+-or suggested by others.
+-.PP
+-The aspects of
+-.UX
+-discussed in this paper exhibit clearly
+-at least the first two of these
+-design considerations.
+-The interface to the file
+-system, for example, is extremely convenient from
+-a programming standpoint.
+-The lowest possible interface level is designed
+-to eliminate distinctions
+-between
+-the various devices and files and between
+-direct and sequential access.
+-No large ``access method'' routines
+-are required
+-to insulate the programmer from the
+-system calls;
+-in fact, all user programs either call the system
+-directly or
+-use a small library program, less than a page long,
+-that buffers a number of characters
+-and reads or writes them all at once.
+-.PP
+-Another important aspect of programming
+-convenience is that there are no ``control blocks''
+-with a complicated structure partially maintained by
+-and depended on by the file system or other system calls.
+-Generally speaking, the contents of a program's address space
+-are the property of the program, and we have tried to
+-avoid placing restrictions
+-on the data structures within that address space.
+-.PP
+-Given the requirement
+-that all programs should be usable with any file or
+-device as input or output,
+-it is also desirable
+-to push device-dependent considerations
+-into the operating system itself.
+-The only alternatives seem to be to load,
+-with all programs,
+-routines for dealing with each device,
+-which is expensive in space,
+-or to depend on some means of dynamically linking to
+-the routine appropriate to each device when it is actually
+-needed,
+-which is expensive either in overhead or in hardware.
+-.PP
+-Likewise,
+-the process-control scheme and the command interface
+-have proved both convenient and efficient.
+-Because the \&shell operates as an ordinary, swappable
+-user program,
+-it consumes no ``wired-down'' space in the system proper,
+-and it may be made as powerful as desired
+-at little cost.
+-In particular,
+-given the framework in which the \&shell executes
+-as a process that spawns other processes to
+-perform commands,
+-the notions of I/O redirection, background processes,
+-command files, and user-selectable system interfaces
+-all become essentially trivial to implement.
+-.SH
+-Influences
+-.PP
+-The success of
+-.UX
+-lies
+-not so much in new inventions
+-but rather in the full exploitation of a carefully selected
+-set of fertile ideas,
+-and especially in showing that
+-they can be keys to the implementation of a small
+-yet powerful operating system.
+-.PP
+-The
+-.UL fork
+-operation, essentially as we implemented it, was
+-present in the \*sGENIE\*n time-sharing system.
+-.[
+-lampson deutsch 930 manual 1965 system preliminary
+-.]
+-On a number of points we were influenced by Multics,
+-which suggested the particular form of the I/O system calls
+-.[
+-multics input output feiertag organick
+-.]
+-and both the name of the \&shell and its general functions.
+-The notion that the \&shell should create a process
+-for each command was also suggested to us by
+-the early design of Multics, although in that
+-system it was later dropped for efficiency reasons.
+-A similar scheme is used by \*sTENEX\*n.
+-.[
+-bobrow burchfiel tenex
+-.]
+//GO.SYSIN DD p5
+echo p6
+sed 's/.//' >p6 <<'//GO.SYSIN DD p6'
+-.SH
+-IX. STATISTICS
+-.PP
+-The following numbers
+-are presented to suggest the scale of the Research
+-.UX
+-operation.
+-Those of our users
+-not involved in document preparation
+-tend to use the system for
+-program development, especially language work.
+-There are few important
+-``applications'' programs.
+-.PP
+-Overall, we have today:
+-.PP
+-.SP .5
+-.TS
+-center;
+-r5 l.
+-125   user population
+-33    maximum simultaneous users
+-1,630 directories
+-28,300        files
+-301,700       512-byte secondary storage blocks used
+-.TE
+-.SP .5
+-There is a ``background'' process that
+-runs at the lowest possible priority; it is used
+-to soak up any idle \*sCPU\*n time.
+-It has been used to produce a million-digit
+-approximation to the constant \fIe\fR,
+-and other semi-infinite problems.
+-Not counting this background work, we average daily:
+-.SP .5
+-.TS
+-center;
+-r 5 l.
+-13,500        commands
+-9.6   \*sCPU\*n hours
+-230   connect hours
+-62    different users
+-240   log-ins
+-.TE
+-.SP .5
+-.SH
+-X. ACKNOWLEDGMENTS
+-.PP
+-The contributors to
+-.UX
+-are, in the traditional but here especially apposite
+-phrase, too numerous to mention.
+-Certainly, collective salutes are due to our colleagues in the
+-Computing Science Research Center.
+-R. H. Canaday contributed much to the basic design of the
+-file system.
+-We are particularly appreciative
+-of the inventiveness,
+-thoughtful criticism,
+-and constant support of
+-R. Morris, M. D. McIlroy,
+-and J. F. Ossanna.
+-.[
+-$LIST$
+-.]
+//GO.SYSIN DD p6
diff --git a/doc/7thEdMan/vol2/cman b/doc/7thEdMan/vol2/cman
new file mode 100644 (file)
index 0000000..7c8fbf5
--- /dev/null
@@ -0,0 +1,2 @@
+Sorry, but for copyright reasons, the source
+for the C Reference Manual is not distributed.
diff --git a/doc/7thEdMan/vol2/ctour.bun b/doc/7thEdMan/vol2/ctour.bun
new file mode 100644 (file)
index 0000000..da968eb
--- /dev/null
@@ -0,0 +1,1474 @@
+# To unbundle, run this file
+echo cdoc0
+sed 's/.//' >cdoc0 <<'//GO.SYSIN DD cdoc0'
+-.TL
+-A Tour through the UNIX\(dg C Compiler
+-.AU "MH 2C517 3770
+-D. M. Ritchie
+-.AI
+-.MH
+-.OK
+-Languages
+-Computing
+-..AB
+-..AE
+-.CS a b c d e f
+-.de II
+-.I
+-\\$1
+-.R
+-..
+-.de Op
+-.SH
+-\\$1 \fI\\$2
+-.IP
+-..
+-.PP
+//GO.SYSIN DD cdoc0
+echo cdoc1
+sed 's/.//' >cdoc1 <<'//GO.SYSIN DD cdoc1'
+-.SH
+-The Intermediate Language
+-.PP
+-.FS
+-\(dgUNIX is a Trademark of Bell Laboratories.
+-.FE
+-Communication between the two phases of the compiler proper
+-is carried out by means of a pair of intermediate files.
+-These files are treated as having identical structure,
+-although the second file contains only the code generated for strings.
+-It is convenient to write strings out separately to reduce the
+-need for multiple location counters in a later assembly
+-phase.
+-.PP
+-The intermediate language is not machine-independent;
+-its structure in a number of ways reflects
+-the fact that C was originally a one-pass compiler
+-chopped in two to reduce the maximum memory
+-requirement.
+-In fact, only the latest version
+-of the compiler has a complete
+-intermediate language at all.
+-Until recently, the first phase of the compiler generated
+-assembly code for those constructions it could deal with,
+-and passed expression parse trees, in absolute binary
+-form,
+-to the second phase for code generation.
+-Now, at least, all inter-phase information
+-is passed in a describable form, and there are
+-no absolute pointers involved, so the coupling between
+-the phases is not so strong.
+-.PP
+-The areas in which the machine
+-(and system) dependencies are most noticeable are
+-.IP 1.
+-Storage allocation for automatic variables and arguments
+-has already been performed,
+-and nodes for such variables refer to them by offset
+-from a display pointer.
+-Type conversion
+-(for example, from integer to pointer)
+-has already occurred using the assumption of
+-byte addressing and 2-byte words.
+-.IP 2.
+-Data representations suitable to the PDP-11 are assumed;
+-in particular, floating point constants are passed as
+-four words in the machine representation.
+-.PP
+-As it happens, each intermediate file is represented as a sequence
+-of binary numbers without any explicit demarcations.
+-It consists of a sequence of
+-conceptual lines, each headed by an operator, and possibly containing
+-various operands.
+-The operators are small numbers;
+-to assist in recognizing failure in synchronization,
+-the high-order byte of each operator word is always the
+-octal number 376.
+-Operands are
+-either 16-bit binary numbers or strings of characters representing names.
+-Each name is terminated by a null character.
+-There is no alignment requirement for numerical
+-operands and so there is no padding
+-after a name string.
+-.PP
+-The binary representation was chosen to avoid the necessity
+-of converting to and from character form
+-and to minimize the size of the files.
+-It would be very easy to make
+-each operator-operand `line' in the file be
+-a genuine, printable line, with the numbers in octal or decimal;
+-this in fact was the representation originally used.
+-.PP
+-The operators fall naturally into two classes:
+-those which represent part of an expression, and all others.
+-Expressions are transmitted in a reverse-Polish notation;
+-as they are being read, a tree is built which is isomorphic
+-to the tree constructed in the first phase.
+-Expressions are passed as a whole, with no non-expression operators
+-intervening.
+-The reader maintains a stack; each leaf of the expression tree (name, constant)
+-is pushed on the stack;
+-each unary operator replaces the top of the stack by a node whose
+-operand is the old top-of-stack;
+-each binary operator replaces the top pair on the stack with
+-a single entry.
+-When the expression is complete there is exactly one item on the
+-stack.
+-Following each expression
+-is a special operator which passes the unique previous expression
+-to the `optimizer' described below and then to the code
+-generator.
+-.PP
+-Here is the list of operators not themselves part of expressions.
+-.LP
+-.Op EOF
+-marks the end of an input file.
+-.Op BDATA "flag data ..."
+-specifies a sequence of bytes to be assembled
+-as static data.
+-It is followed by pairs of words; the first member
+-of the pair is non-zero to indicate that the data continue;
+-a zero flag is not followed by data and terminates
+-the operator.
+-The data bytes occupy the low-order part of a word.
+-.Op WDATA "flag data ..."
+-specifies a sequence of words to be assembled as
+-static data; it is identical to the BDATA operator
+-except that entire words, not just bytes, are passed.
+-.Op PROG
+-means that subsequent information is to be compiled as program text.
+-.Op DATA
+-means that subsequent information is to be compiled as static data.
+-.Op BSS
+-means that subsequent information is to be compiled as unitialized
+-static data.
+-.Op SYMDEF name
+-means that
+-the symbol
+-.I
+-name
+-.R
+-is an external name defined in the current program.
+-It is produced for each external data or function definition.
+-.Op CSPACE "name size"
+-indicates that the name refers to a data area whose size is the
+-specified number of bytes.
+-It is produced for external data definitions without explicit initialization.
+-.Op SSPACE size
+-indicates that
+-.I
+-size
+-.R
+-bytes should be set aside for data storage.
+-It is used to pad out short initializations of external data
+-and to reserve space for static (internal) data.
+-It will be preceded by an appropriate label.
+-.Op EVEN
+-is produced after each
+-external data definition whose size is not
+-an integral number of words.
+-It is not produced after strings except when they initialize
+-a character array.
+-.Op NLABEL name
+-is produced just before a BDATA or WDATA initializing
+-external data, and serves as a label for the data.
+-.Op RLABEL name
+-is produced just before each function definition,
+-and labels its entry point.
+-.Op SNAME "name number"
+-is produced at the start of each function for each static variable
+-or label
+-declared therein.
+-Subsequent uses of the variable will be in terms of the given number.
+-The code generator uses this only to produce a debugging symbol table.
+-.Op ANAME "name number"
+-Likewise, each automatic variable's name and stack offset
+-is specified by this operator.
+-Arguments count as automatics.
+-.Op RNAME "name number"
+-Each register variable is similarly named, with its register number.
+-.Op SAVE number
+-produces a register-save sequence at the start of each function,
+-just after its label (RLABEL).
+-.Op SETREG number
+-is used to indicate the number of registers used
+-for register variables.
+-It actually gives the register number of the lowest
+-free register; it is redundant because the RNAME operators could be
+-counted instead.
+-.Op PROFIL
+-is produced before the save sequence for functions
+-when the profile option is turned on.
+-It produces code to count the number
+-of times the function is called.
+-.Op SWIT "deflab line label value ..."
+-is produced for switches.
+-When control flows into it,
+-the value being switched on is in the register
+-forced by RFORCE (below).
+-The switch statement occurred on the indicated line
+-of the source, and the label number of the default location
+-is
+-.I
+-deflab.
+-.R
+-Then the operator is followed by a sequence of label-number and value pairs;
+-the list is terminated by a 0 label.
+-.Op LABEL number
+-generates an internal label.
+-It is referred to elsewhere using the given number.
+-.Op BRANCH number
+-indicates an unconditional transfer to the internal label number
+-given.
+-.Op RETRN
+-produces the return sequence for a function.
+-It occurs only once, at the end of each function.
+-.Op EXPR line
+-causes the expression just preceding to be compiled.
+-The argument is the line number in the source where the
+-expression occurred.
+-.Op NAME "class type name"
+-.Op NAME "class type number"
+-indicates a name occurring in an expression.
+-The first form is used when the name is external;
+-the second when the name is automatic, static, or a register.
+-Then the number indicates the stack offset, the label number,
+-or the register number as appropriate.
+-Class and type encoding is described elsewhere.
+-.Op CON "type value"
+-transmits an integer constant.
+-This and the next two operators occur as part of expressions.
+-.Op FCON "type 4-word-value"
+-transmits a floating constant as
+-four words in PDP-11 notation.
+-.Op SFCON "type value"
+-transmits a floating-point constant
+-whose value is correctly represented by its high-order word
+-in PDP-11 notation.
+-.Op NULL
+-indicates a null argument list of a function call in an expression;
+-call is a binary operator whose second operand is the argument list.
+-.Op CBRANCH "label cond"
+-produces a conditional branch.
+-It is an expression operator, and will be followed
+-by an EXPR.
+-The branch to the label number takes place if the expression's
+-truth value is the same as that of
+-.I
+-cond.
+-.R
+-That is, if
+-.I
+-cond=1
+-.R
+-and the expression evaluates to true, the branch is taken.
+-.Op binary-operator type
+-There are binary operators corresponding
+-to each such source-language operator;
+-the type of the result of each is passed as well.
+-Some perhaps-unexpected ones are:
+-COMMA, which is a right-associative operator designed
+-to simplify right-to-left evaluation
+-of function arguments;
+-prefix and postfix ++ and \-\-, whose second operand
+-is the increment amount, as a CON;
+-QUEST and COLON, to express the conditional
+-expression as `a?(b:c)';
+-and a sequence of special operators for expressing
+-relations between pointers, in case pointer comparison
+-is different from integer comparison
+-(e.g. unsigned).
+-.Op unary-operator type
+-There are also numerous unary operators.
+-These include ITOF, FTOI, FTOL, LTOF, ITOL, LTOI
+-which convert among floating, long, and integer;
+-JUMP which branches indirectly through a label expression;
+-INIT, which compiles the value of a constant expression
+-used as an initializer;
+-RFORCE, which is used before a return sequence or
+-a switch to place a value in an agreed-upon register.
+//GO.SYSIN DD cdoc1
+echo cdoc2
+sed 's/.//' >cdoc2 <<'//GO.SYSIN DD cdoc2'
+-.SH
+-Expression Optimization
+-.PP
+-Each expression tree, as it is read in, is subjected to
+-a fairly comprehensive
+-analysis.
+-This is performed
+-by the
+-.II optim
+-routine and a number of subroutines;
+-the major things done are
+-.IP 1.
+-Modifications and simplifications
+-of the tree so its value may be computed more efficiently
+-and conveniently by the code generator.
+-.RT
+-.IP 2.
+-Marking each interior node with an estimate of the number of
+-registers required to evaluate it.
+-This register count is needed to guide the code generation algorithm.
+-.PP
+-One thing that is definitely not done is
+-discovery or exploitation of common subexpressions, nor is this done anywhere in the
+-compiler.
+-.PP
+-The basic organization is simple: a depth-first scan of the tree.
+-.II Optim
+-does nothing for leaf nodes (except for automatics; see below),
+-and calls
+-.II unoptim
+-to handle unary operators.
+-For binary operators,
+-it calls itself to process the operands,
+-then treats each operator separately.
+-One important case is
+-commutative and associative operators, which are handled
+-by
+-.II acommute.
+-.PP
+-Here is a brief catalog of the transformations carried out by
+-by
+-.II optim
+-itself.
+-It is not intended to be complete.
+-Some of the transformations are machine-dependent,
+-although they may well be useful on machines other than the
+-PDP-11.
+-.IP 1.
+-As indicated in the discussion of
+-.II unoptim
+-below, the optimizer can create a node type corresponding
+-to the location addressed by a register plus a constant offset.
+-Since this is precisely the implementation of automatic variables
+-and arguments, where the register is fixed by convention,
+-such variables are changed to the new form to simplify
+-later processing.
+-.RT
+-.IP 2.
+-Associative and commutative operators are processed by the
+-special routine
+-.II acommute.
+-.RT
+-.IP 3.
+-After processing by
+-.II acommute,
+-the bitwise & operator is turned into a new
+-.II andn
+-operator; `a & b' becomes
+-`a
+-.II andn
+-~b'.
+-This is done because the PDP-11 provides
+-no
+-.II and
+-operator, but only
+-.II andn.
+-A similar transformation takes place for
+-`=&'.
+-.RT
+-.IP 4.
+-Relationals are turned around so the
+-more complicated expression is on the left.
+-(So that `2 > f(x)' becomes `f(x) < 2').
+-This improves code generation since
+-the algorithm prefers to have the right operand
+-require fewer registers than the left.
+-.RT
+-.IP 5.
+-An expression minus a constant is turned into
+-the expression plus the negative constant,
+-and the
+-.II acommute
+-routine is called
+-to take advantage of the properties of addition.
+-.RT
+-.IP 6.
+-Operators with constant operands are evaluated.
+-.RT
+-.IP 7.
+-Right shifts (unless by 1)
+-are turned into left shifts with a negated right operand,
+-since the PDP-11 lacks a general right-shift operator.
+-.RT
+-.IP 8.
+-A number of special cases are simplified, such as division or
+-multiplication by 1,
+-and shifts by 0.
+-.LP
+-The
+-.II unoptim
+-routine performs the same sort of processing for unary operators.
+-.IP 1.
+-`*&x' and `&*x' are simplified to `x'.
+-.RT
+-.IP 2.
+-If
+-.II r
+-is a register and
+-.II c
+-is a constant or the address of a static or external
+-variable,
+-the expressions `*(r+c)'
+-and `*r' are turned into a special kind of name node
+-which expresses
+-the name itself and the offset.
+-This simplifies subsequent processing
+-because such constructions can appear as
+-the the address of a PDP-11 instruction.
+-.RT
+-.IP 3.
+-When the unary `&' operator is applied to
+-a name node of the special kind just discussed,
+-it is reworked to make the addition
+-explicit again;
+-this is done because the PDP-11 has no `load address' instruction.
+-.RT
+-.IP 4.
+-Constructions
+-like
+-`*r++' and
+-`*\-\-r'
+-where
+-.II r
+-is a register are discovered and marked
+-as being implementable using the PDP-11
+-auto-increment and -decrement modes.
+-.RT
+-.IP 5.
+-If `!' is applied to a relational,
+-the `!' is discarded
+-and the sense of the relational is reversed.
+-.RT
+-.IP 6.
+-Special cases involving reflexive
+-use of negation and complementation are discovered.
+-.RT
+-.IP 7.
+-Operations applying to constants are evaluated.
+-.PP
+-The
+-.II acommute
+-routine, called for associative and commutative operators,
+-discovers clusters of the same operator at the top levels
+-of the current tree, and arranges them in a list:
+-for `a+((b+c)+(d+f))'
+-the list would be`a,b,c,d,e,f'.
+-After each subtree is optimized, the list is sorted in
+-decreasing difficulty of computation;
+-as mentioned above,
+-the code generation algorithm works best when left operands
+-are the difficult ones.
+-The `degree of difficulty'
+-computed is actually finer than
+-the mere number of registers required;
+-a constant is considered simpler
+-than the address of a static or external, which is simpler
+-than reference to a variable.
+-This makes it easy to fold all the constants
+-together,
+-and also to merge together the sum of a constant and the address of
+-a static
+-or external (since in such nodes there is space for
+-an `offset' value).
+-There are also special cases, like multiplication by 1 and addition of 0.
+-.II
+-A special routine is invoked to handle sums of products.
+-.II Distrib
+-is based on the fact that it is better
+-to compute `c1*c2*x + c1*y' as `c1*(c2*x + y)'
+-and makes the divisibility tests required to assure the
+-correctness of the transformation.
+-This transformation is rarely
+-possible with code directly written by the user,
+-but it invariably occurs as a result of the
+-implementation of multi-dimensional arrays.
+-.PP
+-Finally,
+-.II acommute
+-reconstructs a tree from the list
+-of expressions which result.
+//GO.SYSIN DD cdoc2
+echo cdoc3
+sed 's/.//' >cdoc3 <<'//GO.SYSIN DD cdoc3'
+-.SH
+-Code Generation
+-.PP
+-The grand plan for code-generation is
+-independent of any particular machine;
+-it depends largely on a set of tables.
+-But this fact does not necessarily make it very easy
+-to modify the compiler to produce code for other machines,
+-both because there is a good deal of machine-dependent structure
+-in the tables, and because in any event such tables are non-trivial to
+-prepare.
+-.PP
+-The arguments to the basic code generation routine
+-.II rcexpr
+-are a pointer to a tree representing an expression,
+-the name of a code-generation table,
+-and the number of a register in which the value of the
+-expression should be placed.
+-.II Rcexpr
+-returns the number of the register in which the value actually
+-ended up;
+-its caller
+-may need to produce a
+-.II mov
+-instruction if the value really needs to be in the given register.
+-There are four code generation tables.
+-.PP
+-.II Regtab
+-is the basic one, which actually does the job described
+-above: namely,
+-compile code which places the value represented by the expression
+-tree in a register.
+-.PP
+-.II Cctab
+-is used when the value of the expression is not actually needed,
+-but instead the value of the condition codes resulting from
+-evaluation of the expression.
+-This table is used, for example, to evaluate the expression after
+-.II if.
+-It is clearly silly to
+-calculate the value (0 or 1) of the expression
+-`a==b' in the context `if (a==b) ... '
+-.PP
+-The
+-.II sptab
+-table is used when the value of an expression is to be pushed on the stack,
+-for example when it is an actual argument.
+-For example in the function call `f(a)' it is a bad idea to
+-load
+-.II a
+-into a register which is then pushed on the stack,
+-when there is a single instruction which does the job.
+-.PP
+-The
+-.II efftab
+-table is used when an expression is to be evaluated for its side effects,
+-not its value.
+-This occurs mostly for expressions which are statements, which have no
+-value.
+-Thus the code for the statement
+-`a = b'
+-need produce only the approoriate
+-.II mov
+-instruction, and need not leave the value of
+-.II b
+-in a register,
+-while in the expression `a + (b = c)'
+-the value of `b = c' will appear in a register.
+-.PP
+-All of the tables besides
+-.II regtab
+-are rather small, and handle only a relatively few special cases.
+-If one of these subsidiary tables does not contain
+-an entry applicable to the given expression tree,
+-.II rcexpr
+-uses
+-.II regtab
+-to put the value of the expression into a register
+-and then fixes things up;
+-nothing need be done when the table
+-was
+-.II efftab,
+-but a
+-.II tst
+-instruction is produced when the table called for was
+-.II cctab,
+-and a 
+-.II mov
+-instruction,
+-pushing the register on the stack,
+-when the table was
+-.II sptab.
+-.PP
+-The
+-.II rcexpr
+-routine itself picks off some special
+-cases, then calls
+-.II cexpr
+-to do the real work.
+-.II Cexpr
+-tries to find an entry applicable
+-to the given tree in the given table, and returns \-1 if
+-no such entry is found, letting
+-.II rcexpr
+-try again with a different table.
+-A successful match yields a string
+-containing both literal characters
+-which are written out and pseudo-operations, or macros, which are expanded.
+-Before studying the contents
+-of these strings we will consider how table entries are matched
+-against trees.
+-.PP
+-Recall that most non-leaf nodes in an expression tree
+-contain the name of the operator,
+-the type of the value represented, and pointers to the subtrees (operands).
+-They also contain an estimate of the number of registers required to evaluate
+-the expression, placed there by the expression-optimizer routines.
+-The register counts are used to guide the code generation process,
+-which is based on the Sethi-Ullman algorithm.
+-.PP
+-The main code generation
+-tables consist of entries
+-each containing an operator number and a pointer
+-to a subtable for the corresponding operator.
+-A subtable consists of a sequence
+-of entries, each with a key describing certain properties of the
+-operands of the operator involved; associated with the key is a code string.
+-Once the subtable corresponding to the operator is found, the subtable
+-is searched linearly until a key is found such that the properties demanded
+-by the key are compatible with the operands of the tree node.
+-A successful match returns the code string;
+-an unsuccessful search, either for the operator in the main table
+-or a compatble key in the subtable,
+-returns a failure indication.
+-.PP
+-The tables are all contained in a file
+-which must be processed to obtain an assembly language program.
+-Thus they are written in a special-purpose language.
+-To provided definiteness to the following discussion, here is an
+-example of a subtable entry.
+-.DS
+-%n,aw
+-      F
+-      add     A2,R
+-.DE
+-The `%' indicates the key;
+-the information following (up to a blank line) specifies the code string.
+-Very briefly, this entry is in the subtable
+-for `+' of
+-.II regtab;
+-the key specifies that the left operand is any integer, character, or pointer
+-expression,
+-and the right operand is any word quantity which is directly addressible
+-(e.g. a variable or constant).
+-The code string calls for the generation of the code
+-to compile the left (first) operand into the
+-current register (`F')
+-and then to produce an `add' instruction which adds the
+-second operand (`A2') to the register (`R').
+-All of the notation will be explained below.
+-.PP
+-Only three features of the operands are used in deciding
+-whether a match has occurred.
+-They are:
+-.IP 1.
+-Is the type of the operand compatible with that demanded?
+-.RT
+-.IP 2.
+-Is the `degree of difficulty' (in a sense described below) compatible?
+-.RT
+-.IP 3.
+-The table may demand that the operand have a `*'
+-(indirection operator) as its highest operator.
+-.PP
+-As suggested above, the key for a subtable entry
+-is indicated by a `%,' and a comma-separated pair
+-of specifications for the operands.
+-(The second specification is ignored for unary operators).
+-A specification indicates
+-a type requirement by including one of the following letters.
+-If no type letter is present, any integer, character,
+-or pointer operand will satisfy the requirement (not float, double, or long).
+-.IP b
+-A byte (character) operand is required.
+-.RT
+-.IP w
+-A word (integer or pointer) operand is required.
+-.RT
+-.IP f
+-A float or double operand is required.
+-.RT
+-.IP d
+-A double operand is required.
+-.RT
+-.IP l
+-A long (32-bit integer) operand is required.
+-.PP
+-Before discussing the `degree of difficulty' specification,
+-the algorithm has to be explained more completely.
+-.II Rcexpr
+-(and
+-.II cexpr)
+-are called with a register number in which to place their result.
+-Registers 0, 1, ... are used during evaluation of expressions;
+-the maximum register which can be used in this way depends on the
+-number of register variables, but in any event only registers
+-0 through 4 are available since r5 is used as a stack frame
+-header and r6 (sp) and r7 (pc) have special
+-hardware properties.
+-The code generation routines assume that when called with register
+-.II n
+-as argument, they may use
+-.II n+1,
+-\&...
+-(up to the first register variable)
+-as temporaries.
+-Consider the expression `X+Y', where both
+-X and Y are expressions.
+-As a first approximation, there are three ways of compiling
+-code to put this expression in register
+-.II n.
+-.IP 1.
+-If Y is an addressible cell,
+-(recursively) put X into register
+-.II n
+-and add Y to it.
+-.RT
+-.IP 2.
+-If Y is an expression that can be calculated in
+-.II k
+-registers, where
+-.II k
+-smaller than the number of registers available,
+-compile X into register
+-.II n,
+-Y into register
+-.II n+1,
+-and add register
+-.II n+1
+-to
+-.II n.
+-.RT
+-.IP 3.
+-Otherwise, compile Y into register
+-.II n,
+-save the result in a temporary (actually, on the stack)
+-compile X into register
+-.II n,
+-then add in the temporary.
+-.PP
+-The distinction between cases 2 and 3 therefore depends
+-on whether the right operand can be compiled in fewer than
+-.II k
+-registers, where
+-.II k
+-is the number of free registers left after registers 0 through
+-.II n
+-are taken:
+-0 through
+-.II n\-1
+-are presumed to contain already computed temporary results;
+-.II n
+-will, in case 2,
+-contain the value of the left operand while the right
+-is being evaluated.
+-.PP
+-These considerations should make clear
+-the specification codes for the degree of difficulty,
+-bearing in mind that a number of special cases are also present:
+-.IP z
+-is satisfied when the operand is zero, so that special code
+-can be produced for expressions like `x = 0'.
+-.RT
+-.IP 1
+-is satisfied when the operand is the constant 1, to optimize
+-cases like left and right shift by 1, which can be done
+-efficiently on the PDP-11.
+-.RT
+-.IP c
+-is satisfied when the operand is a positive (16-bit)
+-constant; this takes care of some special cases in long arithmetic.
+-.RT
+-.IP a
+-is satisfied when the operand is addressible;
+-this occurs not only for variables and constants, but also for
+-some more complicated constructions, such as indirection through
+-a simple variable, `*p++' where
+-.II p
+-is a register variable (because of the PDP-11's auto-increment address
+-mode), and `*(p+c)' where
+-.II p
+-is a register and
+-.II c
+-is a constant.
+-Precisely, the requirement is that the operand refers to a cell
+-whose address can be written as a source or destination of a PDP-11
+-instruction.
+-.RT
+-.IP e
+-is satisfied by an operand whose value can be generated in a register
+-using no more than
+-.II k
+-registers, where
+-.II k
+-is the number of registers left (not counting the current register).
+-The `e' stands for `easy.'
+-.RT
+-.IP n
+-is satisfied by any operand.
+-The `n' stands for `anything.'
+-.PP
+-These degrees of difficulty are considered to lie in a linear ordering
+-and any operand which satisfies an earlier-mentioned requirement
+-will satisfy a later one.
+-Since the subtables are searched linearly,
+-if a `1' specification is included, almost certainly
+-a `z' must be written first to prevent
+-expressions containing the constant 0 to be compiled
+-as if the 0 were 1.
+-.PP
+-Finally,
+-a key specification may contain a `*' which
+-requires the operand to have an indirection as its leading operator.
+-Examples below should clarify the utility of this specification.
+-.PP
+-Now let us consider the contents of the code string
+-associated with each subtable entry.
+-Conventionally, lower-case letters in this string
+-represent literal information which is copied directly
+-to the output.
+-Upper-case letters generally introduce specific
+-macro-operations, some of which may be followed
+-by modifying information.
+-The code strings in the tables are written with tabs and
+-new-lines used freely to suggest instructions which will be generated;
+-the table-compiling program compresses tabs (using the 0200 bit of the
+-next character) and throws away some of the new-lines.
+-For example the macro `F' is ordinarily written on a line by itself;
+-but since its expansion will end with a new-line, the new-line
+-after `F' itself is dispensable.
+-This is all to reduce the size of the stored tables.
+-.PP
+-The first set of macro-operations is concerned with
+-compiling subtrees.
+-Recall that this is done by the
+-.II cexpr
+-routine.
+-In the following discussion the `current register'
+-is generally the argument register to
+-.II cexpr;
+-that is, the place where the result is desired.
+-The `next register' is numbered one
+-higher
+-than the current register.
+-(This explanation isn't fully true
+-because of complications, described below, involving
+-operations which require even-odd register pairs.)
+-.IP F
+-causes a recursive call to
+-the
+-.II rcexpr
+-routine to compile code which places the value of the first (left)
+-operand of the operator in the current register.
+-.RT
+-.IP F1
+-generates code which places the value of the first operand in the
+-next register.
+-It is incorrectly used if there might be no next register;
+-that is, if the degree of difficulty of the first operand is not `easy;'
+-if not, another register might not be available.
+-.RT
+-.IP FS
+-generates code which pushes the value of the first operand on the stack,
+-by calling
+-.II rcexpr
+-specifying
+-.II sptab
+-as the table.
+-.LP
+-Analogously,
+-.IP "S, S1, SS"
+-compile the second (right) operand
+-into the current register, the next register, or onto the stack.
+-.LP
+-To deal with registers, there are
+-.IP R
+-which expands into the name of the current register.
+-.RT
+-.IP R1
+-which expands into the name of the next register.
+-.RT
+-.IP R+
+-which expands into the the name of the current register plus 1.
+-It was suggested above that this is the same as the next register,
+-except for complications; here is one of them.
+-Long integer variables have
+-32 bits and require 2 registers; in such cases the next register
+-is the current register plus 2.
+-The code would like to talk about both halves of the
+-long quantity, so R refers to the register with the high-order part
+-and R+ to the low-order part.
+-.RT
+-.IP R\-
+-This is another complication, involving division and mod.
+-These operations involve a pair of registers of which the odd-numbered
+-contains the left operand.
+-.II Cexpr
+-arranges that the current register is odd;
+-the R\- notation allows the code to refer to the next lower,
+-even-numbered register.
+-.LP
+-To refer to addressible quantities, there are the notations:
+-.IP A1
+-causes generation of the address specified by the first operand.
+-For this to be legal, the operand must be addressible; its 
+-key must contain an `a'
+-or a more restrictive specification.
+-.RT
+-.IP A2
+-correspondingly generates the address of the second operand
+-providing it has one.
+-.PP
+-We now have enough mechanism to show a complete, if suboptimal,
+-table for the + operator on word or byte operands.
+-.DS
+-%n,z
+-      F
+-.sp 1
+-%n,1
+-      F
+-      inc     R
+-.sp 1
+-%n,aw
+-      F
+-      add     A2,R
+-.sp 1
+-%n,e
+-      F
+-      S1
+-      add     R1,R
+-.sp 1
+-%n,n
+-      SS
+-      F
+-      add     (sp)+,R
+-.DE
+-The first two sequences handle some special cases.
+-Actually it turns out that handling a right operand of 0
+-is unnecessary since the expression-optimizer
+-throws out adds of 0.
+-Adding 1 by using the `increment' instruction is done next,
+-and then the case where the right operand is addressible.
+-It must be a word quantity, since the PDP-11 lacks an `add byte' instruction.
+-Finally the cases where the right operand either can, or cannot,
+-be done in the available registers are treated.
+-.PP
+-The next macro-instructions are conveniently
+-introduced by noticing that the above table is suitable
+-for subtraction as well as addition, since no use is made of the
+-commutativity of addition.
+-All that is needed is substitution of `sub' for `add'
+-and `dec' for 'inc.'
+-Considerable saving of space is achieved by factoring out
+-several similar operations.
+-.IP I
+-is replaced by a string from another table indexed by the operator
+-in the node being expanded.
+-This secondary table actually contains two strings per operator.
+-.RT
+-.IP I\(fm
+-is replaced by the second string in the side table
+-entry for the current operator.
+-.PP
+-Thus, given that the entries for `+' and `\-' in the side table
+-(which is called
+-.II instab)
+-are `add' and `inc,' `sub' and `dec'
+-respectively,
+-the middle of of the above addition table can be written
+-.DS
+-%n,1
+-      F
+-      I'      R
+-
+-%n,aw
+-      F
+-      I       A2,R
+-.DE
+-and it will be suitable for subtraction,
+-and several other operators, as well.
+-.PP
+-Next, there is the question of character and floating-point operations.
+-.IP B1
+-generates the letter `b' if the first operand is a character,
+-`f' if it is float or double, and nothing otherwise.
+-It is used in a context like `movB1'
+-which generates a `mov', `movb', or `movf'
+-instruction according to the type of the operand.
+-.RT
+-.IP B2
+-is just like B1 but applies to the second operand.
+-.RT
+-.IP BE
+-generates `b' if either operand is a character
+-and null otherwise.
+-.RT
+-.IP BF
+-generates `f' if the type of the operator node itself is float or double,
+-otherwise null.
+-.PP
+-For example, there is an entry in
+-.II efftab
+-for the `=' operator
+-.DS
+-%a,aw
+-%ab,a
+-      IBE     A2,A1
+-.DE
+-Note first that two key specifications
+-can be applied to the same code string.
+-Next, observe that when a word is assigned to a byte or to a word,
+-or a word is assigned to a byte,
+-a single instruction,
+-a
+-.II mov
+-or
+-.II movb
+-as appropriate, does the job.
+-However, when a byte is assigned to a word,
+-it must pass through a register to implement the sign-extension rules:
+-.DS
+-%a,n
+-      S
+-      IB1     R,A1
+-.DE
+-.PP
+-Next, there is the question of handling indirection properly.
+-Consider the expression `X + *Y', where X and Y are expressions,
+-Assuming that Y is more complicated than just a variable,
+-but on the other hand qualifies as `easy' in the context,
+-the expression would be compiled by placing the value of X in a register,
+-that of *Y in the next register, and adding the registers.
+-It is easy to see that a better job can be done
+-by compiling X, then Y (into the next register),
+-and producing the
+-instruction symbolized by `add (R1),R'.
+-This scheme avoids generating
+-the instruction `mov (R1),R1'
+-required actually to place the value of *Y in a register.
+-A related situation occurs
+-with the expression `X + *(p+6)', which
+-exemplifies a construction
+-frequent in structure and array references.
+-The addition table shown above would produce
+-.DS
+-[put X in register R]
+-mov   p,R1
+-add   $6,R1
+-mov   (R1),R1
+-add   R1,R
+-.DE
+-when the best code is
+-.DS
+-[put X in R]
+-mov   p,R1
+-add   6(R1),R
+-.DE
+-As we said above, a key specification for a code table entry
+-may require an operand to have an indirection as its highest operator.
+-To make use of the requirement,
+-the following macros are provided.
+-.IP F*
+-the first operand must have the form *X.
+-If in particular it has the form *(Y + c), for some constant
+-.II c,
+-then code is produced which places the value of Y in
+-the current register.
+-Otherwise, code is produced which loads X into the current register.
+-.RT
+-.IP F1*
+-resembles F* except that the next register is loaded.
+-.RT
+-.IP S*
+-resembles F* except that the second operand is loaded.
+-.RT
+-.IP S1*
+-resembles S* except that the next register is loaded.
+-.RT
+-.IP FS*
+-The first operand must have the form `*X'.
+-Push the value of X on the stack.
+-.RT
+-.IP SS*
+-resembles FS* except that it applies to the second operand.
+-.LP
+-To capture the constant that may have been skipped over
+-in the above macros, there are
+-.IP #1
+-The first operand must have the form *X;
+-if in particular it has the form *(Y + c) for
+-.II c
+-a constant, then the constant is written out,
+-otherwise a null string.
+-.RT
+-.IP #2
+-is the same as #1 except that the second operand is used.
+-.LP
+-Now we can improve the addition table above.
+-Just before the `%n,e' entry, put
+-.DS
+-%n,ew*
+-      F
+-      S1*
+-      add     #2(R1),R
+-.DE
+-and just before the `%n,n' put
+-.DS
+-%n,nw*
+-      SS*
+-      F
+-      add     *(sp)+,R
+-.DE
+-When using the stacking macros there is no place to use
+-the constant
+-as an index word, so that particular special case doesn't occur.
+-.PP
+-The constant mentioned above can actually be more
+-general than a number.
+-Any quantity acceptable to the assembler as an expression will do,
+-in particular the address of a static cell, perhaps with a numeric offset.
+-If
+-.II x
+-is an external character array,
+-the expression `x[i+5] = 0' will generate
+-the code
+-.DS
+-mov   i,r0
+-clrb  x+5(r0)
+-.DE
+-via the table entry (in the `=' part of
+-.II efftab)
+-.DS
+-%e*,z
+-      F
+-      I'B1    #1(R)
+-.DE
+-Some machine operations place restrictions on the registers
+-used.
+-The divide instruction, used to implement the divide and mod
+-operations, requires the dividend to be placed in the odd member
+-of an even-odd pair;
+-other peculiarities
+-of multiplication make it simplest to put the multiplicand
+-in an odd-numbered register.
+-There is no theory which optimally accounts for
+-this kind of requirement.
+-.II Cexpr
+-handles it by checking for a multiply, divide, or mod operation;
+-in these cases, its argument register number is incremented by
+-one or two so that it is odd, and if the operation was divide or mod,
+-so that it is a member of a free even-odd pair.
+-The routine which determines the number of registers required
+-estimates, conservatively, that
+-at least two registers are required for a multiplication
+-and three for the other peculiar operators.
+-After the expression is compiled,
+-the register where the result actually ended up is returned.
+-(Divide and mod are actually the same operation except for the
+-location of the result).
+-.PP
+-These operations are the ones which cause results to end up in
+-unexpected places,
+-and this possibility adds a further level of complexity.
+-The simplest way of handling the problem is always to move the
+-result to the place where the caller expected it,
+-but this will produce unnecessary register moves in many
+-simple cases; `a = b*c' would generate
+-.DS
+-mov   b,r1
+-mul   c,r1
+-mov   r1,r0
+-mov   r0,a
+-.DE
+-The next thought is used the passed-back
+-information as to where the result landed to change the notion of the current
+-register.
+-While compiling the `=' operation above, which comes from a
+-table
+-entry
+-like
+-.DS
+-%a,e
+-      S
+-      mov     R,A1
+-.DE
+-it is sufficient to redefine the meaning of `R'
+-after processing the `S' which does the multiply.
+-This technique is in fact used; the tables are written in such a way
+-that correct code is produced.
+-The trouble is that the technique cannot be used in general,
+-because it invalidates the count of the number of registers
+-required for an expression.
+-Consider just `a*b + X' where X is some expression.
+-The algorithm assumes that the value of a*b,
+-once computed, requires just one register.
+-If there are three registers available, and X requires two registers to
+-compute, then this expression will match a key specifying
+-`%n,e'.
+-If a*b is computed and left in register 1, then there are, contrary
+-to expectations, no longer two registers available to compute X,
+-but only one, and bad code will be produced.
+-To guard against this possibility,
+-.II cexpr
+-checks the result returned by recursive calls which implement
+-F, S and their relatives.
+-If the result is not in the expected register, then the number of
+-registers required by the other operand is checked;
+-if it can be done using those registers which remain even
+-after making unavailable the unexpectedly-occupied
+-register, then
+-the notions of the `next register' and possibly the `current
+-register' are redefined.
+-Otherwise a register-copy instruction is produced.
+-A register-copy is also always produced
+-when the current operator is one of those which have odd-even requirements.
+-.PP
+-Finally, there are a few loose-end macro operations
+-and facts about the tables.
+-The operators:
+-.IP V
+-is used for long operations.
+-It is written with an address like a machine instruction;
+-it expands into `adc' (add carry) if the operation
+-is an additive operator,
+-`sbc' (subtract carry) if the operation is a subtractive
+-operator, and disappears, along with the rest of the line, otherwise.
+-Its purpose is to allow common treatment of logical
+-operations, which have no carries, and additive and subtractive
+-operations, which generate carries.
+-.RT
+-.IP T
+-generates a `tst' instruction if the first operand
+-of the tree does not set the condition codes correctly.
+-It is used with divide and mod operations,
+-which require a sign-extended 32-bit operand.
+-The code table for the operations contains an `sxt'
+-(sign-extend) instruction to generate the high-order part of the
+-dividend.
+-.RT
+-.IP H
+-is analogous to the `F' and `S' macros,
+-except that it calls for the generation of code for
+-the current tree
+-(not one of its operands)
+-using
+-.II regtab.
+-It is used in
+-.II cctab
+-for all the operators which, when executed normally,
+-set the condition codes properly according to the result.
+-It prevents a `tst' instruction from being generated for
+-constructions like `if (a+b) ...'
+-since after calculation of the value of
+-`a+b' a conditional branch can be written immediately.
+-.PP
+-All of the discussion above is in terms of operators with operands.
+-Leaves of the expression tree (variables and constants), however,
+-are peculiar in that they have no operands.
+-In order to regularize the matching process,
+-.II cexpr
+-examines its operand to determine if it is a leaf;
+-if so, it creates a special `load' operator whose operand
+-is the leaf, and substitutes it for the argument tree;
+-this allows the table entry for the created operator
+-to use the `A1' notation to load the leaf into a register.
+-.PP
+-Purely to save space in the tables,
+-pieces of subtables can be labelled and referred to later.
+-It turns out, for example,
+-that rather large portions of the
+-the
+-.II efftab
+-table for the `=' and `=+' operators are identical.
+-Thus `=' has an entry
+-.DS
+-%[move3:]
+-%a,aw
+-%ab,a
+-      IBE     A2,A1
+-.DE
+-while part of the `=+' table is
+-.DS
+-%aw,aw
+-%     [move3]
+-.DE
+-Labels are written as `%[ ... : ]',
+-before the key specifications;
+-references
+-are written
+-with `%  [ ... ]'
+-after the key.
+-Peculiarities in the implementation
+-make it necessary that labels appear before references to them.
+-.PP
+-The example illustrates the utility
+-of allowing separate keys
+-to point to the same code string.
+-The assignment code
+-works properly if either the right operand is a word, or the left operand
+-is a byte;
+-but since there is no `add byte' instruction the addition code
+-has to be restricted to word operands.
+//GO.SYSIN DD cdoc3
+echo cdoc4
+sed 's/.//' >cdoc4 <<'//GO.SYSIN DD cdoc4'
+-.SH
+-Delaying and reordering
+-.PP
+-Intertwined with the code generation routines are two other,
+-interrelated processes.
+-The first, implemented by a routine called
+-.II delay,
+-is based on the observation that
+-naive code generation for the expression
+-`a = b++' would produce
+-.DS
+-mov   b,r0
+-inc   b
+-mov   r0,a
+-.DE
+-The point is that the table for postfix ++ has to preserve
+-the value of
+-.II b
+-before incrementing it;
+-the general way to do this is to preserve its value in a register.
+-A cleverer scheme would generate
+-.DS
+-mov   b,a
+-inc   b
+-.DE
+-.II Delay
+-is called for each expression input to
+-.II rcexpr,
+-and it searches for postfix ++ and \-\-
+-operators.
+-If one is found applied to a variable,
+-the tree is patched to bypass the operator
+-and compiled as it stands;
+-then the increment or decrement itself is done.
+-The effect is as if `a = b; b++' had been written.
+-In this example, of course, the user himself could have done the same job,
+-but more complicated examples are easily constructed, for example
+-`switch (x++)'.
+-An essential restriction is that the condition codes not
+-be required.
+-It would be incorrect to compile
+-`if (a++) ...'
+-as
+-.DS
+-tst   a
+-inc   a
+-beq   ...
+-.DE
+-because the `inc' destroys the required setting of the condition codes.
+-.PP
+-Reordering is a similar sort of optimization.
+-Many cases which it detects are useful
+-mainly with register variables.
+-If
+-.II r
+-is a register variable,
+-the expression `r = x+y' is best compiled
+-as
+-.DS
+-mov   x,r
+-add   y,r
+-.DE
+-but the codes tables would produce
+-.DS
+-mov   x,r0
+-add   y,r0
+-mov   r0,r
+-.DE
+-which is in fact preferred if
+-.II r
+-is not a register.
+-(If
+-.II r
+-is not a register,
+-the
+-two sequences are the same size, but the
+-second is slightly faster.)
+-The scheme is to compile the expression as if it had been written
+-`r = x; r =+ y'.
+-The
+-.II reorder
+-routine
+-is called with a pointer to each tree that
+-.II rcexpr
+-is about to compile;
+-if it has the right characteristics,
+-the `r = x' tree is constructed and passed recursively
+-to
+-.II rcexpr;
+-then the original tree is modified to read `r =+ y'
+-and the calling instance of
+-.II rcexpr
+-compiles that instead.
+-Of course the whole business is itself recursive
+-so that more extended forms of the same phenomenon are
+-handled, like `r = x + y | z'.
+-.PP
+-Care does have to be taken
+-to avoid `optimizing' an expression like `r = x + r'
+-into `r = x; r =+ r'.
+-It is required that the right operand of the expression on the right
+-of the `=' be a ', distinct from the register variable.
+-.PP
+-The second case that
+-.II reorder
+-handles is expressions of the form `r = X' used as a subexpression.
+-Again, the code out of the tables for
+-`x = r = y'
+-would be
+-.DS
+-mov   y,r0
+-mov   r0,r
+-mov   r0,x
+-.DE
+-whereas if
+-.II r
+-were a register it would be better to produce
+-.DS
+-mov   y,r
+-mov   r,x
+-.DE
+-When
+-.II reorder
+-discovers that
+-a register variable is being assigned to
+-in a subexpression,
+-it calls
+-.II rcexpr
+-recursively to
+-compile the subexpression, then fiddles the tree passed
+-to it so that the register variable itself appears
+-as the operand instead of the whole subexpression.
+-Here care has to be taken to avoid an infinite regress,
+-with
+-.II rcexpr
+-and
+-.II reorder
+-calling each other forever to handle assignments to registers.
+-.PP
+-A third set of cases treated by
+-.II reorder
+-comes up when any name, not necessarily a register,
+-occurs as a left operand of an assignment operator other than `='
+-or as an operand of prefix `++' or `\-\-'.
+-Unless condition-code tests are involved,
+-when a subexpression like `(a =+ b)' is seen,
+-the assignment is performed and the argument tree
+-modified so that
+-.II a
+-is its operand;
+-effectively
+-`x + (y =+ z)' is compiled as `y =+ z; x + y'.
+-Similarly, prefix increment and decrement are pulled out
+-and performed first, then the remainder of the expression.
+-.PP
+-Throughout code generation,
+-the expression optimizer is called whenever
+-.II delay
+-or
+-.II reorder
+-change the expression tree.
+-This allows some special cases to be found that otherwise
+-would not be seen.
+//GO.SYSIN DD cdoc4
diff --git a/doc/7thEdMan/vol2/dc b/doc/7thEdMan/vol2/dc
new file mode 100644 (file)
index 0000000..f77522e
--- /dev/null
@@ -0,0 +1,709 @@
+.RP
+....TM 75-1271-8 39199 39199-11
+.TL
+DC \- An Interactive Desk Calculator
+.AU "MH 2C-524" 3878
+Robert Morris
+.AU
+Lorinda Cherry
+.AI
+.MH
+.AB
+DC is an interactive desk calculator program implemented
+on the
+.UX
+time-sharing system to do arbitrary-precision
+integer arithmetic.
+It has provision for manipulating scaled fixed-point numbers and
+for input and output in bases other than decimal.
+.PP
+The size of numbers that can be manipulated is limited
+only by available core storage.
+On typical implementations of
+.UX ,
+the size of numbers that
+can be handled varies from several hundred digits on the smallest
+systems to several thousand on the largest.
+.AE
+.PP
+.SH
+.ND
+.PP
+DC is an arbitrary precision arithmetic package implemented
+on the
+.UX
+time-sharing system
+in the form of an interactive desk calculator.
+It works like a stacking calculator using reverse Polish notation.
+Ordinarily DC operates on decimal integers, but one may
+specify an input base, output base, and a number of fractional
+digits to be maintained.
+.PP
+A language called BC [1] has been developed which accepts
+programs written in the familiar style of higher-level
+programming languages and compiles output which is
+interpreted by DC.
+Some of the commands described below were designed
+for the compiler interface and are not easy for a human user
+to manipulate.
+.PP
+Numbers that are typed into DC are put on a push-down
+stack.
+DC commands work by taking the top number or two
+off the stack, performing the desired operation, and pushing the result
+on the stack.
+If an argument is given,
+input is taken from that file until its end,
+then from the standard input.
+.SH
+SYNOPTIC DESCRIPTION
+.PP
+Here we describe the DC commands that are intended
+for use by people.  The additional commands that are
+intended to be invoked by compiled output are
+described in the detailed description.
+.PP
+Any number of commands are permitted on a line.
+Blanks and new-line characters are ignored except within numbers
+and in places where a register name is expected.
+.PP
+The following constructions are recognized:
+.SH
+number
+.IP
+The value of the number is pushed onto the main stack.
+A number is an unbroken string of the digits 0-9
+and the capital letters A\-F which are treated as digits
+with values 10\-15 respectively.
+The number may be preceded by an underscore \*_ to input a
+negative number.
+Numbers may contain decimal points.
+.SH
++  \-  *  %  ^
+.IP
+The
+top two values on the stack are added
+(\fB+\fP),
+subtracted
+(\fB\-\fP),
+multiplied (\fB*\fP),
+divided (\fB/\fP),
+remaindered (\fB%\fP),
+or exponentiated (^).
+The two entries are popped off the stack;
+the result is pushed on the stack in their place.
+The result of a division is an integer truncated toward zero.
+See the detailed description below for the treatment of
+numbers with decimal points.
+An exponent must not have any digits after the decimal point.
+.SH
+s\fIx\fP
+.IP
+The
+top of the main stack is popped and stored into
+a register named \fIx\fP, where \fIx\fP may be any character.
+If
+the
+.ft B
+s
+.ft
+is capitalized,
+.ft I
+x
+.ft
+is treated as a stack and the value is pushed onto it.
+Any character, even blank or new-line, is a valid register name.
+.SH
+l\fIx\fP
+.IP
+The
+value in register
+.ft I
+x
+.ft
+is pushed onto the stack.
+The register
+.ft I
+x
+.ft
+is not altered.
+If the
+.ft B
+l
+.ft
+is capitalized,
+register
+.ft I
+x
+.ft
+is treated as a stack and its top value is popped onto the main stack.
+.LP
+All registers start with empty value which is treated as a zero
+by the command \fBl\fP and is treated as an error by the command \fBL\fP.
+.SH
+.SH
+d
+.IP
+The
+top value on the stack is duplicated.
+.SH
+p
+.IP
+The top value on the stack is printed.
+The top value remains unchanged.
+.SH
+f
+.IP
+All values on the stack and in registers are printed.
+.SH
+x
+.IP
+treats the top element of the stack as a character string,
+removes it from the stack, and
+executes it as a string of DC commands.
+.SH
+[ ... ]
+.IP
+puts the bracketed character string onto the top of the stack.
+.SH
+q
+.IP
+exits the program.
+If executing a string, the recursion level is
+popped by two.
+If
+.ft B
+q
+.ft
+is capitalized,
+the top value on the stack is popped and the string execution level is popped
+by that value.
+.SH
+<\fIx\fP  >\fIx\fP  =\fIx\fP  !<\fIx\fP  !>\fIx\fP  !=\fIx\fP
+.IP
+The
+top two elements of the stack are popped and compared.
+Register
+.ft I
+x
+.ft
+is executed if they obey the stated
+relation.
+Exclamation point is negation.
+.SH
+v
+.IP
+replaces the top element on the stack by its square root.
+The square root of an integer is truncated to an integer.
+For the treatment of numbers with decimal points, see
+the detailed description below.
+.SH
+!
+.IP
+interprets the rest of the line as a
+.UX
+command.
+Control returns to DC when the
+.UX
+command terminates.
+.SH
+c
+.IP
+All values on the stack are popped; the stack becomes empty.
+.SH
+i
+.IP
+The top value on the stack is popped and used as the
+number radix for further input.
+If \fBi\fP is capitalized, the value of
+the input base is pushed onto the stack.
+No mechanism has been provided for the input of arbitrary
+numbers in bases less than 1 or greater than 16.
+.SH
+o
+.IP
+The top value on the stack is popped and used as the
+number radix for further output.
+If \fBo\fP is capitalized, the value of the output
+base is pushed onto the stack.
+.SH
+k
+.IP
+The top of the stack is popped, and that value is used as
+a scale factor
+that influences the number of decimal places
+that are maintained during multiplication, division, and exponentiation.
+The scale factor must be greater than or equal to zero and
+less than 100.
+If \fBk\fP is capitalized, the value of the scale factor
+is pushed onto the stack.
+.SH
+z
+.IP
+The value of the stack level is pushed onto the stack.
+.SH
+?
+.IP
+A line of input is taken from the input source (usually the console)
+and executed.
+.SH
+DETAILED DESCRIPTION
+.SH
+Internal Representation of Numbers
+.PP
+Numbers are stored internally using a dynamic storage allocator.
+Numbers are kept in the form of a string
+of digits to the base 100 stored one digit per byte
+(centennial digits).
+The string is stored with the low-order digit at the
+beginning of the string.
+For example, the representation of 157
+is 57,1.
+After any arithmetic operation on a number, care is taken
+that all digits are in the range 0\-99 and that
+the number has no leading zeros.
+The number zero is represented by the empty string.
+.PP
+Negative numbers are represented in the 100's complement
+notation, which is analogous to two's complement notation for binary
+numbers.
+The high order digit of a negative number is always \-1
+and all other digits are in the range 0\-99.
+The digit preceding the high order \-1 digit is never a 99.
+The representation of \-157 is 43,98,\-1.
+We shall call this the canonical form of a number.
+The advantage of this kind of representation of negative
+numbers is ease of addition.  When addition is performed digit
+by digit, the result is formally correct.  The result need only
+be modified, if necessary, to put it into canonical form.
+.PP
+Because the largest valid digit is 99 and the byte can
+hold numbers twice that large, addition can be carried out
+and the handling of carries done later when
+that is convenient, as it sometimes is.
+.PP
+An additional byte is stored with each number beyond
+the high order digit to indicate the number of
+assumed decimal digits after the decimal point.  The representation
+of .001 is 1,\fI3\fP
+where the scale has been italicized to emphasize the fact that it
+is not the high order digit.
+The value of this extra byte is called the
+.ft B
+scale factor
+.ft
+of the number.
+.SH
+The Allocator
+.PP
+DC uses a dynamic string storage allocator
+for all of its internal storage.
+All reading and writing of numbers internally is done through
+the allocator.
+Associated with each string in the allocator is a four-word header containing pointers
+to the beginning of the string, the end of the string,
+the next place to write, and the next place to read.
+Communication between the allocator and DC
+is done via pointers to these headers.
+.PP
+The allocator initially has one large string on a list
+of free strings.  All headers except the one pointing
+to this string are on a list of free headers.
+Requests for strings are made by size.
+The size of the string actually supplied is the next higher
+power of 2.
+When a request for a string is made, the allocator
+first checks the free list to see if there is
+a string of the desired size.
+If none is found, the allocator finds the next larger free string and splits it repeatedly until
+it has a string of the right size.
+Left-over strings are put on the free list.
+If there are no larger strings,
+the allocator tries to coalesce smaller free strings into
+larger ones.
+Since all strings are the result
+of splitting large strings,
+each string has a neighbor that is next to it in core
+and, if free, can be combined with it to make a string twice as long.
+This is an implementation of the `buddy system' of allocation
+described in [2].
+.PP
+Failing to find a string of the proper length after coalescing,
+the allocator asks the system for more space.
+The amount of space on the system is the only limitation
+on the size and number of strings in DC.
+If at any time in the process of trying to allocate a string, the allocator runs out of
+headers, it also asks the system for more space.
+.PP
+There are routines in the allocator for reading, writing, copying, rewinding,
+forward-spacing, and backspacing strings.
+All string manipulation is done using these routines.
+.PP
+The reading and writing routines
+increment the read pointer or write pointer so that
+the characters of a string are read or written in
+succession by a series of read or write calls.
+The write pointer is interpreted as the end of the
+information-containing portion of a string and a call
+to read beyond that point returns an end-of-string indication.
+An attempt to write beyond the end of a string
+causes the allocator to
+allocate a larger space and then copy
+the old string into the larger block.
+.SH
+Internal Arithmetic
+.PP
+All arithmetic operations are done on integers.
+The operands (or operand) needed for the operation are popped
+from the main stack and their scale factors stripped off.
+Zeros are added or digits removed as necessary to get
+a properly scaled result from the internal arithmetic routine.
+For example, if the scale of the operands is different and decimal
+alignment is required, as it is for
+addition, zeros are appended to the operand with the smaller
+scale.
+After performing the required arithmetic operation,
+the proper scale factor is appended to the end of the number before
+it is pushed on the stack.
+.PP
+A register called \fBscale\fP plays a part
+in the results of most arithmetic operations.
+\fBscale\fP is the bound on the number of decimal places retained in
+arithmetic computations.
+\fBscale\fP may be set to the number on the top of the stack
+truncated to an integer with the \fBk\fP command.
+\fBK\fP may be used to push the value of \fBscale\fP on the stack.
+\fBscale\fP must be greater than or equal to 0 and less than 100.
+The descriptions of the individual arithmetic operations will
+include the exact effect of \fBscale\fP on the computations.
+.SH
+Addition and Subtraction
+.PP
+The scales of the two numbers are compared and trailing
+zeros are supplied to the number with the lower scale to give both
+numbers the same scale.  The number with the smaller scale is
+multiplied by 10 if the difference of the scales is odd.
+The scale of the result is then set to the larger of the scales
+of the two operands.
+.PP
+Subtraction is performed by negating the number
+to be subtracted and proceeding as in addition.
+.PP
+Finally, the addition is performed digit by digit from the
+low order end of the number.  The carries are propagated
+in the usual way.
+The resulting number is brought into canonical form, which may
+require stripping of leading zeros, or for negative numbers
+replacing the high-order configuration 99,\-1 by the digit \-1.
+In any case, digits which are not in the range 0\-99 must
+be brought into that range, propagating any carries or borrows
+that result.
+.SH
+Multiplication
+.PP
+The scales are removed from the two operands and saved.
+The operands are both made positive.
+Then multiplication is performed in
+a digit by digit manner that exactly mimics the hand method
+of multiplying.
+The first number is multiplied by each digit of the second
+number, beginning with its low order digit.  The intermediate
+products are accumulated into a partial sum which becomes the
+final product.
+The product is put into the canonical form and its sign is
+computed from the signs of the original operands.
+.PP
+The scale of the result is set equal to the sum
+of the scales of the two operands.
+If that scale is larger than the internal register
+.ft B
+scale
+.ft
+and also larger than both of the scales of the two operands,
+then the scale of the result is set equal to the largest
+of these three last quantities.
+.SH
+Division
+.PP
+The scales are removed from the two operands.
+Zeros are appended or digits removed from the dividend to make
+the scale of the result of the integer division equal to
+the internal quantity
+\fBscale\fP.
+The signs are removed and saved.
+.PP
+Division is performed much as it would be done by hand.
+The difference of the lengths of the two numbers
+is computed.
+If the divisor is longer than the dividend,
+zero is returned.
+Otherwise the top digit of the divisor is divided into the top
+two digits of the dividend.
+The result is used as the first (high-order) digit of the
+quotient.
+It may turn out be one unit too low, but if it is, the next
+trial quotient will be larger than 99 and this will be
+adjusted at the end of the process.
+The trial digit is multiplied by the divisor and the result subtracted
+from the dividend and the process is repeated to get
+additional quotient digits until the remaining
+dividend is smaller than the divisor.
+At the end, the digits of the quotient are put into
+the canonical form, with propagation of carry as needed.
+The sign is set from the sign of the operands.
+.SH
+Remainder
+.PP
+The division routine is called and division is performed
+exactly as described.  The quantity returned is the remains of the
+dividend at the end of the divide process.
+Since division truncates toward zero, remainders have the same
+sign as the dividend.
+The scale of the remainder is set to 
+the maximum of the scale of the dividend and
+the scale of the quotient plus the scale of the divisor.
+.SH
+Square Root
+.PP
+The scale is stripped from the operand.
+Zeros are added if necessary to make the
+integer result have a scale that is the larger of
+the internal quantity
+\fBscale\fP
+and the scale of the operand.
+.PP
+The method used to compute sqrt(y) is Newton's method
+with successive approximations by the rule
+.EQ
+x sub {n+1} ~=~ half ( x sub n + y over x sub n )
+.EN
+The initial guess is found by taking the integer square root
+of the top two digits.
+.SH
+Exponentiation
+.PP
+Only exponents with zero scale factor are handled.  If the exponent is
+zero, then the result is 1.  If the exponent is negative, then
+it is made positive and the base is divided into one.  The scale
+of the base is removed.
+.PP
+The integer exponent is viewed as a binary number.
+The base is repeatedly squared and the result is
+obtained as a product of those powers of the base that
+correspond to the positions of the one-bits in the binary
+representation of the exponent.
+Enough digits of the result
+are removed to make the scale of the result the same as if the
+indicated multiplication had been performed.
+.SH
+Input Conversion and Base
+.PP
+Numbers are converted to the internal representation as they are read
+in.
+The scale stored with a number is simply the number of fractional digits input.
+Negative numbers are indicated by preceding the number with a \fB\_\fP.
+The hexadecimal digits A\-F correspond to the numbers 10\-15 regardless of input base.
+The \fBi\fP command can be used to change the base of the input numbers.
+This command pops the stack, truncates the resulting number to an integer,
+and uses it as the input base for all further input.
+The input base is initialized to 10 but may, for example be changed to
+8 or 16 to do octal or hexadecimal to decimal conversions.
+The command \fBI\fP will push the value of the input base on the stack.
+.SH
+Output Commands
+.PP
+The command \fBp\fP causes the top of the stack to be printed.
+It does not remove the top of the stack.
+All of the stack and internal registers can be output
+by typing the command \fBf\fP.
+The \fBo\fP command can be used to change the output base.
+This command uses the top of the stack, truncated to an integer as
+the base for all further output.
+The output base in initialized to 10.
+It will work correctly for any base.
+The command \fBO\fP pushes the value of the output base on the stack.
+.SH
+Output Format and Base
+.PP
+The input and output bases only affect
+the interpretation of numbers on input and output; they have no
+effect on arithmetic computations.
+Large numbers are output with 70 characters per line;
+a \\ indicates a continued line.
+All choices of input and output bases work correctly, although not all are
+useful.
+A particularly useful output base is 100000, which has the effect of
+grouping digits in fives.
+Bases of 8 and 16 can be used for decimal-octal or decimal-hexadecimal
+conversions.
+.SH
+Internal Registers
+.PP
+Numbers or strings may be stored in internal registers or loaded on the stack
+from registers with the commands \fBs\fP and \fBl\fP.
+The command \fBs\fIx\fR pops the top of the stack and
+stores the result in register \fBx\fP.
+\fIx\fP can be any character.
+\fBl\fIx\fR puts the contents of register \fBx\fP on the top of the stack.
+The \fBl\fP command has no effect on the contents of register \fIx\fP.
+The \fBs\fP command, however, is destructive.
+.SH
+Stack Commands
+.PP
+The command \fBc\fP clears the stack.
+The command \fBd\fP pushes a duplicate of the number on the top of the stack
+on the stack.
+The command \fBz\fP pushes the stack size on the stack.
+The command \fBX\fP replaces the number on the top of the stack
+with its scale factor.
+The command \fBZ\fP replaces the top of the stack
+with its length.
+.SH
+Subroutine Definitions and Calls
+.PP
+Enclosing a string in \fB[]\fP pushes the ascii string on the stack.
+The \fBq\fP command quits or in executing a string, pops the recursion levels by two.
+.SH
+Internal Registers \- Programming DC
+.PP
+The load and store
+commands together with \fB[]\fP to store strings, \fBx\fP to execute
+and the testing commands `<', `>', `=', `!<', `!>', `!=' can be used to program
+DC.
+The \fBx\fP command assumes the top of the stack is an string of DC commands
+and executes it.
+The testing commands compare the top two elements on the stack and if the relation holds, execute the register
+that follows the relation.
+For example, to print the numbers 0-9,
+.DS
+[lip1+  si  li10>a]sa
+0si  lax
+.DE
+.SH
+Push-Down Registers and Arrays
+.PP
+These commands were designed for used by a compiler, not by
+people.
+They involve push-down registers and arrays.
+In addition to the stack that commands work on, DC can be thought
+of as having individual stacks for each register.
+These registers are operated on by the commands \fBS\fP and \fBL\fP.
+\fBS\fIx\fR pushes the top value of the main stack onto the stack for
+the register \fIx\fP.
+\fBL\fIx\fR pops the stack for register \fIx\fP and puts the result on the main
+stack.
+The commands \fBs\fP and \fBl\fP also work on registers but not as push-down
+stacks.
+\fBl\fP doesn't effect the top of the
+register stack, and \fBs\fP destroys what was there before.
+.PP
+The commands to work on arrays are \fB:\fP and \fB;\fP.
+\fB:\fIx\fR pops the stack and uses this value as an index into
+the array \fIx\fP.
+The next element on the stack is stored at this index in \fIx\fP.
+An index must be greater than or equal to 0 and
+less than 2048.
+\fB;\fIx\fR is the command to load the main stack from the array \fIx\fP.
+The value on the top of the stack is the index
+into the array \fIx\fP of the value to be loaded.
+.SH
+Miscellaneous Commands
+.PP
+The command \fB!\fP interprets the rest of the line as a 
+.UX
+ command and passes
+it to 
+.UX
+to execute.
+One other compiler command is \fBQ\fP.
+This command uses the top of the stack as the number of levels of recursion to skip.
+.SH
+DESIGN CHOICES
+.PP
+The real reason for the use of a dynamic storage allocator was
+that a general purpose program could be (and in fact has been)
+used for a variety of other tasks.
+The allocator has some value for input and for compiling (i.e.
+the bracket [...] commands) where it cannot be known in advance
+how long a string will be.
+The result was that at a modest
+cost in execution time, all considerations of string allocation
+and sizes of strings were removed from the remainder of the program
+and debugging was made easier.  The allocation method
+used wastes approximately 25% of available space.
+.PP
+The choice of 100 as a base for internal arithmetic
+seemingly has no compelling advantage.  Yet the base cannot
+exceed 127 because of hardware limitations and at the cost
+of 5% in space, debugging was made a great deal easier and
+decimal output was made much faster.
+.PP
+The reason for a stack-type arithmetic design was
+to permit all DC commands from addition to subroutine execution
+to be implemented in essentially the same way.  The result
+was a considerable degree of logical separation of the final
+program into modules with very little communication between
+modules.
+.PP
+The rationale for the lack of interaction between the scale and the bases
+was to provide an understandable means of proceeding after
+a change of base or scale when numbers had already been entered.
+An earlier implementation which had global notions of
+scale and base did not work out well.
+If the value of
+.ft B
+scale
+.ft
+were to be interpreted in the current
+input or output base,
+then a change of base or scale in the midst of a
+computation would cause great confusion in the interpretation
+of the results.
+The current scheme has the advantage that the value of
+the input and output bases
+are only used for input and output, respectively, and they
+are ignored in all other operations.
+The value of
+scale
+is not used for any essential purpose by any part of the program
+and it is used only to prevent the number of
+decimal places resulting from the arithmetic operations from
+growing beyond all bounds.
+.PP
+The design rationale for the choices for the scales of
+the results of arithmetic were that in no case should
+any significant digits be thrown away if, on appearances, the
+user actually wanted them.  Thus, if the user wants
+to add the numbers 1.5 and 3.517, it seemed reasonable to give
+him the result 5.017 without requiring him to unnecessarily
+specify his rather obvious requirements for precision.
+.PP
+On the other hand, multiplication and exponentiation produce
+results with many more digits than their operands and it
+seemed reasonable to give as a minimum the number of decimal
+places in the operands but not to give more than that
+number of digits
+unless the user asked for them by specifying a value for \fBscale\fP.
+Square root can be handled in just the same way as multiplication.
+The operation of division gives arbitrarily many decimal places
+and there is simply no way to guess how many places the user
+wants.
+In this case only, the user must
+specify a \fBscale\fP to get any decimal places at all.
+.PP
+The scale of remainder was chosen to make it possible
+to recreate the dividend from the quotient and remainder.
+This is easy to implement; no digits are thrown away.
+.SH
+References
+.IP [1]
+L. L. Cherry, R. Morris,
+.ft I
+BC \- An Arbitrary Precision Desk-Calculator Language.
+.ft
+.IP [2]
+K. C. Knowlton,
+.ft I
+A Fast Storage Allocator,
+.ft
+Comm. ACM \fB8\fP, pp. 623-625 (Oct. 1965).
diff --git a/doc/7thEdMan/vol2/edtut.bun b/doc/7thEdMan/vol2/edtut.bun
new file mode 100644 (file)
index 0000000..97a3329
--- /dev/null
@@ -0,0 +1,2124 @@
+# To unbundle, run this file
+echo e.mac
+sed 's/.//' >e.mac <<'//GO.SYSIN DD e.mac'
+-.ds . \&\s+2.\s0\&
+-.de UC
+-\&\\$3\s-1\\$1\s0\\$2
+-..
+-.de UL
+-.if t \&\\$3\f3\\$1\f1\\$2
+-.if n \&\\$3\f2\\$1\f1\\$2
+-..
+-.de IT
+-\&\\$3\f2\\$1\fP\\$2
+-..
+-.de UI
+-\f3\\$1\fI\\$2\fR\\$3
+-..
+-.de P1
+-.if n .ls 1
+-.nf
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ta .3i .6i .9i 1.2i 1.5i 1.8i
+-.tr -\-
+-.             use first argument as indent if present
+-.if \\n(.$ .DS I \\$1
+-.if !\\n(.$ .DS I 5
+-.bd 1 2
+-..
+-.de P2
+-.br
+-.bd 1 2
+-.DE
+-.bd 1
+-.tr --
+-.if n .ls 2
+-..
+-.hy 14
+-.     2=not last lines; 4= no -xx; 8=no xx-
+-.tr *\(**
+-.nr PI .2i
+//GO.SYSIN DD e.mac
+echo e0
+sed 's/.//' >e0 <<'//GO.SYSIN DD e0'
+-.RP
+-.TL
+-A Tutorial Introduction to the \s-2UNIX\s+2 Text Editor
+-.AU
+-Brian W. Kernighan
+-.AI
+-.MH
+-.AB
+-.PP
+-Almost all text input on
+-the
+-.UX
+-operating system
+-is done with
+-the text-editor
+-.IT ed .
+-This memorandum is a tutorial guide
+-to help beginners get started
+-with text editing.
+-.PP
+-Although it does not cover everything,
+-it does discuss enough for most users'
+-day-to-day needs.
+-This includes
+-printing, appending, changing, deleting, moving and inserting entire lines of text;
+-reading and writing files;
+-context searching and line addressing;
+-the substitute command;
+-the global commands;
+-and the use of special characters for advanced editing.
+-.AE
+//GO.SYSIN DD e0
+echo e1
+sed 's/.//' >e1 <<'//GO.SYSIN DD e1'
+-.nr PS 9
+-.nr VS 11
+-.if t .2C
+-.SH
+-Introduction
+-.PP
+-.ul
+-Ed
+-is a ``text editor'', that is, an interactive program
+-for creating and modifying ``text'',
+-using directions provided by a user at
+-a terminal.
+-The text is often a document
+-like this one,
+-or a program
+-or perhaps data for a program.
+-.PP
+-This introduction is meant to simplify learning
+-.ul
+-ed.
+-The recommended way to learn
+-.ul
+-ed
+-is to read this document,
+-simultaneously using
+-.ul
+-ed
+-to follow the examples,
+-then to read the description in section I of the
+-.ul
+-.UC UNIX
+-.ul
+-Programmer's Manual,
+-all the while
+-experimenting with
+-.ul
+-ed.
+-(Solicitation of advice from experienced users is also useful.)
+-.PP
+-Do the exercises!
+-They cover material not completely discussed
+-in the actual text.
+-An appendix summarizes the commands.
+-.SH
+-Disclaimer
+-.PP
+-This is an introduction and a tutorial.
+-For this reason, no attempt is made to
+-cover more than a part of the facilities that
+-.ul
+-ed
+-offers
+-(although this fraction includes the most useful and frequently used
+-parts).
+-When you have mastered the Tutorial,
+-try
+-.ul
+-Advanced Editing on
+-.ul
+-.UC UNIX .
+-Also,
+-there is not enough space to explain basic
+-.UC UNIX
+-procedures.
+-We will assume that you know how to log on to
+-.UC UNIX ,
+-and that you have at least a vague understanding
+-of what a file is.
+-For more on that, read
+-.ul
+-.UC UNIX
+-.ul
+-for Beginners.
+-.PP
+-You must also know what character to type as the end-of-line
+-on your particular terminal.
+-This character is the
+-.UC RETURN
+-key on most terminals.
+-Throughout, we will refer to this character,
+-whatever it is,
+-as
+-.UC RETURN .
+-.SH
+-Getting Started
+-.PP
+-We'll assume that you have logged in to
+-your system
+-and it has just printed the prompt character,
+-usually either a
+-.UL $
+-or a
+-.UL % .
+-The
+-easiest way to get
+-.ul
+-ed
+-is to type
+-.P1
+-ed    (followed by a return)
+-.P2
+-You are now ready to go \-
+-.ul
+-ed
+-is waiting for you to tell it what to do.
+-.SH
+-Creating Text \- the Append command ``a''
+-.PP
+-As your first problem, suppose you want to create some text
+-starting from scratch.
+-Perhaps you are typing the very first
+-draft of a paper; clearly it will have to start
+-somewhere, and undergo modifications later.
+-This section will show how to get some text in, just to
+-get started.
+-Later we'll talk about how to change it.
+-.PP
+-When
+-.ul
+-ed
+-is first started, it is rather like working
+-with a blank piece of paper \- there is no text
+-or information present.
+-This must be supplied by the person using
+-.ul
+-ed;
+-it is usually done
+-by typing in the text, or by reading it into
+-.ul
+-ed
+-from a
+-file.
+-We will start by typing in some text, and return shortly to how to
+-read files.
+-.PP
+-First a bit of terminology.
+-In
+-.ul
+-ed
+-jargon, the text being
+-worked on is said to be ``kept in a buffer.''
+-Think of the
+-buffer as a work space, if you like, or simply as the information
+-that you are going to be editing.
+-In effect the buffer is like the
+-piece of paper, on which we will write things, then change some
+-of them, and finally file the whole thing away for another day.
+-.PP
+-The user tells
+-.ul
+-ed
+-what to do to his text
+-by typing instructions called ``commands.''
+-Most
+-commands consist of a single letter,
+-which must be typed in lower case.
+-Each command is typed
+-on a separate line.
+-(Sometimes the command is preceded by information
+-about what line or lines of text are to be affected \-
+-we will discuss these shortly.)
+-.ul
+-Ed
+-makes no response
+-to most commands \- there is no prompting
+-or typing of messages like ``ready''.
+-(This silence is preferred
+-by experienced users, but sometimes a hangup for beginners.)
+-.PP
+-The first command is
+-.ul
+-append,
+-written as the letter
+-.P1
+-a
+-.P2
+-all
+-by itself.
+-It means ``append (or add) text lines to the buffer,
+-as I type them in.''
+-Appending is rather like
+-writing fresh material on a piece of paper.
+-.PP
+-So to enter lines of text into the buffer,
+-just type an
+-.UL a
+-followed by a
+-.UC RETURN ,
+-followed by the lines of text you want, like this:
+-.P1
+-a
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-\*.
+-.P2
+-.PP
+-The only way to stop appending is to type a
+-line that contains only a period.
+-The ``\*.'' is used
+-to tell
+-.ul
+-ed
+-that you have finished appending.
+-(Even experienced users forget that terminating ``\*.''
+-sometimes.
+-If
+-.ul
+-ed
+-seems to be ignoring you,
+-type an extra line with just ``\*.'' on it.
+-You may then find you've added some garbage lines
+-to your text, which you'll have to take out later.)
+-.PP
+-After the append command has been done, the buffer will
+-contain the three lines
+-.P1
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-.P2
+-The
+-.UL a '' ``
+-and ``\*.'' aren't there, because they are
+-not text.
+-.PP
+-To add more text to what you already have,
+-just issue another
+-.UL a
+-command, and continue typing.
+-.SH
+-Error Messages \- ``?''
+-.PP
+-If at any time you make an error in the commands you type to
+-.ul
+-ed,
+-it will tell you by typing
+-.P1
+-?
+-.P2
+-This is about as cryptic as it can be,
+-but with practice, you can usually
+-figure out how you goofed.
+//GO.SYSIN DD e1
+echo e2
+sed 's/.//' >e2 <<'//GO.SYSIN DD e2'
+-.SH
+-Writing text out as a file \- the Write command ``w''
+-.PP
+-It's likely that you'll want to save your text for later use.
+-To write out the contents of the buffer onto a file,
+-use the
+-.ul
+-write
+-command
+-.P1
+-w
+-.P2
+-followed by the filename you want to write on.
+-This will copy the buffer's contents
+-onto the specified file
+-(destroying any previous information on the file).
+-To save
+-the text on a file named
+-.UL junk ,
+-for example, type
+-.P1
+-w junk
+-.P2
+-Leave a space between
+-.UL w
+-and the file name.
+-.ul
+-Ed
+-will respond by printing
+-the number of characters it wrote out.
+-In this case,
+-.ul
+-ed
+-would respond with
+-.P1
+-68
+-.P2
+-(Remember that blanks and the return character at the end of each
+-line are included in the character count.)
+-Writing a file just makes a copy of the text \- the
+-buffer's contents are not disturbed, so you can go on adding
+-lines to it.
+-This is an important point.
+-.ul
+-Ed
+-at all times works on a copy
+-of a file, not the file itself.
+-No change in the contents
+-of a file takes place until you give a
+-.UL w
+-command.
+-(Writing out the text onto a file from time to time as it is being
+-created is a good idea, since if the system crashes or if you make some horrible mistake, you will lose
+-all the text in the buffer but any text that was written onto
+-a file is relatively safe.)
+-.SH
+-Leaving ed \- the Quit command ``q''
+-.PP
+-To terminate a session with
+-.IT ed ,
+-save the text you're working on
+-by writing it onto a file using the
+-.UL w
+-command,
+-and then type the command
+-.P1
+-q
+-.P2
+-which
+-stands for
+-.IT quit .
+-The system will respond with
+-the prompt character
+-.UL $ "" (
+-or
+-.UL % ).
+-At
+-this point your buffer vanishes, with all its text,
+-which is why you want to write it out before quitting.\(dg
+-.FS
+-\(dg Actually,
+-.IT ed
+-will print 
+-.UL ?
+-if you try to quit without writing.
+-At that point, write if you want;
+-if not, another
+-.UL q
+-will get you out regardless.
+-.FE
+-.SH
+-Exercise 1:
+-.PP
+-Enter
+-.ul
+-ed
+-and
+-create some text using
+-.P1
+-a
+-\&. . . text . . .
+-\&\fB.\fR
+-.P2
+-Write it out using
+-.UL w .
+-Then leave
+-.ul
+-ed
+-with the
+-.UL q
+-command, and print the file,
+-to see that everything worked.
+-(To print a file, say
+-.P1
+-pr filename
+-.P2
+-or
+-.P1
+-cat filename
+-.P2
+-in response to
+-the prompt character.
+-Try both.)
+-.SH
+-Reading text from a file \- the Edit command ``e''
+-.PP
+-A common way to get text into the buffer is to read it
+-from a file in the file system.
+-This is what you do to edit text
+-that you saved with the 
+-.UL w
+-command in a previous session.
+-The
+-.ul
+-edit
+-command
+-.UL e
+-fetches the entire contents of a file into the buffer.
+-So if you had saved the three lines
+-``Now is the time'', etc.,
+-with a
+-.UL w
+-command in an earlier session,
+-the 
+-.ul
+-ed
+-command
+-.P1
+-e junk
+-.P2
+-would fetch the entire contents of the file
+-.UL junk
+-into the buffer, and respond
+-.P1
+-68
+-.P2
+-which is the number of characters in
+-.UL junk .
+-.ul
+-If anything was already in the buffer, it is deleted first.
+-.PP
+-If you use the
+-.UL e
+-command to read a file into the buffer,
+-then you need not use a file name after a subsequent
+-.UL w
+-command;
+-.ul
+-ed
+-remembers the last file name used in an
+-.UL e
+-command,
+-and
+-.UL w
+-will write on this file.
+-Thus a good way to operate is
+-.P1
+-ed
+-e file
+-[editing session]
+-w
+-q
+-.P2
+-This way, you can simply say
+-.UL w
+-from time to time,
+-and be secure in the knowledge that
+-if you got the file name right at the beginning,
+-you are writing into the proper file each time.
+-.PP
+-You can find out at any time what file name
+-.ul
+-ed
+-is remembering by typing the 
+-.ul
+-file
+-command
+-.UL f .
+-In this example,
+-if you typed
+-.P1
+-f
+-.P2
+-.ul
+-ed
+-would reply
+-.P1
+-junk
+-.P2
+-.SH
+-Reading text from a file \- the Read command ``r''
+-.PP
+-Sometimes you want to read a file into the buffer
+-without destroying anything that is already there.
+-This is done by the
+-.ul
+-read
+-command
+-.UL r .
+-The command
+-.P1
+-r junk
+-.P2
+-will read the file
+-.UL junk
+-into the buffer;
+-it adds it
+-to the end of whatever is already in the buffer.
+-So if you do a read after
+-an edit:
+-.P1
+-e junk
+-r junk
+-.P2
+-the buffer will contain
+-.ul
+-two
+-copies of the text (six lines).
+-.P1
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-.P2
+-Like the
+-.UL w
+-and
+-.UL e
+-commands,
+-.UL r
+-prints
+-the
+-number of characters read in, after the reading operation is complete.
+-.PP
+-Generally speaking,
+-.UL r
+-is much less used than
+-.UL e .
+-.SH
+-Exercise 2:
+-.PP
+-Experiment with the
+-.UL e
+-command \-
+-try reading and printing various files.
+-You may get an error
+-.UL ?name ,
+-where
+-.UL name
+-is the name of a file;
+-this means that the file doesn't exist,
+-typically because you spelled the file name wrong,
+-or perhaps that you are not allowed to read or write it.
+-Try alternately reading and appending to see that they work
+-similarly.
+-Verify that
+-.P1
+-ed filename
+-.P2
+-is exactly equivalent to
+-.P1
+-ed
+-e filename
+-.P2
+-What does
+-.P1
+-f filename
+-.P2
+-do?
+-.SH
+-Printing the contents of the buffer \- the Print command ``p''
+-.PP
+-To
+-.ul
+-print
+-or list the contents of the buffer (or parts
+-of it) on the terminal, use the print command
+-.P1
+-p
+-.P2
+-The way this is done is as follows.
+-Specify the lines where
+-you want printing to begin and where you want it to end,
+-separated by a comma, and
+-followed by the letter
+-.UL p .
+-Thus to print the first two lines of the buffer, for
+-example, (that is, lines 1 through 2) say
+-.P1
+-1,2p  (starting line=1, ending line=2 p)
+-.P2
+-.ul
+-Ed
+-will respond with
+-.P1
+-Now is the time
+-for all good men
+-.P2
+-.PP
+-Suppose you want to print
+-.ul
+-all
+-the lines in the buffer.
+-You could use
+-.UL 1,3p
+-as above if you knew there were exactly
+-3 lines in the buffer.
+-But in general, you don't
+-know how many there are, so what do you use for the ending
+-line number?
+-.ul
+-Ed
+-provides a shorthand symbol for ``line number of
+-last line in buffer'' \- the dollar sign
+-.UL $ .
+-Use it this
+-way:
+-.P1
+-1,$p
+-.P2
+-This will print
+-.ul
+-all
+-the lines in the buffer (line 1 to last line.)
+-If you want to stop the printing before it is finished,
+-push the
+-.UC DEL
+-or Delete key;
+-.ul
+-ed
+-will type
+-.P1
+-?
+-.P2
+-and wait for the next command.
+-.PP
+-To print the
+-.ul
+-last
+-line of the buffer, you could use
+-.P1
+-$,$p
+-.P2
+-but
+-.ul
+-ed
+-lets you abbreviate this to
+-.P1
+-$p
+-.P2
+-You can print any single line by typing the line
+-number followed by a
+-.UL p .
+-Thus
+-.P1
+-1p
+-.P2
+-produces the response
+-.P1
+-Now is the time
+-.P2
+-which is the first line of the buffer.
+-.PP
+-In fact,
+-.ul
+-ed
+-lets you abbreviate even further:
+-you can print any single line by typing
+-.ul
+-just
+-the line number \- no need to type the letter
+-.UL p .
+-So if you say
+-.P1
+-$
+-.P2
+-.ul
+-ed
+-will print the last line of the buffer.
+-.PP
+-You can also use
+-.UL $
+-in combinations like
+-.P1
+-$\-1,$p
+-.P2
+-which prints the last two lines of the buffer.
+-This helps when you want to see how far you got in typing.
+-.SH
+-Exercise 3:
+-.PP
+-As before, create some text using the
+-.UL a
+-command and
+-experiment with the
+-.UL p
+-command.
+-You will find, for example,
+-that you can't print line 0 or a line beyond
+-the end of the buffer, and that attempts
+-to print a buffer in reverse order by saying
+-.P1
+-3,1p
+-.P2
+-don't work.
+//GO.SYSIN DD e2
+echo e3
+sed 's/.//' >e3 <<'//GO.SYSIN DD e3'
+-.SH
+-The current line \- ``Dot'' or ``.''
+-.PP
+-Suppose your buffer still contains the six lines as above,
+-that you have just typed
+-.P1
+-1,3p
+-.P2
+-and
+-.ul
+-ed
+-has printed the three lines for you.
+-Try typing just
+-.P1
+-p     (no line numbers)
+-.P2
+-This will print
+-.P1
+-to come to the aid of their party.
+-.P2
+-which is the third line of the buffer.
+-In fact it is the last
+-(most recent) line that you have done anything with.
+-(You just printed it!)
+-You can
+-repeat this
+-.UL p
+-command without line numbers, and
+-it will continue to print line 3.
+-.PP
+-The reason is that
+-.ul
+-ed
+-maintains a record of the last line
+-that you did anything to (in this case, line 3, which you
+-just printed) so that it can be used instead of an explicit
+-line number.
+-This most recent line is referred to by the
+-shorthand symbol
+-.P1
+-\&\*. (pronounced ``dot'').
+-.P2
+-Dot is a line number in the same way that
+-.UL $
+-is; it means
+-exactly ``the current line'', or loosely,
+-``the line you most recently did something to.''
+-You
+-can use it in several ways \- one possibility
+-is to say
+-.P1
+-\&\*.,$p
+-.P2
+-This will print all the lines from (including) the current
+-line to the
+-end of the buffer.
+-In our example these are lines 3 through 6.
+-.PP
+-Some commands change the value of dot, while others do not.
+-The
+-.UL p
+-command sets dot to the number of the last line printed;
+-the last command will
+-set both
+-\*.
+-and
+-.UL $
+-to 6.
+-.PP
+-Dot is most useful when used in combinations like this one:
+-.P1
+-\&\*.+1       (or equivalently, \*.+1p)
+-.P2
+-This means ``print the next line'' and is a handy way to step
+-slowly through a buffer.
+-You can also say
+-.P1
+-\&\*.\-1      (or \*.\-1p )
+-.P2
+-which means ``print the line
+-.ul
+-before
+-the current line.''
+-This enables you to go backwards if you wish.
+-Another useful one is something like
+-.P1
+-\&\*.\-3,\*.\-1p
+-.P2
+-which prints the previous three lines.
+-.PP
+-Don't forget that all of these change the value of dot.
+-You can find out what dot is at any time by typing
+-.P1
+-\&\*.=
+-.P2
+-.ul
+-Ed
+-will respond by printing the value of dot.
+-.PP
+-Let's summarize some things about the
+-.UL p
+-command
+-and dot.
+-Essentially
+-.UL p
+-can be preceded by 0, 1, or 2 line numbers.
+-If there is no line number given, it prints the ``current line'',
+-the line that dot refers to.
+-If there is one line number given
+-(with or without the letter
+-.UL p ),
+-it prints that line (and dot is set there); and if there
+-are two line numbers, it prints all the lines in that range
+-(and sets dot to the last line printed.)
+-If two line numbers are specified
+-the first can't be bigger than the second (see Exercise 2.)
+-.PP
+-Typing a single return will cause printing of the next line \-
+-it's
+-equivalent to
+-.UL .+1p .
+-Try it.
+-Try typing
+-a
+-.UL \- ;
+-you will find that
+-it's equivalent to
+-.UL .\-1p .
+-.SH
+-Deleting lines: the ``d'' command
+-.PP
+-Suppose you want to get rid of the three extra lines in the buffer.
+-This is done by the
+-.ul
+-delete
+-command
+-.P1
+-d
+-.P2
+-Except that
+-.UL d
+-deletes lines instead of printing them,
+-its action is similar to that of
+-.UL p .
+-The lines to be deleted are specified for
+-.UL d
+-exactly as they are for
+-.UL p :
+-.P1
+-\fIstarting line, ending line\fP d
+-.P2
+-Thus the command
+-.P1
+-4,$d
+-.P2
+-deletes lines 4 through the end.
+-There are now three lines left, as you can check by using
+-.P1
+-1,$p
+-.P2
+-And notice that
+-.UL $
+-now is line 3!
+-Dot
+-is set to the next line after the last line deleted,
+-unless the last line deleted is the last line in the buffer.
+-In that case, dot is set to
+-.UL $ .
+-.SH
+-Exercise 4:
+-.PP
+-Experiment with
+-.UL a ,
+-.UL e ,
+-.UL r ,
+-.UL w ,
+-.UL p
+-and
+-.UL d
+-until you are sure that you
+-know what they do, and until you understand how dot,
+-.UL $ ,
+-and
+-line numbers are used.
+-.PP
+-If you are adventurous, try using line numbers with
+-.UL a ,
+-.UL r
+-and
+-.UL w
+-as well.
+-You will find that
+-.UL a
+-will append lines
+-.ul
+-after
+-the line number that you specify (rather than after dot); that
+-.UL r
+-reads
+-a file in
+-.ul
+-after
+-the line number you specify (not necessarily
+-at the end of the buffer); and that
+-.UL w
+-will write out exactly the lines
+-you specify, not necessarily the whole buffer.
+-These variations are sometimes handy.
+-For instance you can insert a file at the beginning of a buffer
+-by saying
+-.P1
+-0r filename
+-.P2
+-and you can enter lines at the beginning of the buffer
+-by saying
+-.P1
+-0a
+-\&. . . \fItext\fP . . .
+-\*.
+-.P2
+-Notice that
+-.UL .w
+-is
+-.ul
+-very
+-different from
+-.P1
+-\*.
+-w
+-.P2
+-.SH
+-Modifying text: the Substitute command ``s''
+-.PP
+-We are now ready to try one of the most important
+-of all commands \- the substitute command
+-.P1
+-s
+-.P2
+-This is the command
+-that is used to change individual
+-words or letters within a line or group of lines.
+-It is what you use, for example, for correcting spelling
+-mistakes and typing errors.
+-.PP
+-Suppose that by a typing error, line 1 says
+-.P1
+-Now is th time
+-.P2
+-\- the
+-.IT e
+-has been left off
+-.IT the .
+-You can use
+-.UL s
+-to fix this up as follows:
+-.P1
+-1s/th/the/
+-.P2
+-This says: ``in line 1, substitute for the characters
+-.IT th
+-the characters
+-.IT the .''
+-To verify
+-that it works
+-.IT ed "" (
+-will not print
+-the result automatically) say
+-.P1
+-p
+-.P2
+-and get
+-.P1
+-Now is the time
+-.P2
+-which is what you wanted.
+-Notice that dot must have been set to the line
+-where the substitution took place, since the
+-.UL p
+-command
+-printed that line.
+-Dot is always set this way with the
+-.UL s
+-command.
+-.PP
+-The general way to use the substitute command is
+-.P1
+-\fIstarting\(hyline, ending\(hyline\fP s/\fIchange this\fP/\fIto this\fP/
+-.P2
+-Whatever string of characters is between the first pair of
+-slashes is replaced by whatever is between the second pair,
+-in
+-.ul
+-all
+-the lines between
+-.ul
+-starting-line
+-and
+-.ul
+-ending-line.
+-Only the first occurrence on each line is changed, however.
+-If you want to change
+-.ul
+-every
+-occurrence, see Exercise 5.
+-The rules for line numbers are the same as those for
+-.UL p ,
+-except that dot is set to the last line changed.
+-(But there is a trap for the unwary: if no substitution
+-took place, dot is
+-.ul
+-not
+-changed.
+-This causes an error
+-.UL ?
+-as a warning.)
+-.PP
+-Thus you can say
+-.P1
+-1,$s/speling/spelling/
+-.P2
+-and correct the first spelling mistake
+-on each line
+-in the text.
+-(This is useful for people who are consistent
+-misspellers!)
+-.PP
+-If no line numbers are given, the
+-.UL s
+-command assumes we mean
+-``make the substitution on line dot'', so it changes things only
+-on the current line.
+-This leads to the very common sequence
+-.P1
+-s/something/something else/p
+-.P2
+-which makes some correction on the
+-current line, and then prints it, to make sure it
+-worked out right.
+-If it didn't,
+-you can try again.
+-(Notice that there is
+-a
+-.UL p
+-on the same line as the
+-.UL s
+-command.
+-With few exceptions,
+-.UL p
+-can follow any command;
+-no other multi-command lines are legal.)
+-.PP
+-It's also legal to say
+-.P1
+-s/ . . . //
+-.P2
+-which means ``change the first
+-string of characters to
+-.IT nothing '', ``
+-i.e.,
+-remove them.
+-This is useful for deleting extra words in a line or removing extra
+-letters from words.
+-For instance, if you had
+-.P1
+-Nowxx is the time
+-.P2
+-you can say
+-.P1
+-s/xx//p
+-.P2
+-to get
+-.P1
+-Now is the time
+-.P2
+-Notice that
+-.UL //
+-(two adjacent slashes) means ``no characters'', not a blank.
+-There
+-.ul
+-is
+-a difference!
+-(See below for another meaning of
+-.UL // .)
+//GO.SYSIN DD e3
+echo e4
+sed 's/.//' >e4 <<'//GO.SYSIN DD e4'
+-.SH
+-Exercise 5:
+-.PP
+-Experiment with the substitute command.
+-See what happens if you
+-substitute for some word on a line with several occurrences of that word.
+-For example, do this:
+-.P1
+-a
+-the other side of the coin
+-\*.
+-s/the/on the/p
+-.P2
+-You will get
+-.P1
+-on the other side of the coin
+-.P2
+-A substitute command changes only the first occurrence of the first string.
+-You can change all occurrences by adding a
+-.UL g
+-(for ``global'')
+-to the
+-.UL s
+-command, like this:
+-.P1
+-s/ . . . / . . . /gp
+-.P2
+-Try other characters instead of slashes to delimit the two sets
+-of characters in the
+-.UL s
+-command \- anything should work
+-except blanks or tabs.
+-.PP
+-(If you get funny results using any of the characters
+-.P1
+-^    \*.    $    [    *    \e    &
+-.P2
+-read the section on ``Special Characters''.)
+-.SH
+-Context searching \- ``/ . . . /''
+-.PP
+-With the substitute command mastered, you can move on to
+-another highly important idea of
+-.ul
+-ed
+-\- context searching.
+-.PP
+-Suppose you have the original three line text in the buffer:
+-.P1
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-.P2
+-Suppose you want to find the line that contains
+-.IT their
+-so
+-you can change it to
+-.IT the .
+-Now with only three lines in the buffer, it's pretty easy
+-to keep track of what line the word
+-.IT their
+-is on.
+-But if the buffer contained several hundred lines,
+-and you'd been making changes, deleting and rearranging lines,
+-and so on, you would no longer really know what this line
+-number would be.
+-Context searching is simply a method of specifying the desired line,
+-regardless of what its number is,
+-by specifying some context on it.
+-.PP
+-The way to say ``search for a line
+-that contains this particular string of characters''
+-is to type
+-.P1
+-/\fIstring of characters we want to find\fP/
+-.P2
+-For example,
+-the
+-.ul
+-ed
+-command
+-.P1
+-/their/
+-.P2
+-is a context search which
+-is sufficient to find the desired line \-
+-it will locate the next occurrence of
+-the characters between slashes (``their'').
+-It also sets dot to that line
+-and prints the line for verification:
+-.P1
+-to come to the aid of their party.
+-.P2
+-``Next occurrence'' means that
+-.ul
+-ed
+-starts looking for the string at line
+-.UL .+1 ,
+-searches to the end of the buffer,
+-then continues at line 1 and searches to line dot.
+-(That is, the search ``wraps around'' from
+-.UL $
+-to
+-1.)
+-It scans all the lines in the buffer until it either finds the desired line
+-or gets back to dot again.
+-If the given string of characters can't be found in any line,
+-.ul
+-ed
+-types the error message
+-.P1
+-?
+-.P2
+-Otherwise it prints the line it found.
+-.PP
+-You can do both the search for the desired line
+-.ul
+-and
+-a
+-substitution all at once, like this:
+-.P1
+-/their/s/their/the/p
+-.P2
+-which will yield
+-.P1
+-to come to the aid of the party.
+-.P2
+-There were three parts to that last command:
+-context search for the desired line, make the substitution, print the line.
+-.PP
+-The expression
+-.UL /their/
+-is a context search expression.
+-In their simplest form,
+-all context search expressions are like this \-
+-a string of characters surrounded by slashes.
+-Context searches are interchangeable with line numbers,
+-so they can be used by themselves to find and print a desired line,
+-or as line numbers for some other command, like
+-.UL s .
+-They were used both ways in the examples above.
+-.PP
+-Suppose the buffer contains the three familiar lines
+-.P1
+-Now is the time
+-for all good men
+-to come to the aid of their party.
+-.P2
+-Then the
+-.ul
+-ed
+-line numbers
+-.P1
+-/Now/+1
+-/good/
+-/party/\-1
+-.P2
+-are all context search expressions, and they all refer
+-to the same line (line 2).
+-To make a change in line 2,
+-you could say
+-.P1
+-/Now/+1s/good/bad/
+-.P2
+-or
+-.P1
+-/good/s/good/bad/
+-.P2
+-or
+-.P1
+-/party/\-1s/good/bad/
+-.P2
+-The choice is dictated only by convenience.
+-You could print all three lines by, for instance
+-.P1
+-/Now/,/party/p
+-.P2
+-or
+-.P1
+-/Now/,/Now/+2p
+-.P2
+-or by any number of similar combinations.
+-The first one of these might be better if you don't
+-know how many lines are involved.
+-(Of course, if there were only three lines in the buffer,
+-you'd use
+-.P1
+-1,$p
+-.P2
+-but not if there were several hundred.)
+-.PP
+-The basic rule is: a context search expression is
+-.ul
+-the same as
+-a line number, so it can be used wherever a line number is needed.
+-.SH
+-Exercise 6:
+-.PP
+-Experiment with context searching.
+-Try a body of text with
+-several occurrences
+-of the same string of characters, and scan through it using
+-the same context search.
+-.PP
+-Try using context searches as line numbers for the
+-substitute, print and delete commands.
+-(They can also be used
+-with
+-.UL r ,
+-.UL w ,
+-and
+-.UL a .)
+-.PP
+-Try context searching using
+-.UL ?text?
+-instead of
+-.UL /text/ .
+-This scans lines in the buffer in reverse order
+-rather than normal.
+-This is
+-sometimes useful if you go too far while looking for some
+-string of characters \- it's an easy way to back up.
+-.PP
+-(If you get funny results with any of the characters
+-.P1
+-^    \*.    $    [    *    \e    &
+-.P2
+-read the section on ``Special Characters''.)
+-.PP
+-.ul
+-Ed
+-provides a shorthand for repeating a context search
+-for the same string.
+-For example,
+-the
+-.ul
+-ed
+-line number
+-.P1
+-/string/
+-.P2
+-will find the next occurrence of
+-.UL string .
+-It often happens that this is not the desired line,
+-so the search must be repeated.
+-This can be done by typing merely
+-.P1
+-//
+-.P2
+-This shorthand stands for ``the most recently used
+-context search expression.''
+-It can
+-also be used as the first string of the substitute
+-command, as in
+-.P1
+-/string1/s//string2/
+-.P2
+-which will find the next occurrence of
+-.UL string1
+-and replace it by
+-.UL string2 .
+-This can save a lot of typing.
+-Similarly
+-.P1
+-??
+-.P2
+-means ``scan backwards for the same expression.''
+//GO.SYSIN DD e4
+echo e5
+sed 's/.//' >e5 <<'//GO.SYSIN DD e5'
+-.SH
+-Change and Insert \- ``c'' and ``i''
+-.PP
+-This section discusses the
+-.ul
+-change
+-command
+-.P1
+-c
+-.P2
+-which is used to change
+-or replace a group of one or more lines,
+-and the
+-.ul
+-insert
+-command
+-.P1
+-i
+-.P2
+-which is used for inserting a group of one or more lines.
+-.PP
+-``Change'', written as
+-.P1
+-c
+-.P2
+-is used to replace a number of lines with different lines, which
+-are typed in at the terminal.
+-For example,
+-to change lines
+-.UL .+1
+-through
+-.UL $
+-to something else, type
+-.P1
+-\&.+1,$c
+-\&. . . \fItype the lines of text you want here\fP . . .
+-\*.
+-.P2
+-The lines you type between the
+-.UL c
+-command and
+-the 
+-.UL .
+-will take the place of the original lines between
+-start line and end line.
+-This is most useful in replacing a line
+-or several lines which have errors in them.
+-.PP
+-If only one line is specified in the
+-.UL c
+-command, then just
+-that line is replaced.
+-(You can type in as many replacement lines as you like.)
+-Notice
+-the use of
+-.UL .
+-to end the
+-input \- this works just like the
+-.UL .
+-in the append command
+-and must appear by itself on a new line.
+-If no line number is given, line dot is replaced.
+-The value of dot is set to the last line you typed in.
+-.PP
+-``Insert'' is similar to append \- for instance
+-.P1
+-/string/i
+-\&. . . \fItype the lines to be inserted here\fP . . .
+-\*.
+-.P2
+-will insert the given text
+-.ul
+-before
+-the next line that contains ``string''.
+-The text between
+-.UL i
+-and
+-.UL .
+-is
+-.ul
+-inserted before
+-the specified line.
+-If no line number is specified dot is used.
+-Dot is set to the last line inserted.
+-.SH
+-Exercise 7:
+-.PP
+-``Change'' is rather like a combination of
+-delete followed by insert.
+-Experiment to verify that
+-.P1
+-\fIstart, end\fP d
+-i
+-.ul
+-\&. . . text . . .
+-\*.
+-.P2
+-is almost the same as
+-.P1
+-\fIstart, end\fP c
+-.ul
+-\&. . . text . . .
+-\*.
+-.P2
+-These are not
+-.ul
+-precisely
+-the same
+-if line
+-.UL $
+-gets deleted.
+-Check this out.
+-What is dot?
+-.PP
+-Experiment with
+-.UL a
+-and
+-.UL i ,
+-to see that they are
+-similar, but not the same.
+-You will observe that
+-.P1
+-\fIline\(hynumber\fP a
+-\&. . . \fItext\fP . . .
+-\*.
+-.P2
+-appends
+-.ul
+-after
+-the given line, while
+-.P1
+-\fIline\(hynumber\fP i
+-\&. . . \fItext\fP . . .
+-\*.
+-.P2
+-inserts
+-.ul
+-before
+-it.
+-Observe that if no line number is given,
+-.UL i
+-inserts before line dot, while 
+-.UL a
+-appends
+-after line dot.
+-.SH
+-Moving text around: the ``m'' command
+-.PP
+-The move command 
+-.UL m
+-is used for cutting and pasting \-
+-it lets you move a group of lines
+-from one place to another in the buffer.
+-Suppose you want to put the first three lines of the buffer at the end instead.
+-You could do it by saying:
+-.P1
+-1,3w temp
+-$r temp
+-1,3d
+-.P2
+-(Do you see why?)
+-but you can do it a lot easier with the 
+-.UL m
+-command:
+-.P1
+-1,3m$
+-.P2
+-The general case is
+-.P1
+-\fIstart line, end line\fP m \fIafter this line\fP
+-.P2
+-Notice that there is a third line to be specified \-
+-the place where the moved stuff gets put.
+-Of course the lines to be moved can be specified
+-by context searches;
+-if you had
+-.P1
+-First paragraph
+-\&. . .
+-end of first paragraph.
+-Second paragraph
+-\&. . .
+-end of second paragraph.
+-.P2
+-you could reverse the two paragraphs like this:
+-.P1
+-/Second/,/end of second/m/First/\-1
+-.P2
+-Notice the
+-.UL \-1 :
+-the moved text goes
+-.ul
+-after
+-the line mentioned.
+-Dot gets set to the last line moved.
+-.SH
+-The global commands ``g'' and ``v''
+-.PP
+-The
+-.ul
+-global
+-command
+-.UL g
+-is used to execute one or more 
+-.ul
+-ed
+-commands on all those lines in the buffer
+-that match some specified string.
+-For example
+-.P1
+-g/peling/p
+-.P2
+-prints all lines that contain
+-.UL peling .
+-More usefully,
+-.P1
+-g/peling/s//pelling/gp
+-.P2
+-makes the substitution everywhere on the line,
+-then prints each corrected line.
+-Compare this to
+-.P1
+-1,$s/peling/pelling/gp
+-.P2
+-which only prints the last line substituted.
+-Another subtle difference is that
+-the
+-.UL g
+-command
+-does not give a
+-.UL ?
+-if
+-.UL peling
+-is not found
+-where the
+-.UL s
+-command will.
+-.PP
+-There may be several commands
+-(including
+-.UL a ,
+-.UL c ,
+-.UL i ,
+-.UL r ,
+-.UL w ,
+-but not
+-.UL g );
+-in that case,
+-every line except the last must end with a backslash
+-.UL \e :
+-.P1
+-g/xxx/\*.-1s/abc/def/\\
+-\&\*.+2s/ghi/jkl/\\
+-\&\*.-2,\*.p
+-.P2
+-makes changes in the lines before and after each line
+-that contains
+-.UL xxx ,
+-then prints all three lines.
+-.PP
+-The
+-.UL v
+-command is the same as
+-.UL g ,
+-except that the commands are executed on every line
+-that does
+-.ul
+-not
+-match the string following
+-.UL v :
+-.P1
+-v/ /d
+-.P2
+-deletes every line that does not contain a blank.
+//GO.SYSIN DD e5
+echo e6
+sed 's/.//' >e6 <<'//GO.SYSIN DD e6'
+-.SH
+-Special Characters
+-.PP
+-You may have noticed that things just don't work right when you used
+-some characters like
+-\*.,
+-.UL * ,
+-.UL $ ,
+-and others in
+-context searches and the substitute command.
+-The reason is rather complex, although the cure is simple.
+-Basically,
+-.ul
+-ed
+-treats these characters as special, with special meanings.
+-For instance,
+-.ul
+-in a context search or the first string of the substitute command only,
+-\*.
+-means ``any character,'' not a period, so
+-.P1
+-/x\*.y/
+-.P2
+-means ``a line with an
+-.UL x ,
+-.ul
+-any character,
+-and a
+-.UL y ,''
+-.ul
+-not
+-just ``a line with an
+-.UL x ,
+-a period, and a
+-.UL y .''
+-A complete list of the special characters
+-that can cause trouble is the following:
+-.P1
+-^    \*.    $    [    *    \e
+-.P2
+-.ul
+-Warning:
+-The backslash character
+-.UL \e
+-is special to
+-.ul
+-ed.
+-For safety's sake, 
+-avoid it where possible.
+-If you have to use one of the special characters
+-in a substitute command,
+-you can turn off its magic meaning temporarily
+-by preceding it with the backslash.
+-Thus
+-.P1
+-s/\e\e\e\*.\e*/backslash dot star/
+-.P2
+-will change
+-.UL \e.*
+-into ``backslash dot star''.
+-.PP
+-Here is a hurried synopsis of the other special characters.
+-First, the circumflex
+-.UL ^
+-signifies
+-the beginning of a line.
+-Thus
+-.P1
+-/^string/
+-.P2
+-finds
+-.UL string
+-only if it is at the beginning of a line:
+-it will find
+-.P1
+-string
+-.P2
+-but not
+-.P1
+-the string...
+-.P2
+-The dollar-sign
+-.UL $
+-is just the opposite of the circumflex;
+-it means the end of a line:
+-.P1
+-/string$/
+-.P2
+-will only find an occurrence of
+-.UL string
+-that is at the end of some line.
+-This implies, of course,
+-that
+-.P1
+-/^string$/
+-.P2
+-will find only a line that contains just
+-.UL string ,
+-and
+-.P1
+-/^\*.$/
+-.P2
+-finds a line containing exactly one character.
+-.PP
+-The character
+-.UL . ,
+-as we mentioned above,
+-matches anything;
+-.P1
+-/x\*.y/
+-.P2
+-matches any of
+-.P1
+-x+y
+-x-y
+-x y
+-x\*.y
+-.P2
+-This is useful in conjunction with
+-.UL * ,
+-which is a repetition character;
+-.UL a*
+-is a shorthand for ``any number of
+-.UL a 's,''
+-so 
+-.UL .*
+-matches any number of anythings.
+-This is used like this:
+-.P1
+-s/\*.*/stuff/
+-.P2
+-which changes an entire line,
+-or
+-.P1
+-s/\*.*,//
+-.P2
+-which deletes all characters in the line up to and
+-including the last comma.
+-(Since
+-.UL .*
+-finds the longest possible match,
+-this goes up to the last comma.)
+-.PP
+-.UL [
+-is used with
+-.UL ]
+-to form ``character classes'';
+-for example,
+-.P1
+-/[0123456789]/
+-.P2
+-matches any single digit \-
+-any one of the characters inside the braces
+-will cause a match.
+-This can be abbreviated to
+-.UL [0\-9] .
+-.PP
+-Finally, the
+-.UL &
+-is another shorthand character \-
+-it is used only on the right-hand part of a substitute command
+-where it means ``whatever was matched on the left-hand side''.
+-It is used to save typing.
+-Suppose the current line contained
+-.P1
+-Now is the time
+-.P2
+-and you wanted to put parentheses around it.
+-You could just retype the line, but
+-this is tedious.
+-Or you could say
+-.P1
+-s/^/(/
+-s/$/)/
+-.P2
+-using your knowledge of
+-.UL ^
+-and
+-.UL $ .
+-But the easiest way uses the
+-.UL & :
+-.P1
+-s/\*.*/(&)/
+-.P2
+-This says ``match the whole line, and replace it
+-by itself surrounded by parentheses.''
+-The
+-.UL &
+-can be used several times in a line;
+-consider
+-using
+-.P1
+-s/\*.*/&?  &!!/
+-.P2
+-to produce
+-.P1
+-Now is the time?  Now is the time!!
+-.P2
+-.PP
+-You don't have to match the whole line, of course:
+-if the buffer contains
+-.P1
+-the end of the world
+-.P2
+-you could type
+-.P1
+-/world/s//& is at hand/
+-.P2
+-to produce
+-.P1
+-the end of the world is at hand
+-.P2
+-Observe this expression carefully,
+-for it illustrates how to take advantage of
+-.ul
+-ed
+-to save typing.
+-The string
+-.UL /world/
+-found the desired line;
+-the shorthand
+-.UL //
+-found the same
+-word in the line;
+-and the
+-.UL &
+-saves you from typing it again.
+-.PP
+-The
+-.UL &
+-is a special character only within
+-the replacement text of a substitute command,
+-and has no special meaning elsewhere.
+-You can turn off the special meaning of
+-.UL &
+-by preceding it with a
+-.UL \e :
+-.P1
+-s/ampersand/\e&/
+-.P2
+-will convert the word ``ampersand'' into the literal symbol
+-.UL &
+-in the current line.
+//GO.SYSIN DD e6
+echo e7
+sed 's/.//' >e7 <<'//GO.SYSIN DD e7'
+-.sp 2
+-.SH
+-Summary of Commands and Line Numbers
+-.PP
+-The general form of
+-.ul
+-ed
+-commands is the command name,
+-perhaps preceded by one or two line numbers, and,
+-in the case of
+-.UL e ,
+-.UL r ,
+-and
+-.UL w ,
+-followed by a file name.
+-Only one command is allowed per line,
+-but a
+-.UL p
+-command may follow any other command
+-(except for
+-.UL e ,
+-.UL r ,
+-.UL w
+-and
+-.UL q ).
+-.LP
+-.UL a :
+-Append, that is, 
+-add lines to the buffer (at line dot, unless
+-a different line is specified). Appending continues until
+-\*.
+-is typed on a new line.
+-Dot is set to the last line appended.
+-.LP
+-.UL c :
+-Change the specified lines to the new text which follows.
+-The new lines are terminated by a
+-\*.,
+-as with
+-.UL a .
+-If no lines are specified,
+-replace line dot.
+-Dot is set to last line changed.
+-.LP
+-.UL d :
+-Delete the lines specified.
+-If none are specified, delete line dot.
+-Dot is set to the first undeleted line,
+-unless
+-.UL $
+-is deleted,
+-in which case dot is set to
+-.UL $ .
+-.LP
+-.UL e :
+-Edit new file.
+-Any previous
+-contents of the buffer are thrown away,
+-so issue a
+-.UL w
+-beforehand.
+-.LP
+-.UL f :
+-Print remembered filename.
+-If a name follows
+-.UL f
+-the remembered name will be set to it.
+-.LP
+-.UL g :
+-The command
+-.P1
+-g/\(hy\(hy\(hy/commands
+-.P2
+-will execute the commands on those lines that contain
+-.UL --- ,
+-which can be any context search expression.
+-.LP
+-.UL i :
+-Insert lines before specified line (or dot)
+-until a
+-\*.
+-is typed on a new line.
+-Dot is set to last line inserted.
+-.LP
+-.UL m :
+-Move lines specified to after the line
+-named after
+-.UL m .
+-Dot is set to the last line moved.
+-.LP
+-.UL p :
+-Print specified lines.
+-If none specified, print
+-line dot.
+-A single line number is equivalent to
+-.IT line-number
+-.UL p .
+-A single return prints
+-.UL .+1 ,
+-the next line.
+-.LP
+-.UL q :
+-Quit
+-.IT ed .
+-Wipes out all text in buffer
+-if you give it twice in a row without first giving a
+-.UL w
+-command.
+-.LP
+-.UL r :
+-Read a file into buffer (at end unless specified
+-elsewhere.) Dot set to last line read.
+-.LP
+-.UL s :
+-The command
+-.P1
+-s/string1/string2/
+-.P2
+-substitutes the characters
+-.UL string1
+-into
+-.UL string2
+-in the specified lines.
+-If no lines are specified, make the substitution in line dot.
+-Dot is set to last line in which a
+-substitution took place, which means that if no substitution took place, dot is not changed.
+-.UL s
+-changes only the first occurrence of
+-.UL  string1 
+-on a line;
+-to change all of them, type a
+-.UL g
+-after the final slash.
+-.LP
+-.UL v :
+-The command
+-.P1
+-v/\(hy\(hy\(hy/commands
+-.P2
+-executes
+-.UL commands
+-on those lines that
+-.ul
+-do not
+-contain
+-.UL --- .
+-.LP
+-.UL w :
+-Write out buffer onto a file.
+-Dot is not changed.
+-.LP
+-.UL .= :
+-Print value of dot.
+-.UL = "" (
+-by itself prints the value of
+-.UL $ .)
+-.LP
+-.UL ! :
+-The line
+-.P1
+-!command\(hyline
+-.P2
+-causes
+-.UL command-line
+-to be executed as a
+-.UC UNIX
+-command.
+-.LP
+-.UL /-----/ :
+-Context search.
+-Search for next line which contains
+-this string of characters.
+-Print it.
+-Dot is set to the line where string
+-was found.
+-Search starts at
+-.UL .+1 ,
+-wraps around from
+-.UL $
+-to
+-1,
+-and continues to dot, if necessary.
+-.LP
+-.UL ?-----? :
+-Context search in reverse direction.
+-Start search
+-at
+-.UL .\-1 ,
+-scan to 1,
+-wrap around to
+-.UL $ .
+//GO.SYSIN DD e7
diff --git a/doc/7thEdMan/vol2/eqn.bun b/doc/7thEdMan/vol2/eqn.bun
new file mode 100644 (file)
index 0000000..247427a
--- /dev/null
@@ -0,0 +1,3140 @@
+# To unbundle, run this file
+echo e.mac
+sed 's/.//' >e.mac <<'//GO.SYSIN DD e.mac'
+-.tr _\(em
+-.tr *\(**
+-.de UC
+-\&\\$3\s-1\\$1\\s0\&\\$2
+-..
+-.de IT
+-.if n .ul
+-\&\\$3\f2\\$1\fP\&\\$2
+-..
+-.de UL
+-.if n .ul
+-\&\\$3\f3\\$1\fP\&\\$2
+-..
+-.de BD
+-.bd 3 \\$1
+-..
+-.de BI
+-.bd I \\$1
+-..
+-.de P1
+-.DS I 3n
+-.nf
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ta .4i .8i 1.2i 1.6i 2i 2.4i 2.8i 3.2i 3.6i 4i 4.4i 4.8i 5.2i 5.6i
+-.if t .tr -\(mi|\(bv'\(fm^\(no*\(**
+-.tr `\(ga'\(aa
+-.if t .tr _\(ul
+-.             \"use first argument as indent if present
+-..
+-.de P2
+-.if n .ls 2
+-.tr --||''``^^!!
+-.if t .tr _\(em
+-.DE
+-..
+-.hw semi-colon
+-.hw estab-lished
+-.hy 14
+-.             \"2=not last lines; 4= no -xx; 8=no xx-
+-.             \"special chars in programs
+-.ds . \s\\nP.\s0
+-.ds , \s\\nP,\s0
+-.ds ; \s\\nP\z,\v'-.3m'.\v'.3m'\s0
+-.ds : \s\\nP\z.\v'-.3m'.\v'.3m'\s0
+-.ds ' \s\\nQ\v'.25m'\(fm\v'-.25m'\s0
+-.ds ^ \h'-.1m'\(no\h'.1m'
+-.de WS
+-.sp \\$1
+-..
+//GO.SYSIN DD e.mac
+echo e0
+sed 's/.//' >e0 <<'//GO.SYSIN DD e0'
+-.nr PS 9
+-.nr VS 11
+-....ND "Revised  April, 1977"
+-.EQ
+-delim $$
+-gsize 9
+-.EN
+-....TR 17
+-.TL
+-A System for Typesetting Mathematics
+-.AU
+-Brian W. Kernighan and Lorinda L. Cherry
+-.AI
+-.MH
+-.AB
+-.PP
+-This paper describes the design and implementation
+-of a system for typesetting mathematics.
+-The language has been designed to be easy to learn
+-and to use
+-by people
+-(for example, secretaries and mathematical typists)
+-who know neither mathematics nor typesetting.
+-Experience indicates that the language can
+-be learned in an hour or so,
+-for it has few rules and fewer exceptions.
+-For typical expressions,
+-the size and font changes, positioning, line drawing,
+-and the like necessary to print according to mathematical conventions
+-are all done automatically.
+-For example,
+-the input
+-.sp 4p
+-.ce
+-sum from i=0 to infinity x sub i = pi over 2
+-.sp 4p
+-produces
+-.EQ
+-sum from i=0 to infinity x sub i = pi over 2
+-.EN
+-.PP
+-The syntax of the language is specified by a small
+-context-free grammar;
+-a compiler-compiler is used to make a compiler
+-that translates this language into typesetting commands.
+-Output may be produced on either a phototypesetter
+-or on a terminal with forward and reverse half-line motions.
+-The system interfaces directly with text formatting programs,
+-so mixtures of text and mathematics may be handled simply.
+-.LP
+-.LP
+-.PP
+-This paper is a revision of a paper originally published in
+-CACM, March, 1975.
+-.AE
+//GO.SYSIN DD e0
+echo e1
+sed 's/.//' >e1 <<'//GO.SYSIN DD e1'
+-.2C $gsize 9$
+-.nr PS 9
+-.nr VS 11p
+-.NH
+-Introduction
+-.PP
+-``Mathematics is known in the trade as
+-.ul
+-difficult,
+-or
+-.ul
+-penalty, copy
+-because it is slower, more difficult,
+-and more expensive to set in type
+-than any other kind of copy normally
+-occurring in books and journals.''
+-[1]
+-.PP
+-One difficulty with mathematical text
+-is the multiplicity of characters,
+-sizes, and fonts.
+-An expression such as
+-.EQ
+-lim from {x-> pi /2} ( tan~x) sup{sin~2x}~=~1
+-.EN
+-requires an intimate mixture of roman, italic and greek letters, in three sizes,
+-and a special character or two.
+-(``Requires'' is perhaps the wrong word,
+-but mathematics has its own typographical conventions
+-which are quite different from those
+-of ordinary text.)
+-Typesetting such an expression by traditional methods
+-is still an essentially manual operation.
+-.PP
+-A second difficulty is the two dimensional character
+-of mathematics,
+-which the superscript and limits in the preceding example
+-showed in its simplest form.
+-This is carried further by
+-.EQ
+-a sub 0 + b sub 1 over
+-  {a sub 1 + b sub 2 over
+-    {a sub 2 + b sub 3 over
+-      {a sub 3 + ... }}}
+-.EN
+-.sp
+-and still further by 
+-.EQ
+-define emx "{e sup mx}"
+-define mab "{m sqrt ab}"
+-define sa "{sqrt a}"
+-define sb "{sqrt b}"
+-int dx over {a emx - be sup -mx} ~=~
+-left { lpile {
+-     1 over {2 mab} ~log~ {sa emx - sb} over {sa emx + sb}
+-   above
+-     1 over mab ~ tanh sup -1 ( sa over sb emx ) 
+-   above
+-     -1 over mab ~ coth sup -1 ( sa over sb emx )
+-}
+-.EN
+-These examples also show line-drawing, built-up characters like braces and radicals,
+-and a spectrum of positioning problems.
+-(Section 6 shows
+-what a user has to type to produce these
+-on our system.)
+//GO.SYSIN DD e1
+echo e2
+sed 's/.//' >e2 <<'//GO.SYSIN DD e2'
+-.NH
+-Photocomposition
+-.PP
+-Photocomposition techniques
+-can be used to solve some of the problems of typesetting mathematics.
+-A phototypesetter is a device which exposes
+-a piece of photographic paper or film, placing characters
+-wherever they are wanted.
+-The Graphic Systems phototypesetter[2] on the
+-.UC UNIX
+-operating
+-system[3] works by shining light through a character stencil.
+-The character is made the right size by lenses,
+-and the light beam directed by fiber optics
+-to the desired place on a piece of photographic paper.
+-The exposed paper is developed and typically used
+-in some form of photo-offset reproduction.
+-.PP
+-On
+-.UC UNIX ,
+-the phototypesetter is driven by a formatting program called
+-.UC TROFF
+-[4].
+-.UC TROFF
+-was designed for setting running text.
+-It also provides all of the facilities that one needs for
+-doing mathematics, such as
+-arbitrary horizontal and vertical motions,
+-line-drawing, size changing,
+-but the syntax for describing these special operations is
+-difficult to learn,
+-and difficult even for experienced users to type correctly.
+-.PP
+-For this reason we decided to use
+-.UC TROFF
+-as an ``assembly language,''
+-by
+-designing a language for describing mathematical
+-expressions,
+-and compiling it into
+-.UC TROFF .
+//GO.SYSIN DD e2
+echo e3
+sed 's/.//' >e3 <<'//GO.SYSIN DD e3'
+-.NH
+-Language Design
+-.PP
+-The fundamental principle upon which we based our language design
+-is that the language should be easy to use
+-by people (for example, secretaries) who know neither mathematics nor typesetting.
+-.PP
+-This principle implies
+-several things.
+-First,
+-``normal'' mathematical conventions about operator precedence,
+-parentheses, and the like cannot be used,
+-for to give special meaning to such characters means
+-that the user has to understand what he or she
+-is typing.
+-Thus the language should not assume, for instance,
+-that parentheses are always balanced,
+-for they are not in
+-the half-open interval $(a,b]$.
+-Nor should it assume that
+-that $sqrt{a+b}$ can be replaced by
+-$(a+b) sup roman \(12$,
+-or that $1/(1-x)$ is better written as $1 over 1-x$
+-(or
+-vice versa).
+-.PP
+-Second, there should be relatively few rules,
+-keywords,
+-special symbols and operators, and the like.
+-This keeps the language easy to learn and remember. Furthermore, there should be few exceptions to
+-the rules that do exist: 
+-if something works in one situation,
+-it should work everywhere.
+-If a variable can have a subscript,
+-then a subscript can have a subscript, and so on without limit.
+-.PP
+-Third, ``standard'' things should happen automatically.
+-Someone who types ``x=y+z+1'' should get ``$x=y+z+1$''.
+-Subscripts and superscripts should automatically
+-be printed in an appropriately smaller size,
+-with no special intervention.
+-Fraction bars have to be made the right length and positioned at the
+-right height.
+-And so on.
+-Indeed a mechanism for overriding default actions has to exist,
+-but its application is the exception, not the rule.
+-.PP
+-We assume
+-that the typist has a reasonable picture
+-(a two-dimensional representation)
+-of the desired final form, as might be handwritten
+-by the author of a paper.
+-We also assume that
+-the input is typed on a computer terminal much like an ordinary typewriter.
+-This implies an input alphabet
+-of perhaps 100 characters,
+-none of them special.
+-.PP
+-A secondary, but still important, goal in our design
+-was that the system should be easy to implement,
+-since neither of the authors had any desire to make
+-a long-term project of it.
+-Since our design was not firm,
+-it was also necessary that the program be easy to change
+-at any time.
+-.PP
+-To make the program easy to build and to change,
+-and to guarantee regularity
+-(``it should work everywhere''),
+-the language is defined by a
+-context-free grammar, described in Section 5.
+-The compiler for the language was built using a compiler-compiler.
+-.PP
+-A priori,
+-the grammar/compiler-compiler approach seemed the right thing to do.
+-Our subsequent experience leads us to believe
+-that any other course would have been folly.
+-The original language was designed in a few days. 
+-Construction of a working system
+-sufficient to try significant examples
+-required perhaps a person-month.
+-Since then, we have spent a modest amount of additional time
+-over several years
+-tuning, adding facilities,
+-and occasionally changing the language as users
+-make criticisms and suggestions.
+-.PP
+-We also decided quite early that
+-we would let
+-.UC TROFF
+-do our work for us whenever possible.
+-.UC TROFF
+-is quite a powerful program, with
+-a macro facility, text and arithmetic variables, numerical computation and testing,
+-and conditional branching.
+-Thus we have been able to avoid writing
+-a lot of mundane but tricky software.
+-For example, we store no text strings,
+-but simply pass them on to
+-.UC TROFF .
+-Thus we avoid having to write a storage management package.
+-Furthermore, we have been able to isolate ourselves
+-from most details of the particular device and character set
+-currently in use.
+-For example, we let
+-.UC TROFF
+-compute the widths of all strings of characters;
+-we need know nothing about them.
+-.PP
+-A third design goal is special to our environment.
+-Since our program is only useful for typesetting mathematics,
+-it is necessary that it interface cleanly with the underlying typesetting language
+-for the benefit of users
+-who want to set intermingled mathematics and text
+-(the usual case).
+-The standard mode of operation
+-is that when a document is typed,
+-mathematical expressions are input as part of the text,
+-but marked by user settable delimiters.
+-The program reads this input and treats as comments
+-those things which are not mathematics,
+-simply passing them through untouched.
+-At the same time it converts the mathematical input
+-into the necessary
+-.UC TROFF
+-commands.
+-The resulting ioutput is passed directly to
+-.UC TROFF
+-where the comments and the mathematical parts both become
+-text and/or
+-.UC TROFF
+-commands.
+//GO.SYSIN DD e3
+echo e4
+sed 's/.//' >e4 <<'//GO.SYSIN DD e4'
+-.NH
+-The Language
+-.PP
+-We will not try to describe the language precisely here;
+-interested readers may refer to the appendix for more details.
+-Throughout this section, we will write expressions
+-exactly
+-as they are handed to the typesetting program (hereinafter called
+-.UC ``EQN'' ),
+-except that we won't show the delimiters
+-that the user types to mark the beginning and end of the expression.
+-The interface between
+-.UC EQN
+-and
+-.UC TROFF
+-is described at the end of this section.
+-.PP
+-As we said, typing x=y+z+1 should produce $x=y+z+1$,
+-and indeed it does.
+-Variables are made italic, operators and digits become roman,
+-and normal spacings between letters and operators are altered slightly
+-to give a more pleasing appearance.
+-.PP
+-Input is free-form.
+-Spaces and new lines in the input are used by
+-.UC EQN
+-to separate pieces of the input;
+-they are not used to create space in the output.
+-Thus 
+-.P1
+-x    =    y
+-   + z + 1
+-.P2
+-also gives $x=y+z+1$.
+-Free-form input is easier to type initially;
+-subsequent editing is also easier,
+-for an expression may be typed as many short lines.
+-.PP
+-Extra white space can be forced into the output by several
+-characters of various sizes.
+-A tilde ``\|~\|'' gives a space equal
+-to the normal word spacing in text;
+-a circumflex gives half this much,
+-and a tab charcter spaces to the next tab stop.
+-.PP
+-Spaces (or tildes, etc.)
+-also serve to delimit pieces of the input.
+-For example, to get
+-.EQ
+-f(t) = 2 pi int sin ( omega t )dt
+-.EN
+-we write
+-.P1
+-f(t) = 2 pi int sin ( omega t )dt
+-.P2
+-Here spaces are
+-.ul
+-necessary
+-in the input
+-to indicate that 
+-.ul
+-sin, pi, int,
+-and
+-.ul
+-omega
+-are special, and potentially worth special treatment.
+-.UC EQN
+-looks up each such string of characters
+-in a table, and if appropriate gives it a translation.
+-In this case, 
+-.ul
+-pi
+-and
+-.ul
+-omega
+-become their greek equivalents,
+-.ul
+-int
+-becomes the integral sign
+-(which must be moved down and enlarged so it looks ``right''),
+-and
+-.ul
+-sin
+-is made roman, following conventional mathematical practice.
+-Parentheses, digits and operators are automatically made roman
+-wherever found.
+-.PP
+-Fractions are specified with the keyword
+-.ul
+-over:
+-.P1
+-a+b over c+d+e = 1
+-.P2
+-produces
+-.EQ
+-a+b over c+d+e = 1
+-.EN
+-.PP
+-Similarly, subscripts and superscripts are introduced by the keywords
+-.ul
+-sub
+-and
+-.ul
+-sup:
+-.EQ
+-x sup 2 + y sup 2 = z sup 2
+-.EN
+-is produced by
+-.P1
+-x sup 2 + y sup 2 = z sup 2
+-.P2
+-The spaces after the 2's are necessary to mark the end of
+-the superscripts;
+-similarly the keyword
+-.ul
+-sup
+-has to be marked off by spaces or
+-some equivalent delimiter.
+-The return to the proper baseline is automatic.
+-Multiple levels of subscripts or superscripts
+-are of course allowed:
+-``x\|\|sup\|\|y\|\|sup\|\|z'' is
+-$x sup y sup z$.
+-The construct
+-``something
+-.ul
+-sub
+-something
+-.ul
+-sup
+-something''
+-is recognized as a special case,
+-so 
+-``x sub i sup 2''
+-is
+-$x sub i sup 2$ instead of ${x sub i} sup 2$.
+-.PP
+-More complicated expressions can now be formed with these
+-primitives:
+-.EQ
+-{partial sup 2 f} over {partial x sup 2} =
+-x sup 2 over a sup 2 + y sup 2 over b sup 2
+-.EN
+-is produced by
+-.P1
+-.ce 0
+-   {partial sup 2 f} over {partial x sup 2} =
+-   x sup 2 over a sup 2 + y sup 2 over b sup 2
+-.P2
+-Braces {} are used to group objects together;
+-in this case they indicate unambiguously what goes over what
+-on the left-hand side of the expression.
+-The language defines the precedence of
+-.ul
+-sup
+-to be higher than that of
+-.ul
+-over,
+-so
+-no braces are needed to get the correct association on the right side.
+-Braces can always be used when in doubt
+-about precedence.
+-.PP
+-The braces convention is an example of the power
+-of using a recursive grammar
+-to define the language.
+-It is part of the language that if a construct can appear
+-in some context,
+-then 
+-.ul
+-any expression
+-in braces
+-can also occur in that context.
+-.PP
+-There is a
+-.ul
+-sqrt
+-operator for making square roots of the appropriate size:
+-``sqrt a+b'' produces $sqrt a+b$,
+-and
+-.P1
+-x =  {-b +- sqrt{b sup 2 -4ac}} over 2a
+-.P2
+-is
+-.EQ
+-x={-b +- sqrt{b sup 2 -4ac}} over 2a
+-.EN
+-Since large radicals look poor on our typesetter,
+-.ul
+-sqrt
+-is not useful for tall expressions.
+-.PP
+-Limits on summations, integrals and similar
+-constructions are specified with
+-the keywords
+-.ul
+-from
+-and
+-.ul
+-to.
+-To get
+-.EQ
+-sum from i=0 to inf x sub i -> 0
+-.EN
+-we need only type
+-.P1
+-sum from i=0 to inf x sub i -> 0
+-.P2
+-Centering and making the $SIGMA$ big enough and the limits smaller
+-are all automatic.
+-The
+-.ul
+-from
+-and
+-.ul
+-to
+-parts are both optional,
+-and the central part (e.g., the $SIGMA$)
+-can in fact be anything:
+-.P1
+-lim from {x -> pi /2} ( tan~x) = inf
+-.P2
+-is
+-.EQ
+-lim from {x -> pi /2} ( tan~x) = inf
+-.EN
+-Again,
+-the braces indicate just what goes into the
+-.ul
+-from
+-part.
+-.PP
+-There is a facility for making braces, brackets, parentheses, and vertical bars
+-of the right height, using the keywords
+-.ul
+-left
+-and 
+-.ul
+-right:
+-.P1
+-left [ x+y over 2a right ]~=~1
+-.P2
+-makes
+-.EQ
+-left [ x+y over 2a right ]~=~1
+-.EN
+-A
+-.ul
+-left
+-need not have a corresponding
+-.ul
+-right,
+-as we shall see in the next example.
+-Any characters may follow
+-.ul
+-left
+-and
+-.ul
+-right,
+-but generally only various parentheses and bars are meaningful.
+-.PP
+-Big brackets, etc.,
+-are often used with another facility,
+-called
+-.ul
+-piles,
+-which make vertical piles of objects.
+-For example,
+-to get
+-.EQ
+-sign (x) ~==~ left {
+-   rpile {1 above 0 above -1}
+-   ~~lpile {if above if above if}
+-   ~~lpile {x>0 above x=0 above x<0}
+-.EN
+-we can type
+-.P1
+-sign (x) ~==~ left {
+-   rpile {1 above 0 above -1}
+-   ~~lpile {if above if above if}
+-   ~~lpile {x>0 above x=0 above x<0}
+-.P2
+-The construction ``left {''
+-makes a left brace big enough
+-to enclose the
+-``rpile {...}'',
+-which is a right-justified pile of
+-``above ... above ...''.
+-``lpile'' makes a left-justified pile.
+-There are also centered piles.
+-Because of the recursive language definition,
+-a
+-pile
+-can contain any number of elements;
+-any element of a pile can of course
+-contain piles.
+-.PP
+-Although
+-.UC EQN
+-makes a valiant attempt
+-to use the right sizes and fonts,
+-there are times when the default assumptions
+-are simply not what is wanted.
+-For instance the italic
+-.ul
+-sign
+-in the previous example would conventionally
+-be in roman.
+-Slides and transparencies often require larger characters than normal text.
+-Thus we also provide size and font
+-changing commands:
+-``size 12 bold {A~x~=~y}''
+-will produce
+-$size 12 bold{ A~x~=~y}$.
+-.ul
+-Size
+-is followed by a number representing a character size in points.
+-(One point is 1/72 inch;
+-this paper is set in 9 point type.)
+-.PP
+-If necessary, an input string can be quoted in "...",
+-which turns off grammatical significance, and any font or spacing changes that might otherwise be done on it.
+-Thus we can say 
+-.P1
+-lim~ roman "sup" ~x sub n = 0
+-.P2
+-to ensure that the supremum doesn't become a superscript:
+-.EQ
+-lim~ roman "sup" ~x sub n = 0
+-.EN
+-.PP
+-Diacritical marks, long a problem in traditional typesetting,
+-are straightforward:
+-.EQ
+-x dot under + x hat + y tilde + X hat + Y dotdot = z+Z bar
+-.EN
+-is made by typing
+-.P1
+-x dot under + x hat + y tilde 
+-+ X hat + Y dotdot = z+Z bar
+-.P2
+-.PP
+-There are also facilities for globally changing default
+-sizes and fonts, for example for making viewgraphs
+-or for setting chemical equations.
+-The language allows for matrices, and for lining up equations
+-at the same horizontal position.
+-.PP
+-Finally, there is a definition facility,
+-so a user can say
+-.P1
+-define name "..."
+-.P2
+-at any time in the document;
+-henceforth, any occurrence of the token ``name''
+-in an expression
+-will be expanded into whatever was inside
+-the double quotes in its definition.
+-This lets users tailor
+-the language to their own specifications,
+-for it is quite possible to redefine
+-keywords
+-like
+-.ul
+-sup
+-or
+-.ul
+-over.
+-Section 6 shows an example of definitions.
+-.PP
+-The
+-.UC EQN
+-preprocessor reads intermixed text and equations,
+-and passes its output to
+-.UC TROFF.
+-Since
+-.UC TROFF
+-uses lines beginning with a period as control words
+-(e.g., ``.ce'' means ``center the next output line''),
+-.UC EQN
+-uses the sequence ``.EQ'' to mark the beginning of an equation and
+-``.EN'' to mark the end.
+-The ``.EQ'' and ``.EN'' are passed through to
+-.UC TROFF 
+-untouched,
+-so they can also be used by a knowledgeable user to
+-center equations, number them automatically, etc.
+-By default, however,
+-``.EQ'' and ``.EN'' are simply ignored by
+-.UC TROFF ,
+-so by default equations are printed in-line.
+-.PP
+-``.EQ'' and ``.EN'' can be supplemented by
+-.UC TROFF
+-commands as desired;
+-for example, a centered display equation
+-can be produced with the input:
+-.P1
+-.ce 0
+-.in 5
+- .ce
+- .EQ
+- x sub i = y sub i ...
+- .EN
+-.in 0
+-.P2
+-.PP
+-Since it is tedious to type
+-``.EQ'' and ``.EN'' around very short expressions
+-(single letters, for instance),
+-the user can also define two characters to serve
+-as the left and right delimiters of expressions.
+-These characters are recognized anywhere in subsequent text.
+-For example if the left and right delimiters have both been set to ``#'',
+-the input:
+-.P1
+-Let #x sub i#, #y# and #alpha# be positive
+-.P2
+-produces:
+-.P1
+-Let $x sub i$, $y$ and $alpha$ be positive
+-.P2
+-.PP
+-Running a preprocessor is strikingly easy on
+-.UC UNIX.
+-To typeset
+-text stored in file
+-``f\|'',
+-one issues the command:
+-.P1
+-eqn f | troff
+-.P2
+-The vertical bar connects the output
+-of one process
+-.UC (EQN)
+-to the input of another
+-.UC (TROFF) .
+//GO.SYSIN DD e4
+echo e5
+sed 's/.//' >e5 <<'//GO.SYSIN DD e5'
+-.NH
+-Language Theory
+-.PP
+-The basic structure of the language is
+-not a particularly original one.
+-Equations are pictured as a set of ``boxes,''
+-pieced together in various ways.
+-For example, something with a subscript is
+-just a box followed by another box moved downward
+-and shrunk
+-by an appropriate amount.
+-A fraction is just a box centered above another box,
+-at the right altitude,
+-with a line of correct length drawn between them.
+-.PP
+-The grammar for the language is shown below.
+-For purposes of exposition, we have collapsed
+-some productions. In the original grammar, there
+-are about 70 productions, but many of these
+-are simple ones used only to guarantee
+-that some keyword is recognized early enough in the parsing process.
+-Symbols in
+-capital letters
+-are terminal symbols; 
+-lower case
+-symbols are non-terminals, i.e., syntactic categories.
+-The vertical bar \(bv indicates an alternative;
+-the brackets [ ] indicate optional material.
+-A
+-.UC TEXT
+-is a string of non-blank characters or
+-any string inside double quotes;
+-the other terminal symbols represent literal occurrences
+-of the corresponding keyword.
+-.P1
+-.ce 0
+-.ta .3i
+-.ps 9
+-.ne 17
+-.in 1
+-eqn   : box | eqn box
+-.sp 5p
+-box   : text
+-      | { eqn }
+-      | box OVER box
+-      | SQRT box
+-      | box SUB box | box SUP box
+-      | [ L | C | R ]PILE { list }
+-      | LEFT text eqn [ RIGHT text ]
+-      | box [ FROM box ] [ TO box ]
+-      | SIZE text box
+-      | [ROMAN | BOLD | ITALIC] box
+-      | box [HAT | BAR | DOT | DOTDOT | TILDE]
+-      | DEFINE text text
+-.sp 5p
+-list  : eqn | list ABOVE eqn
+-.sp 5p
+-text  : TEXT
+-.ps 10
+-.in 0
+-.P2
+-.PP
+-The grammar makes it obvious why there are few exceptions.
+-For example, the observation that something can be replaced by a more complicated something 
+-in braces is implicit in the productions:
+-.P1
+-.ce 0
+-   eqn        : box | eqn box
+-   box        : text | { eqn }
+-.P2
+-Anywhere a single character could be used,
+-.ul
+-any
+-legal construction can be used.
+-.PP
+-Clearly, our grammar is highly ambiguous.
+-What, for instance, do we do with the input
+-.P1
+-a over b over c  ?
+-.P2
+-Is it
+-.P1
+-{a over b} over c 
+-.P2
+-or is it
+-.P1
+-a over {b over c}  ?
+-.P2
+-.PP
+-To answer questions like this, the grammar
+-is supplemented with a small set of rules that describe the precedence 
+-and associativity
+-of operators.
+-In particular, we specify (more or less arbitrarily)
+-that
+-.ul
+-over
+-associates to the left,
+-so the first alternative above is the one chosen.
+-On the other hand, 
+-.ul
+-sub
+-and
+-.ul
+-sup
+-bind to the right,
+-because this is closer to standard mathematical practice.
+-That is, we assume $x sup a sup b$ is $x sup {(a sup b )}$,
+-not  $(x sup a ) sup b$.
+-.PP
+-The precedence rules resolve the ambiguity in a construction like
+-.P1
+-a sup 2 over b
+-.P2
+-We define
+-.ul
+-sup
+-to have a higher precedence than
+-.ul
+-over,
+-so this construction is parsed as
+-$a sup 2 over b$ instead of $a sup {2 over b}$.
+-.PP
+-Naturally, a user can always
+-force a particular parsing
+-by placing braces around expressions.
+-.PP
+-The ambiguous grammar approach seems to be quite useful.
+-The grammar we use is small enough to be easily understood,
+-for it contains none of the productions that would be
+-normally used for resolving ambiguity.
+-Instead the supplemental information about
+-precedence and associativity (also small enough to be understood)
+-provides the compiler-compiler
+-with the information it needs
+-to make a fast, deterministic parser for
+-the specific language we want.
+-When the language is supplemented by the disambiguating rules,
+-it is in fact
+-.UC LR(1)
+-and thus easy to parse[5].
+-.PP
+-The output code is generated as the input is scanned.
+-Any time a production
+-of the grammar is recognized,
+-(potentially) some
+-.UC TROFF
+-commands are output.
+-For example, when the lexical analyzer 
+-reports that it has found a
+-.UC TEXT
+-(i.e., a string of contiguous characters),
+-we have recognized the production:
+-.P1
+-text    : TEXT
+-.P2
+-The translation of this is simple.
+-We generate a local name for the string,
+-then hand the name and the string to
+-.UC TROFF,
+-and let
+-.UC TROFF
+-perform the storage management.
+-All we save is the name of the string,
+-its height, and its baseline.
+-.PP
+-As another example,
+-the translation associated with the production
+-.P1
+-box    : box OVER box
+-.P2
+-is:
+-.P1
+-.ce 0
+-.in 1
+-.ne 14
+-Width of output box =
+-  slightly more than largest input width
+-Height of output box =
+-  slightly more than sum of input heights
+-Base of output box =
+-  slightly more than height of bottom input box
+-String describing output box =
+-  move down;
+-  move right enough to center bottom box;
+-  draw bottom box (i.e., copy string for bottom box);
+-  move up; move left enough to center top box;
+-  draw top box (i.e., copy string for top box);
+-  move down and left; draw line full width;
+-  return to proper base line.
+-.in 0
+-.P2
+-Most of the other productions have 
+-equally simple semantic actions.
+-Picturing the output as a set of properly placed boxes
+-makes the right sequence of positioning commands
+-quite obvious.
+-The main difficulty is in finding the right numbers to use
+-for esthetically pleasing positioning.
+-.PP
+-With a grammar, it is usually clear how to extend the language.
+-For instance, one of our users
+-suggested a
+-.UC TENSOR
+-operator, to make constructions like
+-.EQ
+-~ sub size 7 m sup size 7 l
+-{bold T from n to k} sub size 7 i sup size 7 j
+-.EN
+-Grammatically, this is easy:
+-it is sufficient to add a production like
+-.P1
+-box    : TENSOR { list }
+-.P2
+-Semantically, we need only juggle the boxes to the right places.
+//GO.SYSIN DD e5
+echo e6
+sed 's/.//' >e6 <<'//GO.SYSIN DD e6'
+-.NH
+-Experience
+-.PP
+-There are really three aspects of interest_how
+-well
+-.UC EQN
+-sets mathematics,
+-how well it satisfies its goal
+-of being ``easy to use,''
+-and how easy it was to build.
+-.PP
+-The first question is easily addressed.
+-This entire paper
+-has been set by the program.
+-Readers can judge for themselves
+-whether it is good enough for their purposes.
+-One of our users commented that although the output
+-is not as good as the best hand-set material,
+-it is still
+-better than average,
+-and much better than
+-the worst.
+-In any case, who cares?
+-Printed books cannot compete with the birds and flowers
+-of illuminated manuscripts on esthetic grounds,
+-either,
+-but they have some clear economic advantages.
+-.PP
+-Some of the deficiencies in the output could
+-be cleaned up with more work on our part.
+-For example, we sometimes leave too much space between
+-a roman letter and an italic one.
+-If we were willing to keep track of the fonts
+-involved,
+-we could do this better more of the time.
+-.PP
+-Some other weaknesses are inherent in our output device.
+-It is hard, for instance, to draw a line
+-of an arbitrary length without getting
+-a perceptible overstrike at one end.
+-.PP
+-As to ease of use,
+-at the time of writing,
+-the system has been used by two distinct groups.
+-One user population consists of mathematicians,
+-chemists, physicists, and computer scientists.
+-Their typical reaction has been something like:
+-.IP " (1)"
+-It's easy to write, although I make the following mistakes...
+-.IP " (2)"
+-How do I do...?
+-.IP " (3)"
+-It botches the following things.... Why don't you fix them?
+-.IP " (4)"
+-You really need the following features...
+-.sp 5p
+-.PP
+-The learning time is short.
+-A few minutes gives the general flavor,
+-and typing a page or two of a paper generally
+-uncovers most of the misconceptions about how it works.
+-.PP
+-The second user group is much larger,
+-the secretaries and mathematical typists
+-who were the original target of the system.
+-They tend to be enthusiastic converts.
+-They find the language easy to learn
+-(most are largely self-taught),
+-and have little trouble producing the output they want.
+-They are of course less critical of the esthetics of their output
+-than users trained in mathematics.
+-After a transition period, most find
+-using a computer more interesting than
+-a regular typewriter.
+-.PP
+-The main difficulty that users have seems to be remembering
+-that a blank is a delimiter;
+-even experienced users use blanks where they shouldn't and omit them
+-when they are needed.
+-A common instance is typing
+-.P1
+-f(x sub i)
+-.P2
+-which produces
+-.EQ
+-f(x sub i)
+-.EN
+-instead of
+-.EQ
+-f(x sub i )
+-.EN
+-Since the 
+-.UC EQN
+-language knows no mathematics, it cannot deduce that the
+-right parenthesis is not part of the subscript.
+-.PP
+-The language is somewhat prolix, but this doesn't seem
+-excessive considering how much is being done,
+-and it is certainly more compact than the corresponding
+-.UC TROFF
+-commands.
+-For example, here is the source for the continued fraction
+-expression in Section 1 of this paper:
+-.P1
+-.ne 4
+-.ce 0
+-     a sub 0 + b sub 1 over
+-       {a sub 1 + b sub 2 over
+-         {a sub 2 + b sub 3 over
+-           {a sub 3 + ... }}}
+-.P2
+-This is the input for the large integral of Section 1;
+-notice the use of definitions:
+-.P1
+-.ce 0
+-.ne 15
+-.in 1
+-define emx "{e sup mx}"
+-define mab "{m sqrt ab}"
+-define sa "{sqrt a}"
+-define sb "{sqrt b}"
+-int dx over {a emx - be sup -mx} ~=~
+-left { lpile {
+-     1 over {2 mab} ~log~ 
+-           {sa emx - sb} over {sa emx + sb}
+-   above
+-     1 over mab ~ tanh sup -1 ( sa over sb emx ) 
+-   above
+-     -1 over mab ~ coth sup -1 ( sa over sb emx )
+-}
+-.in 0
+-.P2
+-.PP
+-As to ease of construction,
+-we have already
+-mentioned that there are really only a few person-months
+-invested.
+-Much of this time has gone into two things_fine-tuning
+-(what is the most esthetically pleasing space to use
+-between the numerator and denominator of a fraction?),
+-and changing things found deficient by our users
+-(shouldn't a tilde be a delimiter?).
+-.PP
+-The program consists of a number of small,
+-essentially unconnected modules for code generation,
+-a simple lexical analyzer,
+-a canned parser which we did not have to write,
+-and some miscellany associated with input files
+-and the macro facility.
+-The program is now about 1600 lines of 
+-.UC C
+-[6], a high-level language reminiscent of
+-.UC BCPL .
+-About 20 percent of these lines are ``print'' statements,
+-generating the output code.
+-.PP
+-The semantic routines that generate the actual 
+-.UC TROFF
+-commands can be changed to accommodate other formatting languages
+-and devices.
+-For example, in less than 24 hours,
+-one of us changed the entire semantic package
+-to drive 
+-.UC NROFF,
+-a variant of
+-.UC TROFF,
+-for typesetting mathematics on teletypewriter devices
+-capable of reverse line motions.
+-Since many potential users do not have access
+-to a typesetter, but still have to type mathematics,
+-this provides a way to get a typed version of the final output
+-which is close enough for debugging purposes,
+-and sometimes even for ultimate use.
+//GO.SYSIN DD e6
+echo e7
+sed 's/.//' >e7 <<'//GO.SYSIN DD e7'
+-.NH
+-Conclusions
+-.PP
+-We think we have shown that it is possible
+-to do acceptably good typesetting of mathematics
+-on a phototypesetter,
+-with an input language that is easy to learn and use and
+-that satisfies many users' demands.
+-Such a package can be implemented in
+-short order,
+-given a compiler-compiler and
+-a decent typesetting program underneath.
+-.PP
+-Defining a language, and building a compiler for it
+-with a compiler-compiler
+-seems like the only sensible way to do business.
+-Our experience with the use of
+-a grammar and a compiler-compiler has been
+-uniformly favorable.
+-If we had written everything into code directly,
+-we would have been locked into
+-our original design.
+-Furthermore, we would have never been sure
+-where the exceptions and special cases were.
+-But because we have a grammar, we can change our minds readily and still be reasonably
+-sure that if a construction works in one place
+-it will work everywhere.
+-.SH
+-Acknowledgements
+-.PP
+-We are deeply indebted to
+-J. F. Ossanna,
+-the author of
+-.UC TROFF ,
+-for his willingness to modify
+-.UC TROFF
+-to make our task easier
+-and for his continuous assistance
+-during the development of our program.
+-We are also grateful to
+-A. V. Aho for help with language theory,
+-to S. C. Johnson for aid with the compiler-compiler,
+-and to our early users
+-A. V. Aho, S. I. Feldman, S. C. Johnson,
+-R. W. Hamming,
+-and M. D. McIlroy
+-for their constructive criticisms.
+-.SH
+-References
+-.IP [1]
+-.ul
+-A Manual of Style,
+-12th Edition.
+-University of Chicago Press, 1969. p 295.
+-.IP [2]
+-.ul
+-Model C/A/T Phototypesetter.
+-Graphic Systems, Inc.,
+-Hudson, N. H.
+-.IP [3]
+-Ritchie, D. M., and Thompson, K. L.,
+-``The UNIX time-sharing system.''
+-\fIComm. ACM 17,\fR 7 (July 1974), 365-375.
+-.IP [4]
+-Ossanna, J. F.,
+-TROFF User's Manual.
+-Bell Laboratories Computing Science Technical Report 54, 1977.
+-.IP [5]
+-Aho, A. V., and Johnson, S. C.,
+-``LR Parsing.''
+-\fIComp. Surv. 6,\fR 2 (June 1974), 99-124.
+-.br
+-.IP [6]
+-B. W. Kernighan and D. M. Ritchie,
+-.ul
+-The C Programming Language.
+-Prentice-Hall, Inc., 1978.
+//GO.SYSIN DD e7
+echo g.mac
+sed 's/.//' >g.mac <<'//GO.SYSIN DD g.mac'
+-.tr %$
+-.de SC
+-.NH
+-\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9 
+-..
+-.de UC
+-\&\\$3\s-2\\$1\\s+2\\$2
+-..
+-.de P1
+-.nf
+-.tr -\(mi
+-.tr ^.
+-.tr '\(fm
+-.ss 18
+-.if \\n(.$ .DS I \\$1
+-.if !\\n(.$ .DS
+-..
+-.de P2
+-.DE
+-.fi
+-.ss 12
+-.tr --
+-.tr ^^
+-.tr ''
+-..
+-.tr _\(em
+//GO.SYSIN DD g.mac
+echo g0
+sed 's/.//' >g0 <<'//GO.SYSIN DD g0'
+-.EQ
+-delim $$
+-.EN
+-\".ND "June 2, 1976"
+-.RP
+-\".TM "76-1273-4 76-1271-4" 39199 39199-11
+-.TL
+-Typesetting Mathematics _ User's Guide
+-\&\ \ \ \ \ (Second\ Edition)
+-.AU 2C-518 6021
+-Brian W. Kernighan and Lorinda L. Cherry
+-.AI
+-.MH
+-.AB
+-.in
+-.ll
+-.PP
+-This is the user's guide for a system for typesetting
+-mathematics,
+-using
+-the phototypesetters on the
+-.UX
+-and
+-.UC GCOS
+-operating systems.
+-.PP
+-Mathematical expressions are described in a language
+-designed to be easy to use
+-by people who know neither mathematics nor typesetting.
+-Enough of the language to set in-line expressions like
+-$lim from {x-> pi /2} ( tan~x) sup{sin~2x}~=~1$
+-or display equations like
+-.in .5i
+-.EQ I
+-G(z)~mark =~ e sup { ln ~ G(z) }
+-~=~ exp left ( 
+-sum from k>=1 {S sub k z sup k} over k right )
+-~=~  prod from k>=1 e sup {S sub k z sup k /k}
+-.EN
+-.EQ I
+-lineup = left ( 1 + S sub 1 z + 
+-{ S sub 1 sup 2 z sup 2 } over 2! + ... right )
+-left ( 1+ { S sub 2 z sup 2 } over 2
+-+ { S sub 2 sup 2 z sup 4 } over { 2 sup 2 cdot 2! }
+-+ ... right ) ...
+-.EN
+-.EQ I
+-lineup =  sum from m>=0 left (
+-sum from
+-pile { k sub 1 ,k sub 2 ,..., k sub m  >=0
+-above
+-k sub 1 +2k sub 2 + ... +mk sub m =m}
+-{ S sub 1 sup {k sub 1} } over {1 sup k sub 1 k sub 1 ! } ~
+-{ S sub 2 sup {k sub 2} } over {2 sup k sub 2 k sub 2 ! } ~
+-...
+-{ S sub m sup {k sub m} } over {m sup k sub m k sub m ! } 
+-right ) z sup m
+-.EN
+-.in 0
+-can be learned in an hour or so.
+-.PP
+-The language interfaces directly with
+-the phototypesetting language
+-.UC TROFF ,
+-so mathematical expressions can be embedded in the running
+-text
+-of a manuscript,
+-and the entire document produced in one process.
+-This user's guide is an example of its output.
+-.PP
+-The same language
+-may be used with the 
+-.UC UNIX
+-formatter
+-.UC NROFF
+-to set mathematical expressions on 
+-.UC DASI
+-and
+-.UC GSI
+-terminals
+-and Model 37 teletypes.
+-.AE
+-.CS 11 0 11 0 0 3
+//GO.SYSIN DD g0
+echo g1
+sed 's/.//' >g1 <<'//GO.SYSIN DD g1'
+-.if t .2C
+-.SC Introduction
+-.PP
+-.UC EQN
+-is a
+-program for typesetting mathematics
+-on the Graphics Systems phototypesetters on
+-.UC UNIX
+-and
+-.UC GCOS .
+-The 
+-.UC EQN
+-language was designed to be easy to use
+-by people who know neither mathematics
+-nor typesetting.
+-Thus
+-.UC EQN
+-knows relatively little about mathematics.
+-In particular, mathematical symbols like
+-+, \(mi, \(mu, parentheses, and so on have no special meanings.
+-.UC EQN
+-is quite happy to set garbage (but it will look good).
+-.PP
+-.UC EQN
+-works as a preprocessor for the typesetter formatter,
+-.UC TROFF [1],
+-so the normal mode of operation is to prepare
+-a document with both mathematics and ordinary text
+-interspersed,
+-and let
+-.UC EQN
+-set the mathematics while
+-.UC TROFF
+-does the body of the text.
+-.PP
+-On
+-.UC UNIX ,
+-.UC EQN
+-will also produce mathematics on
+-.UC DASI 
+-and
+-.UC GSI
+-terminals and on
+-Model 37 teletypes.
+-The input is identical, but you have to use the programs
+-.UC NEQN 
+-and
+-.UC NROFF
+-instead of
+-.UC EQN 
+-and
+-.UC TROFF .
+-Of course, some things won't look as good
+-because terminals 
+-don't provide the variety of characters, sizes and fonts
+-that a typesetter does,
+-but the output is usually adequate for proofreading.
+-.PP
+-To use 
+-.UC EQN
+-on
+-.UC UNIX ,
+-.P1
+-eqn files | troff
+-.P2
+-.UC GCOS
+-use is discussed in section 26.
+-.SC Displayed Equations
+-.PP
+-To tell
+-.UC EQN
+-where a mathematical expression begins and ends,
+-we mark it with lines beginning
+-.UC .EQ
+-and
+-.UC .EN .
+-Thus
+-if you type the lines
+-.P1
+-^EQ
+-x=y+z
+-^EN
+-.P2
+-your output will look like
+-.EQ
+-x=y+z
+-.EN
+-The
+-.UC .EQ
+-and
+-.UC .EN
+-are copied through untouched;
+-they
+-are not otherwise processed
+-by
+-.UC EQN .
+-This means that you have to take care
+-of things like centering, numbering, and so on
+-yourself.
+-The most common way is to use the
+-.UC TROFF
+-and
+-.UC NROFF
+-macro package package `\(mims'
+-developed by M. E. Lesk[3],
+-which allows you to center, indent, left-justify and number equations.
+-.PP
+-With the `\(mims' package,
+-equations are centered by default.
+-To left-justify an equation, use
+-.UC \&.EQ\ L
+-instead of
+-.UC .EQ .
+-To indent it, use
+-.UC .EQ\ I .
+-Any of these can be followed by an arbitrary `equation number'
+-which will be placed at the right margin.
+-For example, the input
+-.P1
+-^EQ I (3.1a)
+-x = f(y/2) + y/2
+-^EN
+-.P2
+-produces the output
+-.EQ I (3.1a)
+-x = f(y/2) + y/2
+-.EN
+-.PP
+-There is also a shorthand notation so
+-in-line expressions
+-like
+-$pi sub i sup 2$
+-can be entered without
+-.UC .EQ
+-and
+-.UC .EN .
+-We will talk about it in section 19.
+-.SC Input spaces
+-.PP
+-Spaces and newlines within an expression are thrown away by
+-.UC EQN .
+-(Normal text is left absolutely alone.)
+-Thus
+-between
+-.UC .EQ
+-and
+-.UC .EN ,
+-.P1
+-x=y+z
+-.P2
+-and
+-.P1
+-x = y + z
+-.P2
+-and
+-.P1
+-x   =   y   
+-   + z
+-.P2
+-and so on
+-all produce the same
+-output
+-.EQ
+-x=y+z
+-.EN
+-You should use spaces and newlines freely to make your input equations
+-readable and easy to edit.
+-In particular, very long lines are a bad idea,
+-since they are often hard to fix if you make a mistake.
+-.SC Output spaces
+-.PP
+-To force extra spaces into the 
+-.ul
+-output,
+-use a tilde ``\|~\|''
+-for each space you want:
+-.P1
+-x~=~y~+~z
+-.P2
+-gives
+-.EQ
+-x~=~y~+~z
+-.EN
+-You can also use a circumflex ``^'', 
+-which gives a space half the width of a tilde.
+-It is mainly useful for fine-tuning.
+-Tabs may also be used to position pieces
+-of an expression,
+-but the tab stops must be set by 
+-.UC TROFF
+-commands.
+-.SC "Symbols, Special Names, Greek"
+-.PP
+-.UC EQN
+-knows some mathematical symbols,
+-some mathematical names, and the Greek alphabet.
+-For example,
+-.P1
+-x=2 pi int sin ( omega t)dt
+-.P2
+-produces
+-.EQ
+-x = 2 pi int sin ( omega t)dt
+-.EN
+-Here the spaces in the input are
+-.B
+-necessary
+-.R
+-to tell
+-.UC EQN
+-that
+-.ul
+-int,
+-.ul
+-pi,
+-.ul
+-sin
+-and
+-.ul
+-omega
+-are separate entities that should get special treatment.
+-The
+-.ul
+-sin,
+-digit 2, and parentheses are set in roman type instead of italic;
+-.ul
+-pi
+-and
+-.ul
+-omega
+-are made Greek;
+-and
+-.ul
+-int
+-becomes the integral sign.
+-.PP
+-When in doubt, leave spaces around separate parts of the input.
+-A
+-.ul
+-very
+-common error is to type
+-.ul
+-f(pi)
+-without leaving spaces on both sides of the
+-.ul
+-pi.
+-As a result,
+-.UC EQN
+-does not recognize
+-.ul
+-pi
+-as a special word, and it appears as
+-$f(pi)$
+-instead of
+-$f( pi )$.
+-.PP
+-A complete list of
+-.UC EQN
+-names appears in section 23.
+-Knowledgeable users can also use
+-.UC TROFF
+-four-character names
+-for anything 
+-.UC EQN
+-doesn't know about,
+-like
+-.ul
+-\\(bs
+-for the Bell System sign \(bs.
+-.SC "Spaces, Again"
+-.PP
+-The only way
+-.UC EQN
+-can deduce that some sequence
+-of letters might be special
+-is if that sequence is separated from the letters
+-on either side of it.
+-This can be done by surrounding a special word by ordinary spaces
+-(or tabs or newlines),
+-as we did in the previous section.
+-.PP
+-.tr ~~
+-You can also make special words stand out by surrounding them
+-with tildes or circumflexes:
+-.P1
+-x~=~2~pi~int~sin~(~omega~t~)~dt
+-.P2
+-is much the same as the last example,
+-except that the tildes
+-not only
+-separate the magic words
+-like
+-.ul
+-sin,
+-.ul
+-omega,
+-and so on,
+-but also add extra spaces,
+-one space per tilde:
+-.EQ
+-x~=~2~pi~int~sin~(~omega~t~)~dt
+-.EN
+-.PP
+-Special words can also be separated by braces { }
+-and double quotes "...",
+-which have special meanings that we will
+-see soon.
+-.tr ~
+-.SC "Subscripts and Superscripts"
+-.PP
+-Subscripts and superscripts are
+-obtained with the words
+-.ul
+-sub
+-and
+-.ul
+-sup.
+-.P1
+-x sup 2 + y sub k
+-.P2
+-gives
+-.EQ
+-x sup 2 + y sub k
+-.EN
+-.UC EQN
+-takes care of all the size changes and vertical motions
+-needed to make the output look right.
+-The words
+-.ul
+-sub
+-and
+-.ul
+-sup
+-must be surrounded by spaces;
+-.ul
+-x sub2
+-will give you
+-$x sub2$ instead of $x sub 2$.
+-Furthermore, don't forget to leave a space
+-(or a tilde, etc.)
+-to mark the end of a subscript or superscript.
+-A common error is to say
+-something like
+-.P1
+-y = (x sup 2)+1
+-.P2
+-which causes
+-.EQ
+-y = (x sup 2)+1
+-.EN
+-instead of
+-the intended
+-.EQ
+-y = (x sup 2 )+1
+-.EN
+-.PP
+-Subscripted subscripts and superscripted superscripts
+-also work:
+-.P1
+-x sub i sub 1
+-.P2
+-is
+-.EQ
+-x sub i sub 1
+-.EN
+-A subscript and superscript on the same thing
+-are printed one above the other
+-if the subscript comes
+-.ul
+-first:
+-.P1
+-x sub i sup 2
+-.P2
+-is
+-.EQ
+-x sub i sup 2
+-.EN
+-.PP
+-Other than this special case,
+-.ul
+-sub
+-and
+-.ul
+-sup
+-group to the right, so
+-.ul
+-x\ sup\ y\ sub\ z
+-means
+-$x sup {y sub z}$, not ${x sup y} sub z$.
+-.SC "Braces for Grouping"
+-.PP
+-Normally, the end of a subscript or superscript is marked
+-simply by a blank (or tab or tilde, etc.)
+-What if the subscript or superscript is something that has to be typed
+-with blanks in it?
+-In that case, you can use the braces
+-{ and } to mark the
+-beginning and end of the subscript or superscript:
+-.P1
+-e sup {i omega t}
+-.P2
+-is
+-.EQ
+-e sup {i omega t}
+-.EN
+-.sp
+-Rule:  Braces can
+-.ul
+-always
+-be used to force 
+-.UC EQN
+-to treat something as a unit,
+-or just to make your intent perfectly clear.
+-Thus:
+-.P1
+-x sub {i sub 1} sup 2
+-.P2
+-is
+-.EQ
+-x sub {i sub 1} sup 2
+-.EN
+-with braces, but
+-.P1
+-x sub i sub 1 sup 2
+-.P2
+-is
+-.EQ
+-x sub i sub 1 sup 2
+-.EN
+-which is rather different.
+-.PP
+-Braces can occur within braces if necessary:
+-.P1
+-e sup {i pi sup {rho +1}}
+-.P2
+-is
+-.EQ
+-e sup {i pi sup {rho +1}}
+-.EN
+-The general rule is that anywhere you could use some single
+-thing like
+-.ul
+-x,
+-you can use an arbitrarily complicated thing if you enclose
+-it in braces.
+-.UC EQN
+-will look after all the details of positioning it and making
+-it the right size.
+-.PP
+-In all cases, make sure you have the
+-right number of braces.
+-Leaving one out or adding an extra will cause 
+-.UC EQN
+-to complain bitterly.
+-.PP
+-Occasionally you will have to
+-print braces.
+-To do this,
+-enclose them in double quotes,
+-like "{".
+-Quoting is discussed in more detail in section 14.
+-.SC Fractions
+-.PP
+-To make a fraction,
+-use the word
+-.ul
+-over:
+-.P1
+-a+b over 2c =1
+-.P2
+-gives
+-.EQ
+-a+b over 2c =1
+-.EN
+-The line is made the right length and positioned automatically.
+-Braces can be used to make clear what goes over what:
+-.P1
+-{alpha + beta} over {sin (x)}
+-.P2
+-is
+-.EQ
+-{alpha + beta} over {sin (x)}
+-.EN
+-What happens when there is both an
+-.ul
+-over
+-and a
+-.ul
+-sup
+-in the same expression?
+-In such an apparently ambiguous case,
+-.UC EQN
+-does the
+-.ul
+-sup
+-before the
+-.ul
+-over,
+-so
+-.P1
+-\(mib sup 2 over pi
+-.P2
+-is
+-$-b sup 2 over pi$
+-instead of
+-$-b sup {2 over pi}$
+-The rules
+-which decide which operation is done first in cases like this
+-are summarized in section 23.
+-When in doubt, however,
+-.ul
+-use braces
+-to make clear what goes with what.
+-.SC "Square Roots"
+-.PP
+-To draw a square root, use
+-.ul
+-sqrt:
+-.P1 2
+-sqrt a+b + 1 over sqrt {ax sup 2 +bx+c}
+-.P2
+-is
+-.EQ
+-sqrt a+b + 1 over sqrt {ax sup 2 +bx+c}
+-.EN
+-Warning _ square roots of tall quantities look lousy,
+-because a root-sign 
+-big enough to cover the quantity is
+-too dark and heavy:
+-.P1
+-sqrt {a sup 2 over b sub 2}
+-.P2
+-is
+-.EQ
+-sqrt{a sup 2 over b sub 2}
+-.EN
+-Big square roots are generally better written as something
+-to the power \(12:
+-.EQ
+-(a sup 2 /b sub 2 ) sup half
+-.EN
+-which is
+-.P1
+-(a sup 2 /b sub 2 ) sup half
+-.P2
+-.SC "Summation, Integral, Etc."
+-.PP
+-Summations, integrals, and similar constructions
+-are easy:
+-.P1
+-sum from i=0 to {i= inf} x sup i
+-.P2
+-produces
+-.EQ
+-sum from i=0 to {i= inf} x sup i
+-.EN
+-Notice that we used
+-braces to indicate where the upper
+-part
+-$i= inf$
+-begins and ends.
+-No braces were necessary for the lower part $i=0$,
+-because it contained no blanks.
+-The braces will never hurt,
+-and if the 
+-.ul
+-from
+-and
+-.ul
+-to
+-parts contain any blanks, you must use braces around them.
+-.PP
+-The
+-.ul
+-from
+-and
+-.ul
+-to
+-parts are both optional,
+-but if both are used,
+-they have to occur in that order.
+-.PP
+-Other useful characters can replace the
+-.ul
+-sum
+-in our example:
+-.P1
+-int   prod   union   inter
+-.P2
+-become, respectively,
+-.EQ
+-int ~~~~~~ prod ~~~~~~ union ~~~~~~ inter
+-.EN
+-Since the thing before the 
+-.ul
+-from
+-can be anything,
+-even something in braces,
+-.ul
+-from-to
+-can often be used in unexpected ways:
+-.P1
+-lim from {n \(mi> inf} x sub n =0
+-.P2
+-is
+-.EQ
+-lim from {n-> inf} x sub n =0
+-.EN
+//GO.SYSIN DD g1
+echo g2
+sed 's/.//' >g2 <<'//GO.SYSIN DD g2'
+-.SC "Size and Font Changes"
+-.PP
+-By default, equations are set in 10-point type (the same size as this guide),
+-with standard mathematical conventions
+-to determine what characters are in roman and what in italic.
+-Although 
+-.UC EQN
+-makes a valiant attempt to use
+-esthetically pleasing sizes and fonts,
+-it is not perfect.
+-To change sizes and fonts, use
+-.ul
+-size n
+-and
+-.ul
+-roman, italic, 
+-.ul
+-bold
+-and
+-.ul
+-fat.
+-Like
+-.ul
+-sub
+-and
+-.ul
+-sup,
+-size
+-and font changes affect only the thing that follows
+-them, and revert to the normal situation
+-at the end of it. Thus
+-.P1
+-bold x y
+-.P2
+-is
+-.EQ
+-bold x y
+-.EN
+-and
+-.P1
+-size 14 bold x = y +
+-   size 14 {alpha + beta}
+-.P2
+-gives
+-.EQ
+-size 14 bold x = y +
+-   size 14 {alpha + beta}
+-.EN
+-As always, you can use braces if you want to affect something
+-more complicated than a single letter.
+-For example, you can change the size of an entire equation by
+-.P1
+-size 12 { ... }
+-.P2
+-.PP
+-Legal sizes which may follow 
+-.ul
+-size
+-are
+-6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36.
+-You can also change the size
+-.ul
+-by
+-a given amount;
+-for example, you can say
+-.ul
+-size~+2
+-to make the size two points bigger,
+-or
+-.ul
+-size~\(mi3
+-to make it three points smaller.
+-This has the advantage that you don't have
+-to know what the current size is.
+-.PP
+-If you are using fonts other than roman, italic and bold,
+-you can say
+-.ul
+-font X
+-where 
+-.ul
+-X
+-is a one character
+-.UC TROFF
+-name or number for the font.
+-Since
+-.UC EQN
+-is tuned for roman, italic and bold,
+-other fonts may not give quite as good an appearance.
+-.PP
+-The
+-.ul
+-fat 
+-operation takes the current font and widens it by overstriking:
+-.ul
+-fat\ grad
+-is
+-$fat grad$ and
+-.ul
+-fat {x sub i}
+-is
+-$fat {x sub i}$.
+-.PP
+-If an entire document is to be in a non-standard size
+-or font, it is a severe nuisance
+-to have to write out a size and font change for each
+-equation.
+-Accordingly, you can set a ``global'' size or font
+-which thereafter affects all equations.
+-At the beginning of any equation, you might say, for instance,
+-.P1
+-^EQ
+-gsize 16
+-gfont R
+- ...
+-^EN
+-.P2
+-to set the size to 16 and the font to roman thereafter.
+-In place of R, you can use any of the
+-.UC TROFF
+-font names.
+-The size after
+-.ul
+-gsize
+-can be a relative change with + or \(mi.
+-.PP
+-Generally,
+-.ul
+-gsize
+-and
+-.ul
+-gfont
+-will appear at the beginning of a document
+-but they can also appear
+-thoughout a document: the global font and size
+-can be changed as often as needed.
+-For example, in a footnote\(dd
+-.FS
+-\(ddLike this one, in which we have a
+-$gsize -2$few random
+-expressions like $x sub i$ and $pi sup 2$.
+-The sizes for these were set by the command
+-.ul
+-gsize~\(mi2.
+-.FE $gsize +2$
+-you will typically want the size of equations to match
+-the size of the footnote text, which is two points smaller
+-than the main text.
+-Don't forget to reset the global size
+-at the end of the footnote.
+-.SC "Diacritical Marks"
+-.PP
+-To get funny marks on top of letters,
+-there are several words:
+-.P1
+-.tr ^^
+-.tr ~~
+-.ta 1i
+-x dot $x dot$
+-x dotdot      $x dotdot$
+-x hat $x hat$
+-x tilde       $x tilde$
+-x vec $x vec$
+-x dyad        $x dyad$
+-x bar $x bar$
+-x under       $x under$
+-.P2
+-The diacritical mark is placed at the right height.
+-The 
+-.ul
+-bar
+-and
+-.ul
+-under
+-are made the right length for the entire construct,
+-as in $x+y+z bar$;
+-other marks are centered.
+-.SC "Quoted Text"
+-.PP
+-Any input entirely within quotes (\|"..."\|)
+-is not subject to any of the font changes and spacing
+-adjustments normally done by the equation setter.
+-This provides a way to do your own spacing and adjusting if needed:
+-.P1
+-italic "sin(x)" + sin (x)
+-.P2
+-is
+-.EQ
+-italic "sin(x)" + sin (x)
+-.EN
+-.PP
+-Quotes are also used to get braces and other
+-.UC EQN
+-keywords printed:
+-.P1
+-"{ size alpha }"
+-.P2
+-is
+-.EQ
+-"{ size alpha }"
+-.EN
+-and
+-.P1
+-roman "{ size alpha }"
+-.P2
+-is
+-.EQ
+-roman "{ size alpha }"
+-.EN
+-.PP
+-The construction "" is often used as a place-holder
+-when grammatically
+-.UC EQN
+-needs something, but you don't actually want anything in your output.
+-For example, to make
+-$"" sup 2 roman He$,
+-you can't just type
+-.ul
+-sup 2 roman He
+-because a
+-.ul
+-sup
+-has to be a superscript
+-.ul
+-on
+-something.
+-Thus you must say
+-.P1
+-"" sup 2 roman He
+-.P2
+-.PP
+-To get a literal quote
+-use ``\\"''.
+-.UC TROFF 
+-characters like
+-.ul
+-\e(bs
+-can appear unquoted, but more complicated things like
+-horizontal and vertical motions with
+-.ul
+-\eh
+-and
+-.ul
+-\ev
+-should
+-always
+-be quoted.
+-(If you've never heard of
+-.ul
+-\\h
+-and
+-.ul
+-\\v,
+-ignore this section.)
+-.SC "Lining Up Equations"
+-.PP
+-Sometimes it's necessary to line up a series of equations
+-at some horizontal position, often at an equals sign.
+-This is done with two operations called
+-.ul
+-mark
+-and
+-.ul
+-lineup.
+-.PP
+-The word
+-.ul
+-mark
+-may appear once at any place in an equation.
+-It remembers the horizontal position where it appeared.
+-Successive equations can contain one occurrence of the word
+-.ul
+-lineup.
+-The place where
+-.ul
+-lineup
+-appears is made to line up
+-with the place marked by the previous
+-.ul
+-mark
+-if at all possible.
+-Thus, for example,
+-you can say
+-.P1
+-^EQ I
+-x+y mark = z
+-^EN
+-^EQ I
+-x lineup = 1
+-^EN
+-.P2
+-to produce
+-.EQ I
+-x+y mark = z
+-.EN
+-.EQ I
+-x lineup = 1
+-.EN
+-For reasons too complicated to talk about,
+-when you use
+-.UC EQN
+-and
+-`\(mims',
+-use either
+-.UC .EQ\ I
+-or
+-.UC .EQ\ L .
+-mark
+-and
+-.ul
+-lineup
+-don't work with centered equations.
+-Also bear in mind that 
+-.ul
+-mark
+-doesn't look ahead;
+-.P1
+-x mark =1
+- ...
+-x+y lineup =z
+-.P2
+-isn't going to work, because there isn't room
+-for the
+-.ul
+-x+y
+-part after the
+-.ul
+-mark
+-remembers where the
+-.ul
+-x
+-is.
+-.SC "Big Brackets, Etc."
+-.PP
+-.tr ~
+-To get big brackets [~],
+-braces {~}, parentheses (~), and bars |~|
+-around things, use the
+-.ul
+-left 
+-and
+-.ul
+-right
+-commands:
+-.tr ~~
+-.P1
+-left { a over b + 1 right }
+- ~=~ left ( c over d right )
+- + left [ e right ]
+-.P2
+-is
+-.EQ
+-left { a over b + 1 right } ~=~ left ( c over d right ) + left [ e right ]
+-.EN
+-The resulting brackets are made big enough to cover whatever they enclose.
+-Other characters can be used besides these,
+-but the are not likely to look very good.
+-One exception is the
+-.ul
+-floor
+-and
+-.ul
+-ceiling 
+-characters:
+-.P1
+-left floor x over y right floor 
+-<= left ceiling a over b right ceiling
+-.P2
+-produces
+-.EQ
+-left floor x over y right floor 
+-<= left ceiling a over b right ceiling
+-.EN
+-.PP
+-Several warnings about brackets are in order.
+-First, braces are typically bigger than brackets and parentheses,
+-because they are made up of three, five, seven, etc., pieces,
+-while brackets can be made up of two, three, etc.
+-Second, big left and right parentheses often look poor,
+-because the character set is poorly designed.
+-.PP
+-The
+-.ul
+-right
+-part may be omitted:
+-a ``left something'' need not have a
+-corresponding 
+-``right
+-something''.
+-If the
+-.ul
+-right
+-part is omitted,
+-put braces around the thing you want the left bracket
+-to encompass.
+-Otherwise, the resulting brackets may be too large.
+-.PP
+-If you want to omit the
+-.ul
+-left
+-part, things are more complicated,
+-because technically you can't have a
+-.ul
+-right
+-without a corresponding
+-.ul
+-left.
+-Instead you have to say
+-.P1
+-left "" ..... right )
+-.P2
+-for example.
+-The
+-.ul
+-left ""
+-means a ``left nothing''.
+-This satisfies the rules without hurting your output.
+-.SC "Piles"
+-.PP
+-There is a general facility for making vertical piles
+-of things; it comes in several flavors.
+-For example:
+-.P1
+-.tr ~~
+-A ~=~ left [
+-  pile { a above b above c }
+-  ~~ pile { x above y above z }
+-right ]
+-.P2
+-will make
+-.EQ
+-A ~=~ left [
+-pile { a above b above c } ~~ pile { x above y above z }
+-right ]
+-.EN
+-The elements of the pile (there can be as many as you want)
+-are centered one above another, at the right height for
+-most purposes.
+-The keyword
+-.ul
+-above
+-is used to separate the pieces;
+-braces are used around the entire list.
+-The elements of a pile can be as complicated as needed, even containing more piles.
+-.PP
+-Three other forms of pile exist:
+-.ul
+-lpile
+-makes a pile with the elements left-justified;
+-.ul
+-rpile
+-makes a right-justified pile;
+-and
+-.ul
+-cpile
+-makes a centered pile, just like
+-.ul
+-pile.
+-The vertical spacing between the pieces
+-is somewhat larger for
+-.ul
+-l-,
+-.ul
+-r-
+-and
+-.ul
+-cpiles
+-than it is for ordinary piles.
+-.P1 2
+-roman sign (x)~=~ 
+-left {
+-   lpile {1 above 0 above -1} 
+-   ~~ lpile
+-    {if~x>0 above if~x=0 above if~x<0}
+-.P2
+-makes
+-.EQ
+-roman sign (x)~=~ 
+-left {
+-   lpile {1 above 0 above -1} 
+-   ~~ lpile
+-    {if~x>0 above if~x=0 above if~x<0}
+-.EN
+-Notice the left brace
+-without a matching right one.
+-.SC Matrices
+-.PP
+-It is also possible to make matrices.
+-For example, to make
+-a neat array like
+-.EQ
+-matrix {
+-  ccol { x sub i above y sub i }
+-  ccol { x sup 2 above y sup 2 }
+-}
+-.EN
+-you have to type
+-.P1
+-matrix {
+-  ccol { x sub i above y sub i }
+-  ccol { x sup 2 above y sup 2 }
+-}
+-.P2
+-This produces a matrix with
+-two centered columns.
+-The elements of the columns are then listed just as for a pile,
+-each element separated by the word
+-.ul
+-above.
+-You can also use
+-.ul
+-lcol
+-or
+-.ul
+-rcol
+-to left or right adjust columns.
+-Each column can be separately adjusted,
+-and there can be as many columns as you like.
+-.PP
+-The reason for using a matrix instead of two adjacent piles, by the way,
+-is that if the elements of the piles don't all have the same height,
+-they won't line up properly.
+-A matrix forces them to line up,
+-because it looks at the entire structure before deciding what
+-spacing to use.
+-.PP
+-A word of warning about matrices _
+-.ul
+-each column must have the same number of elements in it.
+-The world will end if you get this wrong.
+//GO.SYSIN DD g2
+echo g3
+sed 's/.//' >g3 <<'//GO.SYSIN DD g3'
+-.SC "Shorthand for In-line Equations"
+-.PP
+-In a mathematical document,
+-it is necessary to follow mathematical conventions
+-not just in display equations,
+-but also in the body of the text,
+-for example by making variable names like $x$ italic.
+-Although this could be done by surrounding the appropriate parts
+-with
+-.UC .EQ
+-and
+-.UC .EN ,
+-the continual repetition of
+-.UC .EQ
+-and
+-.UC .EN
+-is a nuisance.
+-Furthermore, with `\(mims',
+-.UC .EQ
+-and
+-.UC .EN
+-imply a displayed equation.
+-.PP
+-.UC EQN
+-provides a shorthand for short in-line expressions.
+-You can define two characters to mark the left and right ends
+-of an in-line equation, and then type expressions right in the middle of text
+-lines.
+-To set both the left and right characters to dollar signs, for example,
+-add to the beginning of your document the three lines
+-.P1
+- .EQ
+- delim %%
+- .EN
+-.P2
+-Having done this, you can then say things like
+-.P1
+-.fi
+-Let %alpha sub i% be the primary variable,
+-and let %beta% be zero.
+-Then we can show that %x sub 1% is %>=0%.
+-.P2
+-This works as
+-you might expect _
+-spaces, newlines, and so on are significant
+-in the text, but not in the equation part itself.
+-Multiple equations can occur in a single input line.
+-.PP
+-Enough room is left before and after a line that contains
+-in-line expressions
+-that something like
+-$sum from i=1 to n x sub i$
+-does not interfere with the lines surrounding it.
+-.PP
+-To turn off the delimiters,
+-.P1
+- .EQ
+- delim off
+- .EN
+-.P2
+-Warning: don't use braces, tildes, circumflexes, or double quotes as delimiters _
+-chaos will result.
+-.SC "Definitions"
+-.PP
+-.UC EQN
+-provides a facility so you can give
+-a frequently-used string of characters a name,
+-and thereafter just type the name instead of the
+-whole string.
+-For example, if the sequence
+-.P1
+-x sub i sub 1 + y sub i sub 1
+-.P2
+-appears repeatedly throughout a paper,
+-you can save re-typing it each time by defining it like this:
+-.P1 2
+-define  xy  'x sub i sub 1 + y sub i sub 1'
+-.P2
+-This makes
+-.ul
+-xy
+-a shorthand for whatever characters occur between the single quotes
+-in the definition.
+-You can use any character instead of quote to mark the ends of the definition,
+-so long as it doesn't appear inside the definition.
+-.PP
+-Now you can use
+-.ul
+-xy
+-like this:
+-.P1
+-^EQ
+-f(x) = xy ...
+-^EN
+-.P2
+-and so on.
+-Each occurrence of
+-.ul
+-xy
+-will expand into what it was defined as.
+-Be careful to leave spaces or their equivalent
+-around the name
+-when you actually use it, so
+-.UC EQN
+-will be able to identify it as special.
+-.PP
+-There are several things to watch out for.
+-First, although definitions can use previous definitions,
+-as in
+-.P1
+- .EQ
+- define  xi  ' x sub i '
+- define  xi1  ' xi sub 1 '
+- .EN
+-.P2
+-.ul
+-don't define something in terms of itself'
+-A favorite error is to say
+-.P1
+-define  X  ' roman X '
+-.P2
+-This is a guaranteed disaster,
+-since X
+-.ul
+-is
+-now defined in terms of itself.
+-If you say
+-.P1
+-define  X  ' roman "X" '
+-.P2
+-however, the quotes
+-protect the second X,
+-and everything works fine.
+-.PP
+-.UC EQN
+-keywords can be redefined.
+-You can make
+-/ mean
+-.ul
+-over
+-by saying
+-.P1
+-define  /  ' over '
+-.P2
+-or redefine
+-.ul
+-over
+-as /
+-with
+-.P1
+-define  over  ' / '
+-.P2
+-.PP
+-If you need different things
+-to print on a terminal and on the typesetter, it is sometimes worth
+-defining a symbol differently in
+-.UC NEQN
+-and
+-.UC EQN .
+-This can be done with
+-.ul
+-ndefine
+-and
+-.ul
+-tdefine.
+-A definition made with
+-.ul
+-ndefine
+-only takes effect if you are running
+-.UC NEQN ;
+-if you use
+-.ul
+-tdefine,
+-the definition only applies for
+-.UC EQN .
+-Names defined with plain
+-.ul
+-define
+-apply to both
+-.UC EQN 
+-and
+-.UC NEQN .
+-.SC "Local Motions"
+-.PP
+-Although
+-.UC EQN
+-tries to get most things at the right place on the paper,
+-it isn't perfect, and occasionally you will need to tune
+-the output to make it just right.
+-Small extra horizontal spaces can be obtained with
+-tilde and circumflex.
+-You can also say
+-.ul
+-back n
+-and
+-.ul
+-fwd n
+-to move small amounts horizontally.
+-.ul
+-n
+-is how far to move in 1/100's of an em (an em is about the width
+-of the letter
+-`m'.)
+-Thus
+-.ul
+-back 50
+-moves back about half the width of an m.
+-Similarly you can move things up or down with
+-.ul
+-up n
+-and
+-.ul
+-down n.
+-As with 
+-.ul
+-sub
+-or
+-.ul
+-sup,
+-the local motions affect the next thing in the input,
+-and this can be something arbitrarily complicated if it is enclosed
+-in braces.
+//GO.SYSIN DD g3
+echo g4
+sed 's/.//' >g4 <<'//GO.SYSIN DD g4'
+-.SC "A Large Example"
+-.PP
+-Here is the complete source for the three display equations
+-in the abstract of this guide.
+-.sp
+-.nf
+-.ps -2
+-.vs -2
+- .EQ I
+- G(z)~mark =~ e sup { ln ~ G(z) }
+- ~=~ exp left ( 
+- sum from k>=1 {S sub k z sup k} over k right )
+- ~=~  prod from k>=1 e sup {S sub k z sup k /k}
+- .EN
+- .EQ I
+- lineup = left ( 1 + S sub 1 z + 
+- { S sub 1 sup 2 z sup 2 } over 2! + ... right )
+- left ( 1+ { S sub 2 z sup 2 } over 2
+- + { S sub 2 sup 2 z sup 4 } over { 2 sup 2 cdot 2! }
+- + ... right ) ...
+- .EN
+- .EQ I
+- lineup =  sum from m>=0 left (
+- sum from
+- pile { k sub 1 ,k sub 2 ,..., k sub m  >=0
+- above
+- k sub 1 +2k sub 2 + ... +mk sub m =m}
+- { S sub 1 sup {k sub 1} } over {1 sup k sub 1 k sub 1 ! } ~
+- { S sub 2 sup {k sub 2} } over {2 sup k sub 2 k sub 2 ! } ~
+- ...
+- { S sub m sup {k sub m} } over {m sup k sub m k sub m ! } 
+- right ) z sup m
+- .EN
+-.sp
+-.fi
+-.ps +2
+-.vs +2
+-.SC "Keywords, Precedences, Etc."
+-.PP
+-If you don't use braces,
+-.UC EQN
+-will
+-do operations in the order shown in this list.
+-.P1 3
+-.ft I
+-dyad vec under bar tilde hat dot dotdot
+-fwd  back  down  up
+-fat  roman  italic  bold  size
+-sub  sup  sqrt  over
+-from  to
+-.ft R
+-.P2
+-These operations group to the left:
+-.P1
+-.ft I
+-over  sqrt  left  right
+-.ft R
+-.P2
+-All others group to the right.
+-.PP
+-Digits, parentheses, brackets, punctuation marks, and these mathematical words
+-are converted
+-to Roman font when encountered:
+-.P1
+-sin  cos  tan  sinh  cosh  tanh  arc
+-max  min  lim  log  ln  exp
+-Re  Im  and  if  for  det
+-.P2
+-These character sequences are recognized and translated as shown.
+-.sp
+-.nf
+-.tr -\(mi
+-.in .5i
+-.ta 1i
+->=            $>=$
+-<=            $<=$
+-==            $==$
+-!=            $!=$
+-+-            $+-$
+-->            $->$
+-<-            $<-$
+-<<            $<<$
+->>            $>>$
+-inf           $inf$
+-partial               $partial$
+-half          $half$
+-prime         $prime$
+-approx                $approx$
+-nothing               $nothing$
+-cdot          $cdot$
+-times         $times$
+-del           $del$
+-grad          $grad$
+-\&...         $...$
+-,...,         $,...,$
+-sum           $sum$
+-.sp 3p
+-int           $int$
+-.sp 2p
+-prod          $prod$
+-union         $union$
+-inter         $inter$
+-.sp
+-.in
+-.fi
+-.tr --
+-.PP
+-To obtain Greek letters,
+-simply spell them out in whatever case you want:
+-.sp
+-.nf
+-.in .2i
+-.ta .7i 1.4i 2.1i
+-DELTA $DELTA$ iota    $iota$
+-GAMMA $GAMMA$ kappa   $kappa$
+-LAMBDA        $LAMBDA$        lambda  $lambda$
+-OMEGA $OMEGA$ mu      $mu$
+-PHI   $PHI$   nu      $nu$
+-PI    $PI$    omega   $omega$
+-PSI   $PSI$   omicron $omicron$
+-SIGMA $SIGMA$ phi     $phi$
+-THETA $THETA$ pi      $pi$
+-UPSILON       $UPSILON$       psi     $psi$
+-XI    $XI$    rho     $rho$
+-alpha $alpha$ sigma   $sigma$
+-beta  $beta$  tau     $tau$
+-chi   $chi$   theta   $theta$
+-delta $delta$ upsilon $upsilon$
+-epsilon       $epsilon$       xi      $xi$
+-eta   $eta$   zeta    $zeta$
+-gamma $gamma$
+-.sp
+-.in
+-.fi
+-.PP
+-These are all the words known to
+-.UC EQN
+-(except for characters with names),
+-together with the section where they are discussed.
+-.sp
+-.nf
+-.in .2i
+-.ta .7i 1.4i 2.1i
+-above 17, 18  lpile   17
+-back  21      mark    15
+-bar   13      matrix  18
+-bold  12      ndefine 20
+-ccol  18      over    9
+-col   18      pile    17
+-cpile 17      rcol    18
+-define        20      right   16
+-delim 19      roman   12
+-dot   13      rpile   17
+-dotdot        13      size    12
+-down  21      sqrt    10
+-dyad  13      sub     7
+-fat   12      sup     7
+-font  12      tdefine 20
+-from  11      tilde   13
+-fwd   21      to      11
+-gfont 12      under   13
+-gsize 12      up      21
+-hat   13      vec     13
+-italic        12      ~, ^    4, 6
+-lcol  18      { }     8
+-left  16      "..."   8, 14
+-lineup        15
+-.sp
+-.in 0
+-.fi
+-.SC Troubleshooting
+-.PP
+-If you make a mistake in an equation,
+-like leaving out a brace (very common)
+-or having one too many (very common)
+-or having a
+-.ul
+-sup
+-with nothing before it (common),
+-.UC EQN
+-will tell you with the message
+-.P1 2
+-.ft I
+-syntax error between lines x and y, file z
+-.ft R
+-.P2
+-where
+-.ul
+-x
+-and
+-.ul
+-y
+-are approximately the lines
+-between which the trouble occurred, and
+-.ul
+-z
+-is the name
+-of the file in question.
+-The line numbers are approximate _ look nearby as well.
+-There are also self-explanatory messages that arise if you leave out a quote
+-or try to run
+-.UC EQN
+-on a non-existent file.
+-.PP
+-If you want to check a document before actually printing it
+-(on
+-.UC UNIX 
+-only),
+-.P1
+-eqn  files >/dev/null
+-.P2
+-will
+-throw away the output but print the messages.
+-.PP
+-If you use something like dollar signs as delimiters,
+-it is easy to leave one out.
+-This causes very strange troubles.
+-The program
+-.ul
+-checkeq
+-(on
+-.UC GCOS ,
+-use
+-.ul
+-\&./checkeq
+-instead)
+-checks for misplaced or missing dollar signs
+-and similar troubles.
+-.PP
+-In-line equations can only be so big
+-because of an internal buffer in
+-.UC TROFF .
+-If you get a message
+-``word overflow'',
+-you have exceeded this limit.
+-If you print the equation as a displayed equation
+-this message will usually go away.
+-The message
+-``line overflow''
+-indicates you have exceeded an even bigger buffer.
+-The only cure for this is to break the equation into two separate ones.
+-.PP
+-On a related topic,
+-.UC EQN
+-does not break equations by itself _
+-you must split long equations up across multiple lines
+-by yourself,
+-marking each by a separate
+-.UC .EQ
+-\&...\&
+-.UC .EN
+-sequence.
+-.UC EQN
+-does warn about equations that are too long
+-to fit on one line.
+//GO.SYSIN DD g4
+echo g5
+sed 's/.//' >g5 <<'//GO.SYSIN DD g5'
+-.SC "Use on UNIX"
+-.PP
+-To print a document that contains mathematics on
+-the
+-.UC UNIX
+-typesetter,
+-.P1
+-eqn files | troff
+-.P2
+-If
+-there are any 
+-.UC TROFF
+-options, they go after the
+-.UC TROFF 
+-part of the command. For example,
+-.P1
+-eqn files | troff -ms
+-.P2
+-To run the same document on the
+-.UC GCOS
+-typesetter, use
+-.P1
+-eqn files | troff -g (other options) | gcat
+-.P2
+-.PP
+-A compatible version of
+-.UC EQN
+-can be used on devices like teletypes and
+-.UC DASI
+-and
+-.UC GSI
+-terminals
+-which have half-line forward and reverse capabilities.
+-To print
+-equations on a Model 37 teletype, for example, use
+-.P1
+-neqn files | nroff
+-.P2
+-The language for equations recognized by
+-.UC NEQN
+-is identical to that of
+-.UC EQN,
+-although of course the output is more restricted.
+-.PP
+-To use a
+-.UC GSI
+-or
+-.UC DASI
+-terminal as the output device,
+-.P1
+-neqn files | nroff -T\fIx\fP
+-.P2
+-where
+-.ul
+-x
+-is the terminal type you are using,
+-such as
+-.ul
+-300
+-or
+-.ul
+-300S.
+-.PP
+-.UC EQN
+-and
+-.UC NEQN
+-can be used with the 
+-.UC TBL
+-program[2]
+-for setting tables that contain mathematics.
+-Use
+-.UC TBL
+-before
+-.UC [N]EQN ,
+-like this:
+-.P1
+-tbl  files  |  eqn  |  troff
+-tbl  files  |  neqn  |  nroff
+-.P2
+-.SC "Acknowledgments"
+-.PP
+-We are deeply indebted to J. F. Ossanna,
+-the author of
+-.UC TROFF ,
+-for his willingness to extend
+-.UC TROFF
+-to make our task easier,
+-and for his
+-continuous assistance during the development
+-and evolution
+-of
+-.UC EQN .
+-We are also grateful to A. V. Aho
+-for advice on language design,
+-to S. C. Johnson for assistance with
+-the
+-.UC YACC
+-compiler-compiler,
+-and to all the
+-.UC EQN
+-users
+-who have made helpful suggestions and criticisms.
+-.SH
+-References
+-.LP
+-.IP [1]
+-J. F. Ossanna,
+-.UC NROFF/TROFF \& ``
+-User's Manual'',
+-Bell Laboratories Computing Science Technical Report
+-#54, 1976.
+-.IP [2]
+-M. E. Lesk,
+-``Typing Documents on
+-.UC UNIX '',
+-Bell Laboratories, 1976.
+-.IP [3]
+-M. E. Lesk,
+-.UC TBL \& ``
+-\(em A Program for Setting Tables'',
+-Bell Laboratories Computing Science Technical Report #49,
+-1976.
+//GO.SYSIN DD g5
diff --git a/doc/7thEdMan/vol2/f77 b/doc/7thEdMan/vol2/f77
new file mode 100644 (file)
index 0000000..609a93f
--- /dev/null
@@ -0,0 +1,2004 @@
+.de XX
+.ne 3
+.sp .3
+.ti -1i
+.ta 1i
+\\$1   \c
+..
+.EQ
+delim $$
+.EN
+.ND "1 August 1978"
+.RP
+.TL
+A Portable Fortran 77 Compiler
+.AU
+S. I. Feldman
+.AU
+P. J. Weinberger
+.AI
+.MH
+.AB
+.LP
+The Fortran language has just been revised.
+The new language, known as Fortran 77,
+became an official American National Standard on April 3, 1978.
+We report here on a compiler and run-time system for the new extended language.
+This is believed to be the first complete Fortran 77 system to be implemented.
+This compiler is designed to be portable,
+to be correct and complete,
+and to generate code compatible with calling sequences produced by C compilers.
+In particular, this Fortran is quite usable on
+.UX
+systems.
+In this paper, we describe the language compiled,
+interfaces between procedures,
+and file formats assumed by the I/O system.
+An appendix describes the Fortran 77 language.
+.AE
+.CS 9 10 19 0 0 8
+.NH 0
+INTRODUCTION
+.PP
+The Fortran language has just been revised.
+The new language, known as Fortran 77, became an official American National Standard [1] on April 3, 1978.
+for the language, known as Fortran 77, is about to be published.
+Fortran 77 supplants 1966 Standard Fortran [2].
+We report here on a compiler and run-time system for the new extended language.
+The compiler and computation library were written by SIF, the I/O system by PJW.
+We believe ours to be the first complete Fortran 77 system to be implemented.
+This compiler is designed to be portable to a number of different machines,
+to be correct and complete,
+and to generate code compatible with calling sequences produced
+by compilers for the C language [3].
+In particular,
+it is in use on
+.UX
+systems.
+Two families of C compilers are in use at Bell Laboratories,
+those based on D. M. Ritchie's PDP-11 compiler[4]
+and those based on S. C. Johnson's portable C compiler [5].
+This Fortran compiler can drive the second passes of either family.
+In this paper, we describe the language compiled,
+interfaces between procedures,
+and file formats assumed by the I/O system.
+We will describe implementation details in companion papers.
+.PP
+.NH 2
+Usage
+.PP
+At present, versions of the compiler run on and compile for the PDP-11,
+the VAX-11/780,
+and the Interdata 8/32
+.UX
+systems.
+The command to run the compiler is
+.DS C
+f\|77  \fIflags  file . . .\fR
+.DE
+.B f\|77
+is a general-purpose command for compiling and loading Fortran and Fortran-related files.
+EFL [6] and Ratfor [7] source files will be preprocessed before being presented to the Fortran compiler.
+C and assembler source files will be compiled by the appropriate programs.
+Object files will be loaded.
+(The
+.B f\|77
+and
+.B cc
+commands cause slightly different loading sequences to be generated,
+since Fortran programs need a few extra libraries and a different startup routine
+than do C programs.)
+The following file name suffixes are understood:
+.DS I
+ .f    Fortran source file
+ .e    EFL source file
+ .r    Ratfor source file
+ .c    C source file
+ .s    Assembler source file
+ .o    Object file
+.DE
+The following flags are understood:
+.in +1i
+.XX \(miS
+Generate assembler output for each source file, but do not assemble it.
+Assembler output for a source file
+.B x.f,
+.B x.e,
+.B x.r,
+or
+.B x.c
+is put on file
+\fBx.s\fR.
+.XX \(mic
+Compile but do not load.
+Output for
+.B x.f,
+.B x.e,
+.B x.r,
+.B x.c,
+or
+.B x.s
+is put on file
+.B x.o.
+.XX \(mim
+Apply the M4 macro preprocessor to each EFL or Ratfor source file before using the appropriate compiler.
+.XX \(mif
+Apply the EFL or Ratfor processor to all
+relevant files, and leave the output from
+.B x.e
+or
+.B x.r
+on
+.B x.f.
+Do not compile the resulting Fortran program.
+.XX \(mip
+Generate code to produce usage profiles.
+.XX "\(mio \fIf\fR"
+Put executable module on file
+.I f.
+(Default is
+\fBa.out\fR).
+.XX \(miw
+Suppress all warning messages.
+.XX \(miw66
+Suppress warnings about Fortran 66 features used.
+.XX \(miO
+Invoke the C object code optimizer.
+.XX \(miC
+Compile code the checks that subscripts are within array bounds.
+.XX \(mionetrip
+Compile code that performs every
+.B do
+loop at least once.
+(see Section 2.10).
+.XX \(miU
+Do not convert upper case letters to lower case.
+The default is to convert Fortran programs to lower case.
+.XX \(miu
+Make the default type of a variable
+.B undefined.
+(see Section 2.3).
+.XX \(miI2
+On machines which support short integers,
+make the default integer constants and variables short.
+(\fB\(miI4\fR is the standard value of this option).  (see Section 2.14).
+All logical quantities will be short.
+.XX \(miE
+The remaining characters in the argument are used as an EFL flag argument.
+.XX \(miR
+The remaining characters in the argument are used as a Ratfor flag argument.
+.XX \(miF
+Ratfor and and EFL source programs are pre-processed into Fortran files,
+but those files are not compiled or removed.
+.in -1i
+.LP
+Other flags,
+all library names (arguments beginning \fB\(mil\fR),
+and any names not ending with one of the understood suffixes are passed to the loader.
+.NH 2
+Documentation Conventions
+.PP
+In running text, we write Fortran keywords and other literal strings in boldface lower case.
+Examples will be presented in lightface lower case.
+Names representing a class of values will be printed in italics.
+.NH 2
+Implementation Strategy
+.PP
+The compiler and library are written entirely in C.
+The compiler  generates C compiler intermediate code.
+Since there are C compilers running on a variety of machines,
+relatively small changes will make this Fortran compiler generate code for any of them.
+Furthermore, this approach guarantees that the resulting programs are compatible with C usage.
+The runtime computational library is complete.
+The mathematical functions are computed to at least 63 bit precision.
+The runtime I/O library makes use of D. M. Ritchie's Standard C I/O package [8]
+for transferring data.
+With the few exceptions described below, only documented calls are used,
+so it should be relatively easy to modify to run on other operating
+systems.
+.NH 1
+LANGUAGE EXTENSIONS
+.PP
+Fortran 77 includes almost all of Fortran 66 as a subset.
+We describe the differences briefly in the Appendix.
+The most important additions are a character string data type,
+file-oriented input/output statements, and random access I/O.
+Also, the language has been cleaned up considerably.
+.PP
+In addition to implementing the language specified in the new Standard,
+our compiler implements a few extensions described in this section.
+Most are useful additions to the language.
+The remainder are extensions
+to make it easier to communicate with C procedures
+or to permit compilation of
+old (1966 Standard) programs.
+.NH 2
+Double Complex Data Type
+.IP
+The new type
+.B "double complex"
+is defined.
+Each datum is represented by a pair of double precision real variables.
+A double complex version of every
+.B complex
+built-in function is provided.
+The specific function names begin with \fBz\fR instead of \fBc\fR.
+.NH 2
+Internal Files
+.IP
+The Fortran 77 standard introduces ``internal files'' (memory arrays), but
+restricts their use to formatted sequential I/O statements.
+Our I/O system also permits internal files to be used
+in direct and unformatted reads and writes.
+.NH 2
+Implicit Undefined statement
+.IP
+Fortran 66 has a fixed rule that the type of a variable that does not appear in a type statement
+is
+.B integer
+if its first letter is
+\fBi, j, k, l, m\fR or \fBn\fR,
+and
+.B real
+otherwise.
+Fortran 77 has an
+.B implicit
+statement for overriding this rule.
+As an aid to good programming practice, we permit an additional type,
+.B undefined.
+The statement
+.DS
+implicit undefined(a-z)
+.DE
+turns off the automatic data typing mechanism,
+and the compiler will issue a diagnostic for each variable that is used but does
+not appear in a type statement.
+Specifying the
+.B \(miu
+compiler flag is equivalent to beginning each procedure with this statement.
+.NH 2
+Recursion
+.IP
+Procedures may call themselves, directly or through a chain of other procedures.
+.NH 2
+Automatic Storage
+.IP
+Two new keywords are recognized,
+.B static
+and
+.B automatic.
+These keywords may appear as ``types'' in type statements and in
+.B implicit
+statements.
+Local variables are static by default;
+there is exactly one copy of the datum, and its value is retained between calls.
+There is one copy of each variable declared
+.B automatic
+for each invocation of the procedure.
+Automatic variables may not appear in
+.B equivalence,
+.B data,
+or
+.B save
+statements.
+.NH 2
+Source Input Format
+.IP
+The Standard expects input to the compiler to be in 72 column format:
+except in comment lines,
+the first five characters are the statement number, the next is the continuation character,
+and the next sixty-six are the body of the line.
+(If there are fewer than seventy-two characters on a line, the compiler pads it with blanks;
+characters after the seventy-second are ignored).
+.IP
+In order to make it easier to type Fortran programs,
+our compiler also accepts input in variable length lines.
+An ampersand (``&'') in the first position of a line indicates a continuation
+line; the remaining characters form the body of the line.
+A tab character in one of the first six positions of a line signals the
+end of the statement number and continuation part of the line;
+the remaining characters form the body of the line.
+A tab elsewhere on the line is treated as another kind of blank by the
+compiler.
+.IP
+In the Standard, there are only 26 letters \(em Fortran is a one-case language.
+Consistent with ordinary
+.UX
+system usage, our compiler expects lower case input.
+By default, the compiler converts all upper case characters to lower case except those inside character constants.
+However, if the
+.B \(miU
+compiler flag is specified, upper case letters are not transformed.
+In this mode, it is possible to specify external names with upper case letters in them,
+and to have distinct variables differing only in case.
+Regardless of the setting of the flag,
+keywords will only be recognized in lower case.
+.NH 2
+Include Statement
+.IP
+The statement
+.DS
+include \(fmstuff\|\(fm
+.DE
+is replaced by the contents of the file
+.B stuff.
+\fBinclude\fRs may be nested to a reasonable depth, currently ten.
+.NH 2
+Binary Initialization Constants
+.IP
+A
+.B logical,
+.B real,
+or
+.B integer
+variable may be initialized in a
+.B data
+statement
+by a binary constant, denoted by a letter followed by a quoted string.
+If the letter is \fBb\fR, the string is binary, and only zeroes and ones are permitted.
+If the letter is \fBo\fR, the string is octal, with digits \fB0\(mi7\fR.
+If the letter is \fBz\fR or \fBx\fR, the string is hexadecimal, with digits \fB0\(mi9\fR, \fBa\(mif\fR.
+Thus, the statements
+.DS
+integer a(3)
+data a / b\(fm1010\(fm, o\(fm12\(fm, z\(fma\(fm /
+.DE
+initialize all three elements of
+.B a
+to ten.
+.NH 2
+Character Strings
+.IP
+For compatibility with C usage, the following backslash escapes are recognized:
+.DS
+\en    newline
+\et    tab
+\eb    backspace
+\ef    form feed
+\e0    null
+\e\(fm apostrophe (does not terminate a string)
+\e"    quotation mark (does not terminate a string)
+\e\e   \e
+\e\fIx\fR      \fIx\fR,  where \fIx\fR is any other character
+.DE
+Fortran 77 only has one quoting character, the apostrophe.
+Our compiler and I/O system recognize
+both the apostrophe ( \(fm ) and the double-quote ( " ).
+If a string begins with one variety of quote mark, the other may be embedded within it
+without using the repeated quote or backslash escapes.
+.IP
+Every unequivalenced scalar local character variable and every character string constant is aligned
+on an
+.B integer
+word boundary.
+Each character string constant appearing outside a
+.B data
+statement is followed by a
+null character to ease communication with C routines.
+.NH 2
+Hollerith
+.IP
+Fortran 77 does not have the old Hollerith (\fIn\|\fBh\fR)
+notation,
+though the new Standard recommends implementing the old Hollerith feature
+in order to improve compatibility with old programs.
+In our compiler, Hollerith data may be used in place of character string constants,
+and may also be used to initialize non-character variables in
+.B data
+statements.
+.NH 2
+Equivalence Statements
+.IP
+As a very special and peculiar case,
+Fortran 66 permits an element of a multiply-dimensioned array to be represented by
+a singly-subscripted reference in
+.B equivalence
+statements.
+Fortran 77 does not permit this usage, since
+subscript lower bounds may now be different from 1.
+Our compiler permits single subscripts in
+.B equivalence
+statements,
+under the interpretation that all missing subscripts are equal to 1.
+A warning message is printed for each such incomplete subscript.
+.NH 2
+One-Trip DO Loops
+.IP
+The Fortran 77 Standard requires that the range of a
+.B do
+loop not be performed
+if the initial value is already past the limit value,
+as in
+.DS
+do 10 i = 2, 1
+.DE
+The 1966 Standard stated that the effect of such a statement was undefined,
+but it was common practice that the range of a
+.B do
+loop would be performed
+at least once.
+In order to accommodate old programs, though they were in violation of the 1966 Standard,
+the
+.B \(mionetrip
+compiler flag causes non-standard loops to be generated.
+.NH 2
+Commas in Formatted Input
+.IP
+The I/O system attempts to be more lenient than the
+Standard when it seems worthwhile.
+When doing a formatted read of non-character variables,
+commas may be used as value separators in the input record,
+overriding the field lengths given in the format statement.
+Thus,
+the format
+.DS
+(i10, f20.10, i4)
+.DE
+will read the record
+.DS
+\(mi345,.05e\(mi3,12
+.DE
+correctly.
+.NH 2
+Short Integers
+.IP
+On machines that support halfword integers,
+the compiler accepts declarations of type
+.B integer\(**2.
+(Ordinary integers follow the Fortran rules about occupying the same
+space as a REAL variable; they are assumed to be of C type
+.B "long int" ;
+halfword integers are of C type
+.B "short int" .)
+An expression involving only objects of type
+.B integer\(**2
+is of that type.
+Generic functions return short or long integers depending on the actual types of their arguments.
+If a procedure is compiled using the
+.B \(miI2
+flag, all small integer constants will be
+of type
+.B integer\(**2.
+If the precision of an integer-valued intrinsic function is not determined by the generic function rules,
+one will be chosen that returns the prevailing length
+(\fBinteger\(**2\fR when the \fB\(miI2\fR command flag is in effect).
+When the
+.B \(miI2
+option is in effect, all quantities of type
+.B logical
+will be short.
+Note that these short integer and logical quantities do not obey the standard rules for storage association.
+.NH 2
+Additional Intrinsic Functions
+.IP
+This compiler supports all of the intrinsic functions specified in the Fortran 77 Standard.
+In addition, there are functions for performing bitwise Boolean operations
+(
+.B or,
+.B and,
+.B xor,
+and
+.B not)
+and for accessing the
+.UX
+command arguments
+(
+.B getarg
+and
+.B iargc
+).
+.NH 1
+VIOLATIONS OF THE STANDARD
+.PP
+We know only thre ways in which our Fortran system violates the new standard:
+.NH 2
+Double Precision Alignment
+.IP
+The Fortran standards (both 1966 and 1977)
+permit
+.B common
+or
+.B equivalence
+statements to force a double precision quantity onto an odd word boundary,
+as in the following example:
+.DS I
+real a(4)
+double precision b,c
+.sp .5
+equivalence (a(1),b), (a(4),c)
+.DE
+Some machines (e.g., Honeywell 6000, IBM 360) require that double precision quantities be on double word boundaries;
+other machines (e.g., IBM 370), run inefficiently if this alignment rule is not observed.
+It is possible to tell which equivalenced and common variables suffer from a forced odd
+alignment, but every double precision argument would have to be assumed on a bad boundary.
+To load such a quantity on some machines,
+it would be necessary to use separate operations to move the upper and lower halves
+into the halves of an aligned temporary, then to load that double precision temporary; the reverse would be
+needed to store a result.
+We have chosen to require that all double precision real and complex quantities
+fall on even word boundaries on machines with corresponding hardware requirements,
+and to issue a diagnostic if the source code demands a violation of the rule.
+.NH 2
+Dummy Procedure Arguments
+.IP
+If any argument of a procedure is of type character,
+all dummy procedure arguments of that procedure must be declared
+in an
+.B external
+statement.
+This requirement arises as a subtle corollary of the way we represent character string arguments
+and of the one-pass nature of the compiler.
+A warning is printed if a dummy procedure is not declared
+.B external.
+Code is correct if there are no
+.B character
+arguments.
+.NH 2
+T and TL Formats
+.IP
+The implementation of the
+.B t
+(absolute tab)
+and
+.B tl
+(leftward tab)
+format codes
+is defective.
+These codes allow rereading or rewriting part of the
+record which has already been processed.
+(Section 6.3.2 in the Appendix.)
+The implementation uses seeks,
+so if the unit is not one which allows seeks,
+such as a terminal,
+the program is in error.
+(People who can make a case for using
+.B tl
+should let us know.)
+A benefit of the implementation chosen is
+that there is no upper limit on the length of
+a record,
+nor is it necessary to predeclare any record
+lengths except where specifically required
+by Fortran or the operating system.
+.NH 1
+INTER-PROCEDURE INTERFACE
+.PP
+To be able to write C procedures that call or are called by Fortran procedures,
+it is necessary to know the conventions for procedure names,
+data representation,
+return values,
+and argument lists that the compiled code obeys.
+.NH 2
+Procedure Names
+.PP
+On
+.UX
+systems,
+the name of a common block or a Fortran procedure
+has an underscore appended to it by the compiler
+to distinguish it from a C procedure or external variable
+with the same user-assigned name.
+Fortran library procedure names have embedded underscores to avoid clashes
+with user-assigned subroutine names.
+.NH 2
+Data Representations
+.PP
+The following is a table of corresponding Fortran and C declarations:
+.KS
+.TS
+center;
+c c
+l l.
+Fortran        C
+.sp .5
+integer\(**2 x short int x;
+integer x      long int x;
+logical x      long int x;
+real x float x;
+double precision x     double x;
+complex x      struct { float r, i; } x;
+double complex x       struct { double dr, di; } x;
+character\(**6 x       char x[6];
+.TE
+.KE
+(By the rules of Fortran,
+.B integer,
+.B logical,
+and
+.B real
+data occupy the same amount of memory).
+.NH 2
+Return Values
+.PP
+A function of type
+.B integer,
+.B logical,
+.B real,
+or
+.B "double precision"
+declared as a C function that returns the corresponding type.
+A
+.B complex
+or
+.B "double complex"
+function is equivalent to a C routine
+with an additional
+initial argument that points to the place where the return value is to be stored.
+Thus,
+.DS
+complex function f( . . . )
+.DE
+is equivalent to
+.DS
+f_(temp, . . .)
+struct { float r, i; } \(**temp;
+ . . .
+.DE
+.DE
+A character-valued function is equivalent to a C routine with
+two extra initial arguments:
+a data address and a length.
+Thus,
+.DS
+character\(**15 function g( . . . )
+.DE
+is equivalent to
+.DS
+g_(result, length, . . .)
+char result[ ];
+long int length;
+ . . .
+.DE
+and could be invoked in C by
+.DS
+char chars[15];
+ . . .
+g_(chars, 15L, . . . );
+.DE
+Subroutines are invoked as if they were \fBinteger\fR-valued functions
+whose value specifies which alternate return to use.
+Alternate return arguments (statement labels) are not passed to the function,
+but are used to do an indexed branch in the calling procedure.
+(If the subroutine has no entry points with alternate return arguments,
+the returned value is undefined.)
+The statement
+.DS
+call nret(\(**1, \(**2, \(**3)
+.DE
+is treated exactly as if it were the computed
+.B goto
+.DS
+goto (1, 2, 3),  nret( )
+.DE
+.NH 2
+Argument Lists
+.PP
+All Fortran arguments are passed by address.
+In addition,
+for every argument that is of type character or
+that is a dummy procedure,
+an argument giving the length of the value is passed.
+(The string lengths are
+.B "long int"
+quantities passed by value).
+The order of arguments is then:
+.DS
+Extra arguments for complex and character functions
+Address for each datum or function
+A \fBlong int\fR for each character or procedure argument
+.DE
+Thus, the call in
+.DS
+external f
+character\(**7 s
+integer b(3)
+ . . .
+call sam(f, b(2), s)
+.DE
+is equivalent to that in
+.DS
+int f();
+char s[7];
+long int b[3];
+ . . .
+sam_(f, &b[1], s, 0L, 7L);
+.DE
+Note that the first element of a C array always has subscript zero,
+but Fortran arrays begin at 1 by default.
+Fortran arrays are stored in column-major order, C arrays are stored in row-major order.
+.NH 1
+FILE FORMATS
+.NH 2
+Structure of Fortran Files
+.PP
+Fortran requires four kinds of external files:
+sequential formatted and unformatted,
+and direct formatted and unformatted.
+On
+.UX
+systems,
+these are all implemented as ordinary files
+which are assumed to have the proper
+internal structure.
+.PP
+Fortran I/O is based on ``records''.
+When a direct file is opened in a Fortran program,
+the record length of the records must be given,
+and this is used by the Fortran I/O system to
+make the file look as if it is made up of records
+of the given length.
+In the special case that the record length is given
+as 1,
+the files are not considered to be divided into records,
+but are treated as byte-addressable byte strings;
+that is,
+as ordinary
+.UX
+file system files.
+(A read or write request on such a file keeps consuming bytes until
+satisfied, rather than being restricted to a single record.)
+.PP
+The peculiar requirements on sequential unformatted files
+make it unlikely that they will ever be read or written by any means except Fortran I/O statements.
+Each record is preceded and followed by
+an integer containing the record's length in bytes.
+.PP
+The Fortran I/O system breaks sequential formatted files
+into records while reading by using each newline
+as a record separator.
+The result of reading off the end of a record is undefined according to the Standard.
+The I/O system is permissive and
+treats the record as being extended by blanks.
+On output,
+the I/O system will write a newline at the end of each
+record.
+It is also possible for programs to write newlines
+for themselves.
+This is an error,
+but the only effect will be that the single record
+the user thought he wrote will be treated as
+more than one record when being read or
+backspaced over.
+.NH 2
+Portability Considerations
+.PP
+The Fortran I/O system uses only the facilities of the
+standard C I/O library,
+a widely available and fairly portable package,
+with the following two nonstandard features:
+The I/O system needs to know whether a file
+can be used for direct I/O,
+and whether or not it is possible to backspace.
+Both of these facilities are implemented
+using the
+.B fseek
+routine,
+so there is a routine
+.B canseek
+which determines if
+.B fseek
+will have the desired effect.
+Also, the
+.B inquire
+statement provides the user
+with the ability to find out if two files are the
+same,
+and to get the name of an already opened file
+in a form which would enable the program to reopen
+it.
+(The
+.UX
+operating system implementation attempts to determine the full pathname.)
+Therefore there are two routines which
+depend on facilities of the operating system
+to provide these two services.
+In any case,
+the I/O system
+runs on the PDP-11, VAX-11/780, and Interdata 8/32
+.UX
+systems.
+.NH 2
+Pre-Connected Files and File Positions
+.PP
+Units 5, 6, and 0 are preconnected when the program starts.
+Unit 5 is connected to the standard input,
+unit 6 is connected to the standard output,
+and unit 0 is connected to the standard error unit.
+All are connected for sequential formatted I/O.
+.PP
+All the other units are also preconnected when execution
+begins.
+Unit
+.I n
+is connected to a file named \fBfort.\fIn\fR.
+These files need not exist,
+nor will they be created unless their units are used
+without first executing an
+.B open.
+The default connection is for sequential formatted I/O.
+.PP
+The Standard does not specify where a file which has been explicitly \fBopen\fRed
+for sequential I/O is initially positioned.
+In fact,
+the I/O system attempts to position the file at the end,
+so a
+.B write
+will append to the file and a
+.B read
+will result in an end-of-file indication.
+To position a file to its beginning,
+use a
+.B rewind
+statement.
+The preconnected units
+0, 5, and 6 are positioned as they come
+from the program's parent process.
+.SG
+.SH
+REFERENCES
+.LP
+.IP 1.
+\fISigplan Notices \fB11\fR, No.3 (1976),
+as amended in X3J3 internal documents through ``/90.1''.
+.IP 2.
+\fIUSA Standard FORTRAN, USAS X3.9-1966\fR,
+New York: United States of America Standards Institute, March 7, 1966.
+Clarified in
+\fIComm. ACM \fB12,\fR 289 (1969)
+and
+\fIComm. ACM \fB14, \fR 628 (1971).
+.IP 3.
+B. W. Kernighan and D. M. Ritchie,
+.I
+The C Programming Language,
+.R
+Englewood Cliffs: Prentice-Hall (1978).
+.IP 4.
+D. M. Ritchie, private communication.
+.IP 5.
+S. C. Johnson,
+``A Portable Compiler: Theory and Practice'',
+Proc. 5th ACM Symp. on Principles of Programming Languages
+(January 1978).
+.IP 6.
+S. I. Feldman,
+``An Informal Description of EFL'',
+internal memorandum.
+.IP 7.
+B. W. Kernighan,
+``RATFOR \(em A Preprocessor for a Rational Fortran'',
+.I
+Bell Laboratories Computing Science Technical Report #55,
+.R
+(January 1977).
+.IP 8.
+D. M. Ritchie, private communication.
+.bp
+.SH
+APPENDIX.  Differences Between Fortran 66 and Fortran 77
+.PP
+The following is a very brief description of the differences
+between the 1966 [2] and the 1977 [1] Standard languages.
+We assume that the reader is familiar with Fortran 66.
+We do not pretend to be complete, precise,
+or unbiased,
+but plan to describe what we feel are the most important aspects of the new language.
+At present the only current information on the 1977 Standard is in publications of the X3J3 Subcommittee
+of the
+American National Standards Institute.
+The following information is from the ``/92'' document.
+This draft Standard is written in English rather than a meta-language, but it is forbidding
+and legalistic.
+No tutorials or textbooks are available yet.
+.NH 0
+Features Deleted from Fortran 66
+.NH 2
+Hollerith
+.IP
+All notions of ``Hollerith''
+(\fIn\|\fBh\fR)
+as data
+have been officially removed, although our compiler, like almost all in the foreseeable future,
+will continue to support this archaism.
+.NH 2
+Extended Range
+.IP
+In Fortran 66, under a set of very restrictive and rarely-understood conditions, it is permissible
+to jump out of the range of a
+.B do
+loop, then jump back into it.
+Extended range has been removed in the Fortran 77 language.
+The restrictions are so special, and the implementation of extended range is so unreliable in many compilers,
+that this change really counts as no loss.
+.NH 1
+Program Form
+.NH 2
+Blank Lines
+.IP
+Completely blank lines are now legal comment lines.
+.NH 2
+Program and Block Data Statements
+.IP
+A main program may now begin with a statement that gives that program an external name:
+.DS
+program work
+.DE
+Block data procedures may also have names.
+.DS
+block data stuff
+.DE
+There is now a rule that only
+.I one
+unnamed
+block data procedure may appear in a program.
+(This rule is not enforced by our system.)
+The Standard does not specify the effect of the program and block data names,
+but they are clearly intended to aid conventional loaders.
+.NH 2
+ENTRY Statement
+.IP
+Multiple entry points are now legal.
+Subroutine and function subprograms may have additional entry points,
+declared by an
+.B entry
+statement with an optional argument list.
+.DS
+entry extra(a, b, c)
+.DE
+Execution begins at the first statement following the
+.B entry
+line.
+All variable declarations must precede all executable statements in the procedure.
+If the procedure begins with a
+.B subroutine
+statement,
+all entry points are subroutine names.
+If it begins with a
+.B function
+statement, each entry is a function entry point,
+with type determined by the type declared for the entry name.
+If any entry is a character-valued function,
+then all entries must be.
+In a function, an entry name of the same type as that where control entered
+must be assigned a value.
+Arguments do not retain their values between calls.
+(The ancient trick of calling one entry point with a large number of arguments
+to cause the procedure to ``remember'' the locations of those arguments,
+then invoking an entry with just a few arguments for later calculation,
+is still illegal.
+Furthermore, the trick doesn't work in our implementation,
+since arguments are not kept in static storage.)
+.NH 2
+DO Loops
+.IP
+.B do
+variables and range parameters may now be of integer, real, or double precision types.
+(The use of floating point
+.B do
+variables is very dangerous
+because of the possibility of unexpected roundoff,
+and we strongly recommend against their use).
+The action of the
+.B do
+statement is now defined for all values of the
+.B do
+parameters.
+The statement
+.DS
+do 10 i = l, u, d
+.DE
+performs
+$ max (0^,^ left floor ( u - l ) / d^ right floor )$
+iterations.
+The
+.B do
+variable has a predictable value when exiting a loop:
+the value at the time a
+.B goto
+or
+.B return
+terminates the loop;
+otherwise
+the value that failed the limit test.
+.NH 2
+Alternate Returns
+.IP
+In a
+.B subroutine
+or subroutine
+.B entry
+statement,
+some of the arguments may be noted by an asterisk, as in
+.DS
+subroutine s(a, \(**, b, \(**)
+.DE
+The meaning of the ``alternate returns'' is described in section 5.2 of the Appendix.
+.NH 1
+Declarations
+.NH 2
+CHARACTER Data Type
+.IP
+One of the biggest improvements to the language is the addition of a character-string data type.
+Local and
+common character variables must have a length denoted by a constant expression:
+.DS
+character\(**17 a, b(3,4)
+character\(**(6+3) c
+.DE
+If the length is omitted entirely, it is assumed equal to 1.
+A character string argument may have a constant length,
+or the length may be declared to be the same as that of the corresponding actual argument at run time
+by a statement like
+.DS
+character\(**(\(**) a
+.DE
+(There is an intrinsic function
+.B len
+that returns the actual length of a character string).
+Character arrays and common blocks containing character variables must be packed:
+in an array of character variables, the first character of one element must follow the last character of
+the preceding element, without holes.
+.NH 2
+IMPLICIT Statement
+.IP
+The traditional implied declaration rules still hold:
+a variable whose name begins with
+\fBi, j, k, l, m,\fR or \fBn\fR is of type
+.B integer,
+other variables are of type
+.B real,
+unless otherwise declared.
+This general rule may be overridden with an
+.B implicit
+statement:
+.DS
+implicit real(a-c,g), complex(w-z), character\(**(17) (s)
+.DE
+declares that variables whose name begins with an
+\fBa ,b, c,\fR
+or
+\fBg\fR
+are
+.B real,
+those beginning with
+\fBw, x, y,\fR
+or
+\fBz\fR
+are assumed
+.B complex,
+and so on.
+It is still poor practice to depend on implicit typing, but this statement is an industry standard.
+.NH 2
+PARAMETER Statement
+.IP
+It is now possible to give a constant a symbolic name, as in
+.DS
+parameter (x=17, y=x/3, pi=3.14159d0, s=\(fmhello\(fm)
+.DE
+The type of each parameter name is governed by the same implicit and explicit rules as for a variable.
+The right side of each equal sign must be a constant expression
+(an expression made up of constants, operators, and already defined parameters).
+.NH 2
+Array Declarations
+.IP
+Arrays may now have as many as seven dimensions.
+(Only three were permitted in 1966).
+The lower bound of each dimension may be declared
+to be other than 1 by
+using a colon.
+Furthermore, an adjustable array bound may be an integer expression involving constants,
+arguments, and variables in
+.B common.
+.DS
+real a(\(mi5:3, 7, m:n), b(n+1:2\(**n)
+.DE
+The upper bound on the last dimension of an array argument may be denoted by an asterisk
+to indicate that the upper bound is not specified:
+.DS
+integer a(5, \(**),  b(\(**), c(0:1, \(mi2:\(**)
+.DE
+.NH 2
+SAVE Statement
+.IP
+A poorly known rule of Fortran 66 is that local variables in a procedure do not necessarily retain their values between
+invocations of that procedure.
+At any instant in the execution of a program,
+if a common block is declared neither in the currently executing procedure
+nor in any of the procedures in the chain of callers,
+all of the variables in that common block also become undefined.
+(The only exceptions are variables that have been defined in a
+.B data
+statement and never changed).
+These rules permit overlay and stack implementations for the affected variables.
+Fortran 77 permits one to specify that certain variables and common blocks are to retain their
+values between invocations.
+The declaration
+.DS
+save a, /b/, c
+.DE
+leaves the values of the variables
+.B a
+and
+.B c
+and all of the contents of common block
+.B b
+unaffected by a return.
+The simple declaration
+.DS
+save
+.DE
+has this effect on all variables and common blocks in the procedure.
+A common block must be \fBsave\fRd in every procedure in which it is declared if the desired effect is to occur.
+.NH 2
+INTRINSIC Statement
+.IP
+All of the functions specified in the Standard are in a single category,
+``intrinsic functions'', rather than being divided into ``intrinsic'' and ``basic external'' functions.
+If an intrinsic function is to be passed to another procedure, it must be declared
+.B intrinsic.
+Declaring it
+.B external
+(as in Fortran 66) causes a function other than the built-in one to be passed.
+.NH 1
+Expressions
+.NH 2
+Character Constants
+.IP
+Character string constants are marked by strings surrounded by apostrophes.
+If an apostrophe is to be included in a constant, it is repeated:
+.DS
+ \(fmabc\(fm
+ \(fmain\(fm\(fmt\(fm
+.DE
+There are no null (zero-length) character strings in Fortran 77.
+Our compiler has two different quotation marks, `` \(fm ''' and `` " ''.
+(See Section 2.9 in the main text.)
+.NH 2
+Concatenation
+.IP
+One new operator has been added, character string concatenation, marked by a double slash
+(``//'').
+The result of a concatenation is the string containing the characters of the left operand followed by the characters of
+the right operand.
+The strings
+.DS
+ \(fmab\(fm // \(fmcd\(fm
+ \(fmabcd\(fm
+.DE
+are equal.
+The strings being concatenated must be of constant length in all concatenations
+that are not the right sides of assignments.
+(The only concatenation expressions in which a
+character string declared adjustable with a ``\(**(\(**)'' modifier
+or a substring denotation with nonconstant position values may appear
+are the right sides of assignments).
+.NH 2
+Character String Assignment
+.IP
+The left and right sides of a character assignment may not share storage.
+(The assumed implementation of character assignment is to copy characters from the right to the left side.)
+If the left side is longer than the right, it is padded with blanks.
+If the left side is shorter than the right, trailing characters are discarded.
+.NH 2
+Substrings
+.IP
+It is possible to extract a substring of a character variable or character array element, using the colon notation:
+.DS
+a(i,\|j) (m:n)
+.DE
+is the string of $(n-m+1)$ characters beginning at the
+$m sup th$ character of the character array element $a sub ij$.
+Results are undefined unless $m<=n$.
+Substrings may be used on the left sides of assignments and as procedure actual arguments.
+.NH 2
+Exponentiation
+.IP
+It is now permissible to raise real quantities to complex powers,
+or complex quantities to real or complex powers.
+(The principal part of the logarithm is used).
+Also, multiple exponentiation is now defined:
+.DS
+a\(**\(**b\(**\(**c = a \(**\(** (b\(**\(**c)
+.DE
+.NH 2
+Relaxation of Restrictions
+.IP
+Mixed mode expressions are now permitted.
+(For instance,
+it is permissible to combine integer and complex quantities in an expression.)
+.IP
+Constant expressions are permitted where a constant is allowed,
+except in
+.B data
+statements.
+(A constant expression is made up of explicit constants and
+\fBparameter\fRs
+and the Fortran operators,
+except for exponentiation to a floating-point power).
+An adjustable dimension may now be an integer expression involving constants,
+arguments, and variables in
+B common..
+.IP
+Subscripts may now be general integer expressions;
+the old
+$c v +- c'$
+rules have been removed.
+.B do
+loop bounds may be general integer, real, or double precision expressions.
+Computed
+.B goto
+expressions and I/O unit numbers may be general integer expressions.
+.NH 1
+Executable Statements
+.NH 2
+IF-THEN-ELSE
+.IP
+At last, the
+if-then-else
+branching structure has been added to Fortran.
+It is called a ``Block If''.
+A Block If begins with a statement of the form
+.DS
+if ( . . . ) then
+.DE
+and ends with an
+.DS
+end if
+.DE
+statement.
+Two other new statements may appear in a Block If.
+There may be several
+.DS
+else if(. . .) then
+.DE
+statements,
+followed by at most one
+.DS
+else
+.DE
+statement.
+If the logical expression in the Block If statement is true, the statements following it up to the
+next
+.B elseif,
+.B else,
+or
+.B endif
+are executed.
+Otherwise, the next
+.B elseif
+statement in the group is executed.
+If none of the
+.B elseif
+conditions are true, control passes to the statements following the
+.B else
+statement, if any.
+(The
+.B else
+must follow all \fBelseif\fRs in a Block If.
+Of course, there may be Block Ifs embedded inside of other Block If structures).
+A
+case
+construct may be rendered
+.DS
+if (s .eq. \(fmab\(fm) then
+ . . .
+else if (s .eq. \(fmcd\(fm) then
+ . . .
+else
+ . . .
+end if
+.DE
+.NH 2
+Alternate Returns
+.IP
+Some of the arguments of a subroutine call may be statement labels preceded by an asterisk, as in
+.DS
+call joe(j, \(**10, m, \(**2)
+.DE
+A
+.B return
+statement may have an integer expression, such as
+.DS
+return k
+.DE
+If the entry point has
+$n$
+alternate return (asterisk) arguments
+and if $1<=k<=n$, the return is followed by a branch to the corresponding statement label;
+otherwise the usual return to the statement following the
+.B call
+is executed.
+.NH 1
+Input/Output
+.NH 2
+Format Variables
+.IP
+A format may be the value of a character expression (constant or otherwise),
+or be stored in a character array, as in
+.DS
+write(6, \(fm(i5)\(fm) x
+.DE
+.NH 2
+END=, ERR=, and IOSTAT= Clauses
+.IP
+A
+.B read
+or
+.B write
+statement may contain
+.B end=,
+.B err=,
+and
+.B iostat=
+clauses, as in
+.DS
+write(6, 101, err=20, iostat=a(4))
+read(5, 101, err=20, end=30, iostat=x)
+.DE
+Here 5 and 6 are the
+.I units
+on which the I/O is done,
+101 is the statement number of the associated format,
+20 and 30 are statement numbers,
+and
+.B a
+and
+.B x
+are integers.
+If an error occurs during I/O,
+control returns to the program at statement 20.
+If the end of the file is reached,
+control returns to the program at statement 30.
+In any case, the variable referred to in
+the
+.B iostat=
+clause is given a value when
+the I/O statement finishes.
+(Yes, the value is assigned to the name on the right side of the equal sign.)
+This value is zero if all went well,
+negative for end of file,
+and some positive value for errors.
+.NH 2
+Formatted I/O
+.NH 3
+Character Constants
+.IP
+Character constants in formats are copied literally to the output.
+Character constants cannot be read into.
+.DS
+write(6,\(fm(i2,\(fm\(fm isn\(fm\(fm\(fm\(fmt \(fm\(fm,i1)\(fm) 7, 4
+.DE
+produces
+.DS
+ 7 isn\(fmt 4
+.DE
+Here the format is the character constant
+.DS
+(i2,\(fm isn\(fm\(fmt \(fm,i1)
+.DE
+and the character constant
+.DS
+ isn\(fmt
+.DE
+is copied into the output.
+.NH 3
+Positional Editing Codes
+.IP
+.B t,
+.B tl,
+.B tr,
+and
+.B x
+codes
+control where the
+next character is in the record.
+\fBtr\fIn\fR
+or
+\fIn\fBx\fR
+specifies that the next character is
+$n$ to the right of the current position.
+\fBtl\fIn\fR
+specifies that the next character is
+$n$ to the left of the current position,
+allowing parts of the record to be reconsidered.
+\fBt\fIn\fR
+says that the next character is to be character
+number $n$ in the record.
+(See section 3.4 in the main text.)
+.NH 3
+Colon
+.IP
+A colon in the format terminates the I/O operation
+if there are no more data items in the I/O list,
+otherwise it has no effect.
+In the fragment
+.DS
+x=\(fm("hello", :, " there", i4)\(fm
+write(6, x) 12
+write(6, x)
+.DE
+the first
+.B write
+statement prints
+\fBhello there 12\fR,
+while the second only prints
+\fBhello\fR.
+.NH 3
+Optional Plus Signs
+.IP
+According to the Standard,
+each implementation has the option of putting
+plus signs in front of non-negative
+numeric output.
+The
+.B sp
+format code may be used to make the optional plus
+signs actually appear for all subsequent items
+while the format is active.
+The
+.B ss
+format code guarantees that the I/O system will not
+insert the optional plus signs,
+and the
+.B s
+format code restores the default behavior of
+the I/O system.
+(Since we never put out optional plus signs,
+.B ss
+and
+.B s
+codes have the same effect in our implementation.)
+.NH 3
+Blanks on Input
+.IP
+Blanks in numeric input fields,
+other than leading blanks
+will be ignored following a
+.B bn
+code in a format
+statement,
+and will be treated as zeros following a
+.B bz
+code in a format statement.
+The default for a unit may be changed by using
+the
+.B open
+statement.
+(Blanks are ignored by default.)
+.NH 3
+Unrepresentable Values
+.IP
+The Standard requires that if a numeric item
+cannot be represented in the form required by a format code,
+the output field must be filled with asterisks.
+(We think this should have been an option.)
+.NH 3
+Iw.m
+.IP
+There is a new integer output code,
+\fBi\fIw.m.\fR
+It is the same as
+\fBi\fIw\fR,
+except that there will be at least $m$
+digits in the output field,
+including,
+if necessary,
+leading zeros.
+The case \fBi\fR$w.0$ is special,
+in that if the value being printed is 0,
+the output field is
+entirely blank.
+\fBi\fIw\fB.1\fR
+is the same as
+\fBi\fIw\fR.
+.NH 3
+Floating Point
+.IP
+On input, exponents may start with the letter
+\fBE, D, e, \fRor \fBd.\fR
+All have the same meaning.
+On output we always use \fBe\fR.
+The
+.B e
+and
+.B d
+format codes also have identical meanings.
+A leading zero before the decimal point in
+.B e
+output
+without a scale factor is optional with the
+implementation.
+(We do not print it.)
+There is a
+\fBg\fIw.d\fR
+format code which is the same as
+\fBe\fIw.d\fR
+and
+\fBf\fIw.d\fR
+on input,
+but which chooses
+.B f
+or
+.B e
+formats for output depending.
+on the size of the number and of $d$.
+.NH 3
+``A'' Format Code
+.IP
+A codes are used for character values.
+\fBa\fIw\fR
+use a field width of $w$,
+while a plain
+.B a
+uses the length of the character item.
+.NH 2
+Standard Units
+.IP
+There are default formatted input and output units.
+The statement
+.DS
+read 10, a, b
+.DE
+reads from the standard unit using format statement 10.
+The default unit may be explicitly specified by an asterisk, as in
+.DS
+read(\(**, 10) a,b
+.DE
+Similarly, the standard output units is specified by a
+.B print
+statement or an asterisk unit:
+.DS
+print 10
+write(\(**, 10)
+.DE
+.NH 2
+List-Directed Formatting
+.IP
+List-directed I/O is a
+kind of free form input for sequential I/O.
+It is invoked by using an asterisk as the
+format identifier, as in
+.DS
+read(6, \(**) a,b,c
+.DE
+.IP
+On input,
+values are separated by strings of blanks
+and possibly a comma.
+Values,
+except for character strings,
+cannot contain blanks.
+End of record counts as a blank,
+except in character strings,
+where it is ignored.
+Complex constants are given as two real constants
+separated by a comma and enclosed in parentheses.
+A null input field,
+such as between two consecutive commas,
+means the corresponding variable in the
+I/O list is not changed.
+Values may be preceded by repetition counts,
+as in
+.DS
+4\(**(3.,2.)  2\(**, 4\(**\(fmhello\(fm
+.DE
+which stands for 4 complex constants, 2 null values,
+and 4 string constants.
+.IP
+For output, suitable formats are chosen for
+each item.
+The values of character strings are printed;
+they are not enclosed in quotes, so they cannot be read back
+using list-directed input.
+.NH 2
+Direct I/O
+.IP
+A file connected for direct access consists of
+a set of equal-sized records each of which is
+uniquely identified by a positive integer.
+The records may be written or read in any order,
+using direct access I/O statements.
+.IP
+Direct access
+.B read
+and
+.B write
+statements
+have an extra argument,
+.B rec=,
+which gives the record number to be read or written.
+.DS
+read(2, rec=13, err=20) (a(i), i=1, 203)
+.DE
+reads the thirteenth record into the array
+.B a.
+.IP
+The size of the records must be given by an
+.B open
+statement
+(see below).
+Direct access files may be connected for either formatted
+or unformatted I/O.
+.NH 2
+Internal Files
+.IP
+Internal files are character string objects,
+such as variables or substrings,
+or arrays of type character.
+In the former cases there is only a single record
+in the file,
+in the latter case each array element is a record.
+The Standard includes only sequential
+formatted I/O on internal files.
+(I/O is not a very precise term to use here,
+but internal files are dealt with using
+.B read
+and
+.B write).
+There is no list-directed I/O on internal files.
+Internal files are used by giving the name of the
+character object in place of the unit number, as in
+.DS
+character\(**80 x
+read(5,"(a)") x
+read(x,"(i3,i4)") n1,n2
+.DE
+which reads a card image into
+.B x
+and then reads
+two integers from the front of it.
+A sequential
+.B read
+or
+.B write
+always starts at the beginning
+of an internal file.
+.IP
+(We also support a compatible extension, direct I/O on internal files.
+This is like direct I/O on external files,
+except that the number of records in the file cannot be
+changed.)
+.NH 2
+OPEN, CLOSE, and INQUIRE Statements
+.IP
+These statements are used to connect and disconnect
+units and files,
+and to gather information about units and files.
+.NH 3
+OPEN
+.IP
+The
+.B open
+statement is used to connect a file with a
+unit,
+or to alter some properties of the connection.
+The following is a minimal example.
+.DS
+open(1, file=\(fmfort.junk\(fm)
+.DE
+.B open
+takes a variety of arguments with meanings described below.
+.RS
+.      \" macros here
+.de HP
+.RT
+.if !\\(IP .nr IP +1
+.sp \\n(PDu
+.ne 3v
+.in +\\n(PIu
+.ti -\\n(PIu
+\fB\\$1\fR\ \c
+..
+.de P1
+.KS
+.nf
+.in +.3i
+.ta .3i .6i .9i 1.2i 1.5i 1.8i
+.sp
+..
+.de P2
+.fi
+.in -.3i
+.sp
+.KE
+..
+.de TH
+.RT
+.sp \\n(PDu
+.ne 3v
+\fB\\$1\\$2\\$3\\$4\\$5\\$6\fR\ \c
+..
+.      \" end of macros
+.HP unit=
+a small non-negative integer which is the unit to
+which the file is to be connected.
+We allow,
+at the time of this writing,
+0 through 9.
+If this parameter is the first one in the
+.B open
+statement,
+the
+.B unit=
+can be omitted.
+.HP iostat=
+is the same as in
+.B read
+or
+.B write.
+.HP err=
+is the same as in
+.B read
+or
+.B write.
+.HP file=
+a character expression,
+which when stripped of trailing blanks,
+is the name of the file to be connected to the unit.
+The filename should not be given if the
+.B status=scratch.
+.HP status=
+one of
+.B old,
+.B new,
+.B scratch,
+or
+.B unknown.
+If this parameter is not given,
+.B unknown
+is assumed.
+If
+.B scratch
+is given,
+a temporary file will be created.
+Temporary files are destroyed at the end of execution.
+If
+.B new
+is given,
+the file will be created if it doesn't exist,
+or truncated if it does.
+The meaning of
+.B unknown
+is processor dependent;
+our system treats it as synonymous with
+.B old.
+.HP access=
+.B sequential
+or
+.B direct,
+depending on whether the file is
+to be opened for sequential or direct I/O.
+.HP form=
+.B formatted
+or
+.B unformatted.
+.HP recl=
+a positive integer specifying the record length of
+the direct access file being opened.
+We measure all record lengths in bytes.
+On
+.UX
+systems a record length of 1 has the special meaning explained
+in section 5.1 of the text.
+.HP blank=
+.B null
+or
+.B zero.
+This parameter has meaning only for formatted I/O.
+The default value is
+.B null.
+.B zero
+means that blanks,
+other than leading blanks,
+in numeric input fields are to be treated as zeros.
+.RE
+.IP
+Opening a new file on a unit which is already connected
+has the effect of first closing the old file.
+.NH 3
+CLOSE
+.IP
+.B close
+severs the connection between a unit and a file.
+The unit number must be given.
+The optional parameters are
+.B iostat=
+and
+.B err=
+with
+their usual meanings,
+and
+.B status=
+either
+.B keep
+or
+.B delete.
+Scratch files cannot be kept,
+otherwise
+.B keep
+is the default.
+.B delete
+means the file will be removed.
+A simple example is
+.DS
+close(3, err=17)
+.DE
+.NH 3
+INQUIRE
+.IP
+The
+.B inquire
+statement gives information about
+a unit
+(``inquire by unit'')
+or a file (``inquire by file'').
+Simple examples are:
+.DS
+inquire(unit=3, namexx)
+inquire(file=\(fmjunk\(fm, number=n, exist=l)
+.DE
+.RS
+.HP file=
+a character variable specifies the file the
+.B inquire
+is about.
+Trailing blanks in the file name are ignored.
+.HP unit=
+an integer variable specifies the unit the
+.B inquire
+is about.
+Exactly one of
+.B file=
+or
+.B unit=
+must be used.
+.HP "iostat=, err="
+are as before.
+.HP exist=
+a logical variable.
+The logical variable is set to
+.B ".true."
+if the file or unit
+exists and is set to
+.B ".false."
+otherwise.
+.HP opened=
+a logical variable.
+The logical variable is set to
+.B ".true."
+if the file
+is connected to a unit or if the unit is connected
+to a file,
+and it is set to
+.B ".false."
+otherwise.
+.HP number=
+an integer variable to which is assigned the
+number of the unit connected to the file,
+if any.
+.HP named=
+a logical variable to which is assigned
+.B ".true."
+if
+the file has a name,
+or
+.B ".false."
+otherwise.
+.HP name=
+a character variable to which is assigned the name
+of the file (inquire by file) or the name of the
+file connected to the unit (inquire by unit).
+The name will be the full name of the file.
+.HP access=
+a character variable to which will be assigned
+the value
+.B \(fmsequential\(fm
+if the connection is for
+sequential I/O,
+.B \(fmdirect\(fm
+if the connection is for direct I/O.
+The value becomes undefined if there is no connection.
+.HP sequential=
+a character variable to which is assigned the
+value
+.B \(fmyes\(fm
+if the file could be connected for
+sequential I/O,
+.B \(fmno\(fm
+if the file could not be connected for sequential I/O,
+and
+.B \(fmunknown\(fm
+if we can't tell.
+.HP direct=
+a character variable to which is assigned the value
+.B \(fmyes\(fm
+if the file could be connected for direct I/O,
+.B\(fmno\(fm
+if the file could not be connected for direct
+I/O,
+and
+.B \(fmunknown\(fm
+if we can't tell.
+.HP form=
+a character variable to which is assigned the value
+.B \(fmformatted\(fm
+if the file is connected for formatted I/O,
+or
+.B \(fmunformatted\(fm
+if the file is connected for unformatted
+I/O.
+.HP formatted=
+a character variable to which is assigned the value
+.B \(fmyes\(fm
+if the file could be connected for formatted I/O,
+.B \(fmno\(fm
+if the file could not be connected for formatted I/O,
+and
+.B \(fmunknown\(fm
+if we can't tell.
+.HP unformatted=
+a character variable to which is assigned the value
+.B \(fmyes\(fm
+if
+the file could be connected for unformatted I/O,
+.B \(fmno\(fm
+if the file could not be connected for unformatted I/O,
+and
+.B \(fmunknown\(fm
+if we can't tell.
+.HP recl=
+an integer variable to which is assigned the record length
+of the records in the file if the file is connected
+for direct access.
+.HP nextrec=
+an integer variable to which is assigned one more
+than the number of the the last record read from a file connected
+for direct access.
+.HP blank=
+a character variable to which is assigned the value
+.B \(fmnull\(fm
+if null blank control is in effect for the file
+connected for formatted I/O,
+.B \(fmzero\(fm
+if blanks are being converted to zeros and
+the file is connected for formatted I/O.
+.RE
+.PP
+.I "The gentle reader"
+will remember that the people who wrote the standard
+probably weren't thinking of his needs.
+Here is an example.
+The declarations are omitted.
+.DS
+open(1, file="/dev/console")
+.DE
+On a
+.UX
+system this statement opens the console for formatted sequential
+I/O.
+An
+.B inquire
+statement for either unit 1 or file "/dev/console"
+would reveal that the file exists, is connected to unit 1,
+has a name, namely "/dev/console",
+is opened for sequential I/O,
+could be connected for sequential I/O,
+could not be connected for direct I/O (can't seek),
+is connected for formatted I/O,
+could be connected for formatted I/O,
+could not be connected for unformatted I/O
+(can't seek),
+has neither a record length nor a next record number,
+and is ignoring blanks in numeric fields.
+.PP
+In the
+.UX
+system environment,
+the only way to discover what permissions you have
+for a file is to open it and try to read and write it.
+The
+.B err=
+parameter will return system error numbers.
+The
+.B inquire
+statement does not give a way of determining permissions.
diff --git a/doc/7thEdMan/vol2/implement b/doc/7thEdMan/vol2/implement
new file mode 100644 (file)
index 0000000..e7f128e
--- /dev/null
@@ -0,0 +1,1231 @@
+.de P1
+.DS
+..
+.de P2
+.DE
+..
+.de UL
+.lg 0
+.if n .ul
+\%\&\\$3\f3\\$1\fR\&\\$2
+.lg
+..
+.de UC
+\&\\$3\s-1\\$1\\s0\&\\$2
+..
+.de IT
+.lg 0
+.if n .ul
+\%\&\\$3\f2\\$1\fR\&\\$2
+.lg
+..
+.de SP
+.sp \\$1
+..
+.hw device
+.TL
+UNIX Implementation
+.AU "MH 2C-523" 2394
+K. Thompson
+.AI
+.MH
+.AB
+This paper describes in high-level terms the
+implementation of the resident
+.UX
+kernel.
+This discussion is broken into three parts.
+The first part describes
+how the
+.UX
+system views processes, users, and programs.
+The second part describes the I/O system.
+The last part describes the
+.UX
+file system.
+.AE
+.NH
+INTRODUCTION
+.PP
+The
+.UX
+kernel consists of about 10,000
+lines of C code and about 1,000 lines of assembly code.
+The assembly code can be further broken down into
+200 lines included for
+the sake of efficiency
+(they could have been written in C)
+and 800 lines to perform hardware
+functions not possible in C.
+.PP
+This code represents 5 to 10 percent of what has
+been lumped into the broad expression
+``the
+.UX
+operating system.''
+The kernel is the only
+.UX
+code that
+cannot be substituted by a user to his
+own liking.
+For this reason,
+the kernel should make as few real
+decisions as possible.
+This does not mean to allow the user
+a million options to do the same thing.
+Rather, it means to allow only one way to
+do one thing,
+but have that way be the least-common divisor
+of all the options that might have been provided.
+.PP
+What is or is not implemented in the kernel
+represents both a great responsibility and a great power.
+It is a soap-box platform on
+``the way things should be done.''
+Even so, if
+``the way'' is too radical,
+no one will follow it.
+Every important decision was weighed
+carefully.
+Throughout,
+simplicity has been substituted for efficiency.
+Complex algorithms are used only if
+their complexity can be localized.
+.NH
+PROCESS CONTROL
+.PP
+In the
+.UX
+system,
+a user executes programs in an
+environment called a user process.
+When a system function is required,
+the user process calls the system
+as a subroutine.
+At some point in this call,
+there is a distinct switch of environments.
+After this,
+the process is said to be a system process.
+In the normal definition of processes,
+the user and system processes are different
+phases of the same process
+(they never execute simultaneously).
+For protection,
+each system process has its own stack.
+.PP
+The user process may execute
+from a read-only text segment,
+which is shared by all processes
+executing the same code.
+There is no
+.IT functional
+benefit
+from shared-text segments.
+An
+.IT efficiency
+benefit comes from the fact
+that there is no need to swap read-only
+segments out because the original
+copy on secondary memory is still current.
+This is a great benefit to interactive
+programs that tend to be swapped while
+waiting for terminal input.
+Furthermore,
+if two processes are
+executing
+simultaneously
+from the same copy of a read-only segment,
+only one copy needs to reside in
+primary memory.
+This is a secondary effect,
+because
+simultaneous execution of a program
+is not common.
+It is ironic that this effect,
+which reduces the use of primary memory,
+only comes into play when there is
+an overabundance of primary memory,
+that is,
+when there is enough memory
+to keep waiting processes loaded.
+.PP
+All current read-only text segments in the
+system are maintained from the
+.IT "text table" .
+A text table entry holds the location of the
+text segment on secondary memory.
+If the segment is loaded,
+that table also holds the primary memory location
+and the count of the number of processes
+sharing this entry.
+When this count is reduced to zero,
+the entry is freed along with any
+primary and secondary memory holding the segment.
+When a process first executes a shared-text segment,
+a text table entry is allocated and the
+segment is loaded onto secondary memory.
+If a second process executes a text segment
+that is already allocated,
+the entry reference count is simply incremented.
+.PP
+A user process has some strictly private
+read-write data
+contained in its
+data segment.
+As far as possible,
+the system does not use the user's
+data segment to hold system data.
+In particular,
+there are no I/O buffers in the
+user address space.
+.PP
+The user data segment has two growing boundaries.
+One, increased automatically by the system
+as a result of memory faults,
+is used for a stack.
+The second boundary is only grown (or shrunk) by
+explicit requests.
+The contents of newly allocated primary memory
+is initialized to zero.
+.PP
+Also associated and swapped with
+a process is a small fixed-size
+system data segment.
+This segment contains all
+the data about the process
+that the system needs only when the
+process is active.
+Examples of the kind of data contained
+in the system data segment are:
+saved central processor registers,
+open file descriptors,
+accounting information,
+scratch data area,
+and the stack for the system phase
+of the process.
+The system data segment is not
+addressable from the user process
+and is therefore protected.
+.PP
+Last,
+there is a process table with
+one entry per process.
+This entry contains all the data
+needed by the system when the process
+is
+.IT not
+active.
+Examples are
+the process's name,
+the location of the other segments,
+and scheduling information.
+The process table entry is allocated
+when the process is created, and freed
+when the process terminates.
+This process entry is always directly
+addressable by the kernel.
+.PP
+Figure 1 shows the relationships
+between the various process control
+data.
+In a sense,
+the process table is the
+definition of all processes,
+because
+all the data associated with a process
+may be accessed
+starting from the process table entry.
+.KS
+.sp 2.44i
+.sp 2v
+.ce
+Fig. 1\(emProcess control data structure.
+.KE
+.NH 2
+Process creation and program execution
+.PP
+Processes are created by the system primitive
+.UL fork .
+The newly created process (child) is a copy of the original process (parent).
+There is no detectable sharing of primary memory between the two processes.
+(Of course,
+if the parent process was executing from a read-only
+text segment,
+the child will share the text segment.)
+Copies of all writable data segments
+are made for the child process.
+Files that were open before the
+.UL fork
+are
+truly shared after the
+.UL fork .
+The processes are informed as to their part in the
+relationship to
+allow them to select their own
+(usually non-identical)
+destiny.
+The parent may
+.UL wait
+for the termination of
+any of its children.
+.PP
+A process may
+.UL exec
+a file.
+This consists of exchanging the current text and data
+segments of the process for new text and data
+segments specified in the file.
+The old segments are lost.
+Doing an
+.UL exec
+does
+.IT not
+change processes;
+the process that did the
+.UL exec
+persists,
+but
+after the
+.UL exec
+it is executing a different program.
+Files that were open
+before the
+.UL exec
+remain open after the
+.UL exec .
+.PP
+If a program,
+say the first pass of a compiler,
+wishes to overlay itself with another program,
+say the second pass,
+then it simply
+.UL exec s
+the second program.
+This is analogous
+to a ``goto.''
+If a program wishes to regain control
+after
+.UL exec ing
+a second program,
+it should
+.UL fork
+a child process,
+have the child
+.UL exec
+the second program, and
+have the parent
+.UL wait
+for the child.
+This is analogous to a ``call.''
+Breaking up the call into a binding followed by
+a transfer is similar to the subroutine linkage in
+SL-5.
+.[
+griswold hanson sl5 overview
+.]
+.NH 2
+Swapping
+.PP
+The major data associated with a process
+(the user data segment,
+the system data segment, and
+the text segment)
+are swapped to and from secondary
+memory, as needed.
+The user data segment and the system data segment
+are kept in contiguous primary memory to reduce
+swapping latency.
+(When low-latency devices, such as bubbles,
+.UC CCD s,
+or scatter/gather devices,
+are used,
+this decision will have to be reconsidered.)
+Allocation of both primary
+and secondary memory is performed
+by the same simple first-fit algorithm.
+When a process grows,
+a new piece of primary memory is allocated.
+The contents of the old memory is copied to the new memory.
+The old memory is freed
+and the tables are updated.
+If there is not enough primary memory,
+secondary memory is allocated instead.
+The process is swapped out onto the
+secondary memory,
+ready to be swapped in with
+its new size.
+.PP
+One separate process in the kernel,
+the swapping process,
+simply swaps the other
+processes in and out of primary memory.
+It examines the
+process table looking for a process
+that is swapped out and is
+ready to run.
+It allocates primary memory for that
+process and
+reads its segments into
+primary memory, where that process competes for the
+central processor with other loaded processes.
+If no primary memory is available,
+the swapping process makes memory available
+by examining the process table for processes
+that can be swapped out.
+It selects a process to swap out,
+writes it to secondary memory,
+frees the primary memory,
+and then goes back to look for a process
+to swap in.
+.PP
+Thus there are two specific algorithms
+to the swapping process.
+Which of the possibly many processes that
+are swapped out is to be swapped in?
+This is decided by secondary storage residence
+time.
+The one with the longest time out is swapped in first.
+There is a slight penalty for larger processes.
+Which of the possibly many processes that
+are loaded is to be swapped out?
+Processes that are waiting for slow events
+(i.e., not currently running or waiting for
+disk I/O)
+are picked first,
+by age in primary memory,
+again with size penalties.
+The other processes are examined
+by the same age algorithm,
+but are not taken out unless they are
+at least of some age.
+This adds
+hysteresis to the swapping and
+prevents total thrashing.
+.PP
+These swapping algorithms are the
+most suspect in the system.
+With limited primary memory,
+these algorithms cause total swapping.
+This is not bad in itself, because
+the swapping does not impact the
+execution of the resident processes.
+However, if the swapping device must
+also be used for file storage,
+the swapping traffic severely
+impacts the file system traffic.
+It is exactly these small systems
+that tend to double usage of limited disk
+resources.
+.NH 2
+Synchronization and scheduling
+.PP
+Process synchronization is accomplished by having processes
+wait for events.
+Events are represented by arbitrary integers.
+By convention,
+events are chosen to be addresses of
+tables associated with those events.
+For example, a process that is waiting for
+any of its children to terminate will wait
+for an event that is the address of
+its own process table entry.
+When a process terminates,
+it signals the event represented by
+its parent's process table entry.
+Signaling an event on which no process
+is waiting has no effect.
+Similarly,
+signaling an event on which many processes
+are waiting will wake all of them up.
+This differs considerably from
+Dijkstra's P and V
+synchronization operations,
+.[
+dijkstra sequential processes 1968
+.]
+in that
+no memory is associated with events.
+Thus there need be no allocation of events
+prior to their use.
+Events exist simply by being used.
+.PP
+On the negative side,
+because there is no memory associated with events,
+no notion of ``how much''
+can be signaled via the event mechanism.
+For example,
+processes that want memory might
+wait on an event associated with
+memory allocation.
+When any amount of memory becomes available,
+the event would be signaled.
+All the competing processes would then wake
+up to fight over the new memory.
+(In reality,
+the swapping process is the only process
+that waits for primary memory to become available.)
+.PP
+If an event occurs
+between the time a process decides
+to wait for that event and the
+time that process enters the wait state,
+then
+the process will wait on an event that has
+already happened (and may never happen again).
+This race condition happens because there is no memory associated with
+the event to indicate that the event has occurred;
+the only action of an event is to change a set of processes
+from wait state to run state.
+This problem is relieved largely
+by the fact that process switching can
+only occur in the kernel by explicit calls
+to the event-wait mechanism.
+If the event in question is signaled by another
+process,
+then there is no problem.
+But if the event is signaled by a hardware
+interrupt,
+then special care must be taken.
+These synchronization races pose the biggest
+problem when
+.UX
+is adapted to multiple-processor configurations.
+.[
+hawley meyer multiprocessing unix
+.]
+.PP
+The event-wait code in the kernel
+is like a co-routine linkage.
+At any time,
+all but one of the processes has called event-wait.
+The remaining process is the one currently executing.
+When it calls event-wait,
+a process whose event has been signaled
+is selected and that process
+returns from its call to event-wait.
+.PP
+Which of the runable processes is to run next?
+Associated with each process is a priority.
+The priority of a system process is assigned by the code
+issuing the wait on an event.
+This is roughly equivalent to the response
+that one would expect on such an event.
+Disk events have high priority,
+teletype events are low,
+and time-of-day events are very low.
+(From observation,
+the difference in system process priorities
+has little or no performance impact.)
+All user-process priorities are lower than the
+lowest system priority.
+User-process priorities are assigned
+by an algorithm based on the
+recent ratio of the amount of compute time to real time consumed
+by the process.
+A process that has used a lot of
+compute time in the last real-time
+unit is assigned a low user priority.
+Because interactive processes are characterized
+by low ratios of compute to real time,
+interactive response is maintained without any
+special arrangements.
+.PP
+The scheduling algorithm simply picks
+the process with the highest priority,
+thus
+picking all system processes first and
+user processes second.
+The compute-to-real-time ratio is updated
+every second.
+Thus,
+all other things being equal,
+looping user processes will be
+scheduled round-robin with a
+1-second quantum.
+A high-priority process waking up will
+preempt a running, low-priority process.
+The scheduling algorithm has a very desirable
+negative feedback character.
+If a process uses its high priority
+to hog the computer,
+its priority will drop.
+At the same time, if a low-priority
+process is ignored for a long time,
+its priority will rise.
+.NH
+I/O SYSTEM
+.PP
+The I/O system
+is broken into two completely separate systems:
+the block I/O system and the character I/O system.
+In retrospect,
+the names should have been ``structured I/O''
+and ``unstructured I/O,'' respectively;
+while the term ``block I/O'' has some meaning,
+``character I/O'' is a complete misnomer.
+.PP
+Devices are characterized by a major device number,
+a minor device number, and
+a class (block or character).
+For each class,
+there is an array of entry points into the device drivers.
+The major device number is used to index the array
+when calling the code for a particular device driver.
+The minor device number is passed to the
+device driver as an argument.
+The minor number has no significance other
+than that attributed to it by the driver.
+Usually,
+the driver uses the minor number to access
+one of several identical physical devices.
+.PP
+The use of the array of entry points
+(configuration table)
+as the only connection between the
+system code and the device drivers is
+very important.
+Early versions of the system had a much
+less formal connection with the drivers,
+so that it was extremely hard to handcraft
+differently configured systems.
+Now it is possible to create new
+device drivers in an average of a few hours.
+The configuration table in most cases
+is created automatically by a program
+that reads the system's parts list.
+.NH 2
+Block I/O system
+.PP
+The model block I/O device consists
+of randomly addressed, secondary
+memory blocks of 512 bytes each.
+The blocks are uniformly addressed
+0, 1, .\|.\|. up to the size of the device.
+The block device driver has the job of
+emulating this model on a
+physical device.
+.PP
+The block I/O devices are accessed
+through a layer of buffering software.
+The system maintains a list of buffers
+(typically between 10 and 70)
+each assigned a device name and
+a device address.
+This buffer pool constitutes a data cache
+for the block devices.
+On a read request,
+the cache is searched for the desired block.
+If the block is found,
+the data are made available to the
+requester without any physical I/O.
+If the block is not in the cache,
+the least recently used block in the cache is renamed,
+the correct device driver is called to
+fill up the renamed buffer, and then the
+data are made available.
+Write requests are handled in an analogous manner.
+The correct buffer is found
+and relabeled if necessary.
+The write is performed simply by marking
+the buffer as ``dirty.''
+The physical I/O is then deferred until
+the buffer is renamed.
+.PP
+The benefits in reduction of physical I/O
+of this scheme are substantial,
+especially considering the file system implementation.
+There are,
+however,
+some drawbacks.
+The asynchronous nature of the
+algorithm makes error reporting
+and meaningful user error handling
+almost impossible.
+The cavalier approach to I/O error
+handling in the
+.UX
+system is partly due to the asynchronous
+nature of the block I/O system.
+A second problem is in the delayed writes.
+If the system stops unexpectedly,
+it is almost certain that there is a
+lot of logically complete,
+but physically incomplete,
+I/O in the buffers.
+There is a system primitive to
+flush all outstanding I/O activity
+from the buffers.
+Periodic use of this primitive helps,
+but does not solve, the problem.
+Finally,
+the associativity in the buffers
+can alter the physical I/O sequence
+from that of the logical I/O sequence.
+This means that there are times
+when data structures on disk are inconsistent,
+even though the software is careful
+to perform I/O in the correct order.
+On non-random devices,
+notably magnetic tape,
+the inversions of writes can be disastrous.
+The problem with magnetic tapes is ``cured'' by
+allowing only one outstanding write request
+per drive.
+.NH 2
+Character I/O system
+.PP
+The character I/O system consists of all
+devices that do not fall into the block I/O model.
+This includes the ``classical'' character devices
+such as communications lines, paper tape, and
+line printers.
+It also includes magnetic tape and disks when
+they are not used in a stereotyped way,
+for example, 80-byte physical records on tape
+and track-at-a-time disk copies.
+In short,
+the character I/O interface
+means ``everything other than block.''
+I/O requests from the user are sent to the
+device driver essentially unaltered.
+The implementation of these requests is, of course,
+up to the device driver.
+There are guidelines and conventions
+to help the implementation of
+certain types of device drivers.
+.NH 3
+Disk drivers
+.PP
+Disk drivers are implemented
+with a queue of transaction records.
+Each record holds a read/write flag,
+a primary memory address,
+a secondary memory address, and
+a transfer byte count.
+Swapping is accomplished by passing
+such a record to the swapping device driver.
+The block I/O interface is implemented by
+passing such records with requests to
+fill and empty system buffers.
+The character I/O interface to the disk
+drivers create a transaction record that
+points directly into the user area.
+The routine that creates this record also insures
+that the user is not swapped during this
+I/O transaction.
+Thus by implementing the general disk driver,
+it is possible to use the disk
+as a block device,
+a character device, and a swap device.
+The only really disk-specific code in normal
+disk drivers is the pre-sort of transactions to
+minimize latency for a particular device, and
+the actual issuing of the I/O request.
+.NH 3
+Character lists
+.PP
+Real character-oriented devices may
+be implemented using the common
+code to handle character lists.
+A character list is a queue of characters.
+One routine puts a character on a queue.
+Another gets a character from a queue.
+It is also possible to ask how many
+characters are currently on a queue.
+Storage for all queues in the system comes
+from a single common pool.
+Putting a character on a queue will allocate
+space from the common pool and link the
+character onto the data structure defining the queue.
+Getting a character from a queue returns
+the corresponding space to the pool.
+.PP
+A typical character-output device
+(paper tape punch, for example)
+is implemented by passing characters
+from the user onto a character queue until
+some maximum number of characters is on the queue.
+The I/O is prodded to start as
+soon as there is anything on the queue
+and, once started,
+it is sustained by hardware completion interrupts.
+Each time there is a completion interrupt,
+the driver gets the next character from the queue
+and sends it to the hardware.
+The number of characters on the queue is checked and,
+as the count falls through some intermediate level,
+an event (the queue address) is signaled.
+The process that is passing characters from
+the user to the queue can be waiting on the event, and
+refill the queue to its maximum
+when the event occurs.
+.PP
+A typical character input device
+(for example, a paper tape reader)
+is handled in a very similar manner.
+.PP
+Another class of character devices is the terminals.
+A terminal is represented by three
+character queues.
+There are two input queues (raw and canonical)
+and an output queue.
+Characters going to the output of a terminal
+are handled by common code exactly as described
+above.
+The main difference is that there is also code
+to interpret the output stream as
+.UC  ASCII
+characters and to perform some translations,
+e.g., escapes for deficient terminals.
+Another common aspect of terminals is code
+to insert real-time delay after certain control characters.
+.PP
+Input on terminals is a little different.
+Characters are collected from the terminal and
+placed on a raw input queue.
+Some device-dependent code conversion and
+escape interpretation is handled here.
+When a line is complete in the raw queue,
+an event is signaled.
+The code catching this signal then copies a
+line from the raw queue to a canonical queue
+performing the character erase and line kill editing.
+User read requests on terminals can be
+directed at either the raw or canonical queues.
+.NH 3
+Other character devices
+.PP
+Finally,
+there are devices that fit no general category.
+These devices are set up as character I/O drivers.
+An example is a driver that reads and writes
+unmapped primary memory as an I/O device.
+Some devices are too
+fast to be treated a character at time,
+but do not fit the disk I/O mold.
+Examples are fast communications lines and
+fast line printers.
+These devices either have their own buffers
+or ``borrow'' block I/O buffers for a while and
+then give them back.
+.NH
+THE FILE SYSTEM
+.PP
+In the
+.UX
+system,
+a file is a (one-dimensional) array of bytes.
+No other structure of files is implied by the
+system.
+Files are attached anywhere
+(and possibly multiply)
+onto a hierarchy of directories.
+Directories are simply files that
+users cannot write.
+For a further discussion
+of the external view of files and directories,
+see Ref.\0
+.[
+ritchie thompson unix bstj 1978
+%Q This issue
+.].
+.PP
+The
+.UX
+file system is a disk data structure
+accessed completely through
+the block I/O system.
+As stated before,
+the canonical view of a ``disk'' is
+a randomly addressable array of
+512-byte blocks.
+A file system breaks the disk into
+four self-identifying regions.
+The first block (address 0)
+is unused by the file system.
+It is left aside for booting procedures.
+The second block (address 1)
+contains the so-called ``super-block.''
+This block,
+among other things,
+contains the size of the disk and
+the boundaries of the other regions.
+Next comes the i-list,
+a list of file definitions.
+Each file definition is
+a 64-byte structure, called an i-node.
+The offset of a particular i-node
+within the i-list is called its i-number.
+The combination of device name
+(major and minor numbers) and i-number
+serves to uniquely name a particular file.
+After the i-list,
+and to the end of the disk,
+come free storage blocks that
+are available for the contents of files.
+.PP
+The free space on a disk is maintained
+by a linked list of available disk blocks.
+Every block in this chain contains a disk address
+of the next block in the chain.
+The remaining space contains the address of up to
+50 disk blocks that are also free.
+Thus with one I/O operation,
+the system obtains 50 free blocks and a
+pointer where to find more.
+The disk allocation algorithms are
+very straightforward.
+Since all allocation is in fixed-size
+blocks and there is strict accounting of
+space,
+there is no need to compact or garbage collect.
+However,
+as disk space becomes dispersed,
+latency gradually increases.
+Some installations choose to occasionally compact
+disk space to reduce latency.
+.PP
+An i-node contains 13 disk addresses.
+The first 10 of these addresses point directly at
+the first 10 blocks of a file.
+If a file is larger than 10 blocks (5,120 bytes),
+then the eleventh address points at a block
+that contains the addresses of the next 128 blocks of the file.
+If the file is still larger than this
+(70,656 bytes),
+then the twelfth block points at up to 128 blocks,
+each pointing to 128 blocks of the file.
+Files yet larger
+(8,459,264 bytes)
+use the thirteenth address for a ``triple indirect'' address.
+The algorithm ends here with the maximum file size
+of 1,082,201,087 bytes.
+.PP
+A logical directory hierarchy is added
+to this flat physical structure simply
+by adding a new type of file, the directory.
+A directory is accessed exactly as an ordinary file.
+It contains 16-byte entries consisting of
+a 14-byte name and an i-number.
+The root of the hierarchy is at a known i-number
+(\fIviz.,\fR 2).
+The file system structure allows an arbitrary, directed graph
+of directories with regular files linked in
+at arbitrary places in this graph.
+In fact,
+very early
+.UX
+systems used such a structure.
+Administration of such a structure became so
+chaotic that later systems were restricted
+to a directory tree.
+Even now,
+with regular files linked multiply
+into arbitrary places in the tree,
+accounting for space has become a problem.
+It may become necessary to restrict the entire
+structure to a tree,
+and allow a new form of linking that
+is subservient to the tree structure.
+.PP
+The file system allows
+easy creation,
+easy removal,
+easy random accessing,
+and very easy space allocation.
+With most physical addresses confined
+to a small contiguous section of disk,
+it is also easy to dump, restore, and
+check the consistency of the file system.
+Large files suffer from indirect addressing,
+but the cache prevents most of the implied physical I/O
+without adding much execution.
+The space overhead properties of this scheme are quite good.
+For example,
+on one particular file system,
+there are 25,000 files containing 130M bytes of data-file content.
+The overhead (i-node, indirect blocks, and last block breakage)
+is about 11.5M bytes.
+The directory structure to support these files
+has about 1,500 directories containing 0.6M bytes of directory content
+and about 0.5M bytes of overhead in accessing the directories.
+Added up any way,
+this comes out to less than a 10 percent overhead for actual
+stored data.
+Most systems have this much overhead in
+padded trailing blanks alone.
+.NH 2
+File system implementation
+.PP
+Because the i-node defines a file,
+the implementation of the file system centers
+around access to the i-node.
+The system maintains a table of all active
+i-nodes.
+As a new file is accessed,
+the system locates the corresponding i-node,
+allocates an i-node table entry, and reads
+the i-node into primary memory.
+As in the buffer cache,
+the table entry is considered to be the current
+version of the i-node.
+Modifications to the i-node are made to
+the table entry.
+When the last access to the i-node goes
+away,
+the table entry is copied back to the
+secondary store i-list and the table entry is freed.
+.PP
+All I/O operations on files are carried out
+with the aid of the corresponding i-node table entry.
+The accessing of a file is a straightforward
+implementation of the algorithms mentioned previously.
+The user is not aware of i-nodes and i-numbers.
+References to the file system are made in terms of
+path names of the directory tree.
+Converting a path name into an i-node table entry
+is also straightforward.
+Starting at some known i-node
+(the root or the current directory of some process),
+the next component of the path name is
+searched by reading the directory.
+This gives an i-number and an implied device
+(that of the directory).
+Thus the next i-node table entry can be accessed.
+If that was the last component of the path name,
+then this i-node is the result.
+If not,
+this i-node is the directory needed to look up
+the next component of the path name, and the
+algorithm is repeated.
+.PP
+The user process accesses the file system with
+certain primitives.
+The most common of these are
+.UL open ,
+.UL create ,
+.UL read ,
+.UL write ,
+.UL seek ,
+and
+.UL close .
+The data structures maintained are shown in Fig. 2.
+.KS
+.sp 22P
+.ce
+Fig. 2\(emFile system data structure.
+.KE
+In the system data segment associated with a user,
+there is room for some (usually between 10 and 50) open files.
+This open file table consists of pointers that can be used to access
+corresponding i-node table entries.
+Associated with each of these open files is
+a current I/O pointer.
+This is a byte offset of
+the next read/write operation on the file.
+The system treats each read/write request
+as random with an implied seek to the
+I/O pointer.
+The user usually thinks of the file as
+sequential with the I/O pointer
+automatically counting the number of bytes
+that have been read/written from the file.
+The user may,
+of course,
+perform random I/O by setting the I/O pointer
+before reads/writes.
+.PP
+With file sharing,
+it is necessary to allow related
+processes to share a common I/O pointer
+and yet have separate I/O pointers
+for independent processes
+that access the same file.
+With these two conditions,
+the I/O pointer cannot reside
+in the i-node table nor can
+it reside in the list of
+open files for the process.
+A new table
+(the open file table)
+was invented for the sole purpose
+of holding the I/O pointer.
+Processes that share the same open
+file
+(the result of
+.UL fork s)
+share a common open file table entry.
+A separate open of the same file will
+only share the i-node table entry,
+but will have distinct open file table entries.
+.PP
+The main file system primitives are implemented as follows.
+.UL \&open
+converts a file system path name into an i-node
+table entry.
+A pointer to the i-node table entry is placed in a
+newly created open file table entry.
+A pointer to the file table entry is placed in the
+system data segment for the process.
+.UL \&create
+first creates a new i-node entry,
+writes the i-number into a directory, and
+then builds the same structure as for an
+.UL open .
+.UL \&read
+and
+.UL write
+just access the i-node entry as described above.
+.UL \&seek
+simply manipulates the I/O pointer.
+No physical seeking is done.
+.UL \&close
+just frees the structures built by
+.UL open
+and
+.UL create .
+Reference counts are kept on the open file table entries and
+the i-node table entries to free these structures after
+the last reference goes away.
+.UL \&unlink
+simply decrements the count of the
+number of directories pointing at the given i-node.
+When the last reference to an i-node table entry
+goes away,
+if the i-node has no directories pointing to it,
+then the file is removed and the i-node is freed.
+This delayed removal of files prevents
+problems arising from removing active files.
+A file may be removed while still open.
+The resulting unnamed file vanishes
+when the file is closed.
+This is a method of obtaining temporary files.
+.PP
+There is a type of unnamed
+.UC  FIFO
+file called a
+.UL pipe.
+Implementation of
+.UL pipe s
+consists of implied
+.UL seek s
+before each
+.UL read
+or
+.UL write
+in order to implement
+first-in-first-out.
+There are also checks and synchronization
+to prevent the
+writer from grossly outproducing the
+reader and to prevent the reader from
+overtaking the writer.
+.NH 2
+Mounted file systems
+.PP
+The file system of a
+.UX
+system
+starts with some designated block device
+formatted as described above to contain
+a hierarchy.
+The root of this structure is the root of
+the
+.UX
+file system.
+A second formatted block device may be
+mounted
+at any leaf of
+the current hierarchy.
+This logically extends the current hierarchy.
+The implementation of
+mounting
+is trivial.
+A mount table is maintained containing
+pairs of designated leaf i-nodes and
+block devices.
+When converting a path name into an i-node,
+a check is made to see if the new i-node is a
+designated leaf.
+If it is,
+the i-node of the root
+of the block device replaces it.
+.PP
+Allocation of space for a file is taken
+from the free pool on the device on which the
+file lives.
+Thus a file system consisting of many
+mounted devices does not have a common pool of
+free secondary storage space.
+This separation of space on different
+devices is necessary to allow easy
+unmounting
+of a device.
+.NH 2
+Other system functions
+.PP
+There are some other things that the system
+does for the user\-a
+little accounting,
+a little tracing/debugging,
+and a little access protection.
+Most of these things are not very
+well developed
+because our use of the system in computing science research
+does not need them.
+There are some features that are missed in some
+applications, for example, better inter-process communication.
+.PP
+The
+.UX
+kernel is an I/O multiplexer more than
+a complete operating system.
+This is as it should be.
+Because of this outlook,
+many features are
+found in most
+other operating systems that are missing from the
+.UX
+kernel.
+For example,
+the
+.UX
+kernel does not support
+file access methods,
+file disposition,
+file formats,
+file maximum size,
+spooling,
+command language,
+logical records,
+physical records,
+assignment of logical file names,
+logical file names,
+more than one character set,
+an operator's console,
+an operator,
+log-in,
+or log-out.
+Many of these things are symptoms rather than features.
+Many of these things are implemented
+in user software
+using the kernel as a tool.
+A good example of this is the command language.
+.[
+bourne shell 1978 bstj
+%Q This issue
+.]
+Each user may have his own command language.
+Maintenance of such code is as easy as
+maintaining user code.
+The idea of implementing ``system'' code with general
+user primitives
+comes directly from
+.UC  MULTICS .
+.[
+organick multics 1972
+.]
+.LP
+.[
+$LIST$
+.]
diff --git a/doc/7thEdMan/vol2/index b/doc/7thEdMan/vol2/index
new file mode 100644 (file)
index 0000000..b0a6de1
--- /dev/null
@@ -0,0 +1,331 @@
+.nr n 0 +1
+.TL
+UNIX Programmer's Manual
+.br
+.sp .5
+Volume 2 \(em Supplementary Documents
+.AU
+.ft B
+.ps 11
+Seventh Edition
+.AI
+January 10, 1979
+.PP
+This volume contains documents which supplement
+the information contained in Volume 1 of 
+.ul
+The
+.ul
+.UX
+.ul
+Programmer's Manual.
+The documents here are grouped roughly into
+the areas of
+basics,
+editing,
+language tools,
+document preparation,
+and
+system maintenance.
+Further general information may be found in
+the Bell System Technical Journal
+special issue on
+.UX ,
+July-August, 1978.
+.PP
+Many of the documents cited within this volume as
+Bell Laboratories internal memoranda
+or Computing Science Technical Reports
+(CSTR) are also contained here.
+.PP
+These documents contain occasional localisms,
+typically references to other operating systems
+like
+GCOS
+and
+IBM.
+In all cases, such references may be safely ignored
+by
+UNIX
+users.
+.SH
+General Works
+.IP \n+n.
+7th Edition UNIX \(em Summary.
+.RS
+A concise summary of the facilities available on
+.UX .
+.RE
+.IP \n+n.
+The UNIX Time-Sharing System.
+D. M. Ritchie and K. Thompson.
+.RS
+The original
+.UX
+paper, reprinted from CACM.
+.RE
+.SH
+Getting Started
+.IP \n+n.
+UNIX for Beginners \(em Second Edition.
+B. W. Kernighan.
+.RS
+An introduction to the most basic use of the system.
+.RE
+.IP \n+n.
+A Tutorial Introduction to the UNIX Text Editor.
+B. W. Kernighan.
+.RS
+An easy way to get started with the editor.
+.RE
+.IP \n+n.
+Advanced Editing on UNIX.
+B. W. Kernighan.
+.RS
+The next step.
+.RE
+.IP \n+n.
+An Introduction to the UNIX Shell.
+S. R. Bourne.
+.RS
+An introduction to the capabilities of the command interpreter,
+the shell.
+.RE
+.IP \n+n.
+Learn \(em Computer Aided Instruction on UNIX.
+M. E. Lesk and B. W. Kernighan.
+.RS
+Describes a computer-aided instruction program that walks new users
+through the basics of
+files, 
+the editor,
+and
+document preparation software.
+.RE
+.SH
+Document Preparation
+.IP \n+n.
+Typing Documents on the UNIX System.
+M. E. Lesk.
+.RS
+Describes the basic use of the formatting tools.
+Also describes ``\-ms'', a standardized package of formatting requests
+that can be used to lay out most documents
+(including those in this volume).
+.RE
+.IP \n+n.
+A System for Typesetting Mathematics.
+B. W. Kernighan and L. L. Cherry.
+.RS
+Describes EQN. an easy-to-learn language for doing high-quality mathematical typesetting,
+.RE
+.IP \n+n.
+TBL \(em A Program to Format Tables.
+M. E. Lesk.
+.RS
+A program to permit easy specification of tabular material
+for typesetting.
+Again, easy to learn and use.
+.RE
+.IP \n+n.
+Some Applications of Inverted Indexes on the UNIX System.
+M. E. Lesk.
+.RS
+Describes, among other things, the program REFER
+which fills in bibliographic citations from a data base
+automatically.
+.RE
+.RE
+.IP \n+n.
+NROFF/TROFF User's Manual.
+J. F. Ossanna.
+.RS
+The basic formatting program.
+.RE
+.IP \n+n.
+A TROFF Tutorial.
+B. W. Kernighan.
+.RS
+An introduction to TROFF for those who
+really want to know such things.
+.RE
+.SH
+Programming
+.IP \n+n.
+The C Programming Language \(em Reference Manual.
+D. M. Ritchie.
+.RS
+Official statement of the syntax and semantics of C.
+Should be supplemented by
+.ul
+The C Programming Language,
+B. W. Kernighan and D. M. Ritchie,
+Prentice-Hall, 1978,
+which contains a tutorial introduction and many examples.
+.RE
+.IP \n+n.
+Lint, A C Program Checker.
+S. C. Johnson.
+.RS
+Checks C programs
+for syntax errors, type violations,
+portability problems,
+and a variety of probable errors.
+.RE
+.IP \n+n.
+Make \(em A Program for Maintaining Computer Programs.
+S. I. Feldman.
+.RS
+Indispensable tool for making sure that large programs
+are properly compiled with minimal effort.
+.RE
+.IP \n+n.
+UNIX Programming.
+B. W. Kernighan and D. M. Ritchie.
+.RS
+Describes the programming interface to the operating system
+and the standard I/O library.
+.RE
+.IP \n+n.
+A Tutorial Introduction to ADB.
+J. F. Maranzano and S. R. Bourne.
+.RS
+How to use the ADB debugger.
+.RE
+.SH
+Supporting Tools and Languages
+.IP \n+n.
+YACC: Yet Another Compiler-Compiler.
+S. C. Johnson.
+.RS
+Converts a BNF specification of a language
+and semantic actions written in C into a compiler for the language.
+.RE
+.IP \n+n.
+LEX \(em A Lexical Analyzer Generator.
+M. E. Lesk and E. Schmidt.
+.RS
+Creates a recognizer for a set of regular expressions;
+each regular expression can be followed by arbitrary C code
+which will be executed when the regular expression is found.
+.RE
+.IP \n+n.
+A Portable Fortran 77 Compiler.
+S. I. Feldman and P. J. Weinberger.
+.RS
+The first Fortran 77 compiler, and still one of the best.
+.RE
+.IP \n+n.
+Ratfor \(em A Preprocessor for a Rational Fortran.
+B. W. Kernighan.
+.RS
+Converts a Fortran with C-like control structures and cosmetics
+into real, ugly Fortran.
+.RE
+.IP \n+n.
+The M4 Macro Processor.
+B. W. Kernighan and D. M. Ritchie.
+.RS
+M4 is a macro processor useful as a front end for C, Ratfor,
+Cobol, and in its own right.
+.RE
+.IP \n+n.
+SED \(em A Non-interactive Text Editor.
+L. E. McMahon.
+.RS
+A variant of the editor for processing large
+inputs.
+.RE
+.IP \n+n.
+AWK \(em A Pattern Scanning and Processing Language.
+A. V. Aho, B. W. Kernighan and 
+.RS
+P. J. Weinberger.
+.br
+Makes it easy to specify many data transformation and selection operations.
+.RE
+.IP \n+n.
+DC \(em An Interactive Desk Calculator.
+R. H. Morris and L. L. Cherry.
+.RS
+A super HP calculator, if you don't need floating point.
+.RE
+.IP \n+n.
+BC \(em An Arbitrary Precision Desk-Calculator Language.
+L. L. Cherry and R. H. Morris.
+.RS
+A front end for DC
+that provides infix notation, control flow, and built-in functions.
+.RE
+.IP \n+n.
+UNIX Assembler Reference Manual.
+D. M. Ritchie.
+.RS
+The ultimate dead language.
+.RE
+.SH
+Implementation, Maintenance, and Miscellaneous
+.IP \n+n.
+Setting Up UNIX \(em Seventh Edition.
+C. B. Haley and D. M. Ritchie.
+.RS
+How to configure and get your system running.
+.RE
+.IP \n+n.
+Regenerating System Software.
+C. B. Haley and D. M. Ritchie.
+.RS
+What do do when you have to change things.
+.RE
+.IP \n+n.
+UNIX Implementation.
+K. Thompson.
+.RS
+How the system actually works inside.
+.RE
+.IP \n+n.
+The UNIX I/O System.
+D. M. Ritchie.
+.RS
+How the I/O system really works.
+.RE
+.IP \n+n.
+A Tour Through the UNIX C Compiler.
+D. M. Ritchie.
+.RS
+How the PDP-11 compiler works inside.
+.RE
+.IP \n+n.
+A Tour Through the Portable C Compiler.
+S. C. Johnson.
+.RS
+How the portable C compiler works inside.
+.RE
+.IP \n+n.
+A Dial-Up Network of UNIX Systems.
+D. A. Nowitz and M. E. Lesk.
+.RS
+Describes UUCP, a program for communicating files
+between UNIX systems.
+.RE
+.IP \n+n.
+UUCP Implementation Description.
+D. A. Nowitz.
+.RS
+How UUCP works, and how to administer it.
+.RE
+.IP \n+n.
+On the Security of UNIX.
+D. M. Ritchie.
+.RS
+Hints on how to break UNIX, and how to avoid doing so.
+.RE
+.IP \n+n.
+Password Security: A Case History.
+R. H. Morris and K. Thompson.
+.RS
+How the bad guys used to be able to
+break the password algorithm,
+and why they can't now,
+at least not so easily.
+.RE
diff --git a/doc/7thEdMan/vol2/iosys b/doc/7thEdMan/vol2/iosys
new file mode 100644 (file)
index 0000000..512d30b
--- /dev/null
@@ -0,0 +1,1044 @@
+.TL
+The UNIX I/O System
+.AU
+Dennis M. Ritchie
+.AI
+.MH
+.PP
+This paper gives an overview of the workings of the UNIX\(dg
+.FS
+\(dgUNIX is a Trademark of Bell Laboratories.
+.FE
+I/O system.
+It was written with an eye toward providing
+guidance to writers of device driver routines,
+and is oriented more toward describing the environment
+and nature of device drivers than the implementation
+of that part of the file system which deals with
+ordinary files.
+.PP
+It is assumed that the reader has a good knowledge
+of the overall structure of the file system as discussed
+in the paper ``The UNIX Time-sharing System.''
+A more detailed discussion
+appears in
+``UNIX Implementation;''
+the current document restates parts of that one,
+but is still more detailed.
+It is most useful in
+conjunction with a copy of the system code,
+since it is basically an exegesis of that code.
+.SH
+Device Classes
+.PP
+There are two classes of device:
+.I block
+and
+.I character.
+The block interface is suitable for devices
+like disks, tapes, and DECtape
+which work, or can work, with addressible 512-byte blocks.
+Ordinary magnetic tape just barely fits in this category,
+since by use of forward
+and
+backward spacing any block can be read, even though
+blocks can be written only at the end of the tape.
+Block devices can at least potentially contain a mounted
+file system.
+The interface to block devices is very highly structured;
+the drivers for these devices share a great many routines
+as well as a pool of buffers.
+.PP
+Character-type devices have a much
+more straightforward interface, although
+more work must be done by the driver itself.
+.PP
+Devices of both types are named by a
+.I major
+and a
+.I minor
+device number.
+These numbers are generally stored as an integer
+with the minor device number
+in the low-order 8 bits and the major device number
+in the next-higher 8 bits;
+macros
+.I major
+and
+.I minor
+are available to access these numbers.
+The major device number selects which driver will deal with
+the device; the minor device number is not used
+by the rest of the system but is passed to the
+driver at appropriate times.
+Typically the minor number
+selects a subdevice attached to
+a given controller, or one of
+several similar hardware interfaces.
+.PP
+The major device numbers for block and character devices
+are used as indices in separate tables;
+they both start at 0 and therefore overlap.
+.SH
+Overview of I/O
+.PP
+The purpose of
+the
+.I open
+and
+.I creat
+system calls is to set up entries in three separate
+system tables.
+The first of these is the
+.I u_ofile
+table,
+which is stored in the system's per-process
+data area
+.I u.
+This table is indexed by
+the file descriptor returned by the
+.I open
+or
+.I creat,
+and is accessed during
+a
+.I read,
+.I write,
+or other operation on the open file.
+An entry contains only
+a pointer to the corresponding
+entry of the
+.I file
+table,
+which is a per-system data base.
+There is one entry in the
+.I file
+table for each
+instance of
+.I open
+or
+.I creat.
+This table is per-system because the same instance
+of an open file must be shared among the several processes
+which can result from
+.I forks
+after the file is opened.
+A
+.I file
+table entry contains
+flags which indicate whether the file
+was open for reading or writing or is a pipe, and
+a count which is used to decide when all processes
+using the entry have terminated or closed the file
+(so the entry can be abandoned).
+There is also a 32-bit file offset
+which is used to indicate where in the file the next read
+or write will take place.
+Finally, there is a pointer to the
+entry for the file in the
+.I inode
+table,
+which contains a copy of the file's i-node.
+.PP
+Certain open files can be designated ``multiplexed''
+files, and several other flags apply to such
+channels.
+In such a case, instead of an offset,
+there is a pointer to an associated multiplex channel table.
+Multiplex channels will not be discussed here.
+.PP
+An entry in the
+.I file
+table corresponds precisely to an instance of
+.I open
+or
+.I creat;
+if the same file is opened several times,
+it will have several
+entries in this table.
+However,
+there is at most one entry
+in the
+.I inode
+table for a given file.
+Also, a file may enter the
+.I inode
+table not only because it is open,
+but also because it is the current directory
+of some process or because it
+is a special file containing a currently-mounted
+file system.
+.PP
+An entry in the
+.I inode
+table differs somewhat from the
+corresponding i-node as stored on the disk;
+the modified and accessed times are not stored,
+and the entry is augmented
+by a flag word containing information about the entry,
+a count used to determine when it may be
+allowed to disappear,
+and the device and i-number
+whence the entry came.
+Also, the several block numbers that give addressing
+information for the file are expanded from
+the 3-byte, compressed format used on the disk to full
+.I long
+quantities.
+.PP
+During the processing of an
+.I open
+or
+.I creat
+call for a special file,
+the system always calls the device's
+.I open
+routine to allow for any special processing
+required (rewinding a tape, turning on
+the data-terminal-ready lead of a modem, etc.).
+However,
+the
+.I close
+routine is called only when the last
+process closes a file,
+that is, when the i-node table entry
+is being deallocated.
+Thus it is not feasible
+for a device to maintain, or depend on,
+a count of its users, although it is quite
+possible to
+implement an exclusive-use device which cannot
+be reopened until it has been closed.
+.PP
+When a
+.I read
+or
+.I write
+takes place,
+the user's arguments
+and the
+.I file
+table entry are used to set up the
+variables
+.I u.u_base,
+.I u.u_count,
+and
+.I u.u_offset
+which respectively contain the (user) address
+of the I/O target area, the byte-count for the transfer,
+and the current location in the file.
+If the file referred to is
+a character-type special file, the appropriate read
+or write routine is called; it is responsible
+for transferring data and updating the
+count and current location appropriately
+as discussed below.
+Otherwise, the current location is used to calculate
+a logical block number in the file.
+If the file is an ordinary file the logical block
+number must be mapped (possibly using indirect blocks)
+to a physical block number; a block-type
+special file need not be mapped.
+This mapping is performed by the
+.I bmap
+routine.
+In any event, the resulting physical block number
+is used, as discussed below, to
+read or write the appropriate device.
+.SH
+Character Device Drivers
+.PP
+The
+.I cdevsw
+table specifies the interface routines present for
+character devices.
+Each device provides five routines:
+open, close, read, write, and special-function
+(to implement the
+.I ioctl
+system call).
+Any of these may be missing.
+If a call on the routine
+should be ignored,
+(e.g.
+.I open
+on non-exclusive devices that require no setup)
+the
+.I cdevsw
+entry can be given as
+.I nulldev;
+if it should be considered an error,
+(e.g.
+.I write
+on read-only devices)
+.I nodev
+is used.
+For terminals,
+the
+.I cdevsw
+structure also contains a pointer to the
+.I tty
+structure associated with the terminal.
+.PP
+The
+.I open
+routine is called each time the file
+is opened with the full device number as argument.
+The second argument is a flag which is
+non-zero only if the device is to be written upon.
+.PP
+The
+.I close
+routine is called only when the file
+is closed for the last time,
+that is when the very last process in
+which the file is open closes it.
+This means it is not possible for the driver to
+maintain its own count of its users.
+The first argument is the device number;
+the second is a flag which is non-zero
+if the file was open for writing in the process which
+performs the final
+.I close.
+.PP
+When
+.I write
+is called, it is supplied the device
+as argument.
+The per-user variable
+.I u.u_count
+has been set to
+the number of characters indicated by the user;
+for character devices, this number may be 0
+initially.
+.I u.u_base
+is the address supplied by the user from which to start
+taking characters.
+The system may call the
+routine internally, so the
+flag
+.I u.u_segflg
+is supplied that indicates,
+if
+.I on,
+that
+.I u.u_base
+refers to the system address space instead of
+the user's.
+.PP
+The
+.I write
+routine
+should copy up to
+.I u.u_count
+characters from the user's buffer to the device,
+decrementing
+.I u.u_count
+for each character passed.
+For most drivers, which work one character at a time,
+the routine
+.I "cpass( )"
+is used to pick up characters
+from the user's buffer.
+Successive calls on it return
+the characters to be written until
+.I u.u_count
+goes to 0 or an error occurs,
+when it returns \(mi1.
+.I Cpass
+takes care of interrogating
+.I u.u_segflg
+and updating
+.I u.u_count.
+.PP
+Write routines which want to transfer
+a probably large number of characters into an internal
+buffer may also use the routine
+.I "iomove(buffer, offset, count, flag)"
+which is faster when many characters must be moved.
+.I Iomove
+transfers up to
+.I count
+characters into the
+.I buffer
+starting
+.I offset
+bytes from the start of the buffer;
+.I flag
+should be
+.I B_WRITE
+(which is 0) in the write case.
+Caution:
+the caller is responsible for making sure
+the count is not too large and is non-zero.
+As an efficiency note,
+.I iomove
+is much slower if any of
+.I "buffer+offset, count"
+or
+.I u.u_base
+is odd.
+.PP
+The device's
+.I read
+routine is called under conditions similar to
+.I write,
+except that
+.I u.u_count
+is guaranteed to be non-zero.
+To return characters to the user, the routine
+.I "passc(c)"
+is available; it takes care of housekeeping
+like
+.I cpass
+and returns \(mi1 as the last character
+specified by
+.I u.u_count
+is returned to the user;
+before that time, 0 is returned.
+.I Iomove
+is also usable as with
+.I write;
+the flag should be
+.I B_READ
+but the same cautions apply.
+.PP
+The ``special-functions'' routine
+is invoked by the
+.I stty
+and
+.I gtty
+system calls as follows:
+.I "(*p) (dev, v)"
+where
+.I p
+is a pointer to the device's routine,
+.I dev
+is the device number,
+and
+.I v
+is a vector.
+In the
+.I gtty
+case,
+the device is supposed to place up to 3 words of status information
+into the vector; this will be returned to the caller.
+In the
+.I stty
+case,
+.I v
+is 0;
+the device should take up to 3 words of
+control information from
+the array
+.I "u.u_arg[0...2]."
+.PP
+Finally, each device should have appropriate interrupt-time
+routines.
+When an interrupt occurs, it is turned into a C-compatible call
+on the devices's interrupt routine.
+The interrupt-catching mechanism makes
+the low-order four bits of the ``new PS'' word in the
+trap vector for the interrupt available
+to the interrupt handler.
+This is conventionally used by drivers
+which deal with multiple similar devices
+to encode the minor device number.
+After the interrupt has been processed,
+a return from the interrupt handler will
+return from the interrupt itself.
+.PP
+A number of subroutines are available which are useful
+to character device drivers.
+Most of these handlers, for example, need a place
+to buffer characters in the internal interface
+between their ``top half'' (read/write)
+and ``bottom half'' (interrupt) routines.
+For relatively low data-rate devices, the best mechanism
+is the character queue maintained by the
+routines
+.I getc
+and
+.I putc.
+A queue header has the structure
+.DS
+struct {
+       int     c_cc;   /* character count */
+       char    *c_cf;  /* first character */
+       char    *c_cl;  /* last character */
+} queue;
+.DE
+A character is placed on the end of a queue by
+.I "putc(c, &queue)"
+where
+.I c
+is the character and
+.I queue
+is the queue header.
+The routine returns \(mi1 if there is no space
+to put the character, 0 otherwise.
+The first character on the queue may be retrieved
+by
+.I "getc(&queue)"
+which returns either the (non-negative) character
+or \(mi1 if the queue is empty.
+.PP
+Notice that the space for characters in queues is
+shared among all devices in the system
+and in the standard system there are only some 600
+character slots available.
+Thus device handlers,
+especially write routines, must take
+care to avoid gobbling up excessive numbers of characters.
+.PP
+The other major help available
+to device handlers is the sleep-wakeup mechanism.
+The call
+.I "sleep(event, priority)"
+causes the process to wait (allowing other processes to run)
+until the
+.I event
+occurs;
+at that time, the process is marked ready-to-run
+and the call will return when there is no
+process with higher
+.I priority.
+.PP
+The call
+.I "wakeup(event)"
+indicates that the
+.I event
+has happened, that is, causes processes sleeping
+on the event to be awakened.
+The
+.I event
+is an arbitrary quantity agreed upon
+by the sleeper and the waker-up.
+By convention, it is the address of some data area used
+by the driver, which guarantees that events
+are unique.
+.PP
+Processes sleeping on an event should not assume
+that the event has really happened;
+they should check that the conditions which
+caused them to sleep no longer hold.
+.PP
+Priorities can range from 0 to 127;
+a higher numerical value indicates a less-favored
+scheduling situation.
+A distinction is made between processes sleeping
+at priority less than the parameter
+.I PZERO
+and those at numerically larger priorities.
+The former cannot
+be interrupted by signals, although it
+is conceivable that it may be swapped out.
+Thus it is a bad idea to sleep with
+priority less than PZERO on an event which might never occur.
+On the other hand, calls to
+.I sleep
+with larger priority
+may never return if the process is terminated by
+some signal in the meantime.
+Incidentally, it is a gross error to call
+.I sleep
+in a routine called at interrupt time, since the process
+which is running is almost certainly not the
+process which should go to sleep.
+Likewise, none of the variables in the user area
+``\fIu\fB.\fR''
+should be touched, let alone changed, by an interrupt routine.
+.PP
+If a device driver
+wishes to wait for some event for which it is inconvenient
+or impossible to supply a
+.I wakeup,
+(for example, a device going on-line, which does not
+generally cause an interrupt),
+the call
+.I "sleep(&lbolt, priority)
+may be given.
+.I Lbolt
+is an external cell whose address is awakened once every 4 seconds
+by the clock interrupt routine.
+.PP
+The routines
+.I "spl4( ), spl5( ), spl6( ), spl7( )"
+are available to
+set the processor priority level as indicated to avoid
+inconvenient interrupts from the device.
+.PP
+If a device needs to know about real-time intervals,
+then
+.I "timeout(func, arg, interval)
+will be useful.
+This routine arranges that after
+.I interval
+sixtieths of a second, the
+.I func
+will be called with
+.I arg
+as argument, in the style
+.I "(*func)(arg).
+Timeouts are used, for example,
+to provide real-time delays after function characters
+like new-line and tab in typewriter output,
+and to terminate an attempt to
+read the 201 Dataphone
+.I dp
+if there is no response within a specified number
+of seconds.
+Notice that the number of sixtieths of a second is limited to 32767,
+since it must appear to be positive,
+and that only a bounded number of timeouts
+can be going on at once.
+Also, the specified
+.I func
+is called at clock-interrupt time, so it should
+conform to the requirements of interrupt routines
+in general.
+.SH
+The Block-device Interface
+.PP
+Handling of block devices is mediated by a collection
+of routines that manage a set of buffers containing
+the images of blocks of data on the various devices.
+The most important purpose of these routines is to assure
+that several processes that access the same block of the same
+device in multiprogrammed fashion maintain a consistent
+view of the data in the block.
+A secondary but still important purpose is to increase
+the efficiency of the system by
+keeping in-core copies of blocks that are being
+accessed frequently.
+The main data base for this mechanism is the
+table of buffers
+.I buf.
+Each buffer header contains a pair of pointers
+.I "(b_forw, b_back)"
+which maintain a doubly-linked list
+of the buffers associated with a particular
+block device, and a
+pair of pointers
+.I "(av_forw, av_back)"
+which generally maintain a doubly-linked list of blocks
+which are ``free,'' that is,
+eligible to be reallocated for another transaction.
+Buffers that have I/O in progress
+or are busy for other purposes do not appear in this list.
+The buffer header
+also contains the device and block number to which the
+buffer refers, and a pointer to the actual storage associated with
+the buffer.
+There is a word count
+which is the negative of the number of words
+to be transferred to or from the buffer;
+there is also an error byte and a residual word
+count used to communicate information
+from an I/O routine to its caller.
+Finally, there is a flag word
+with bits indicating the status of the buffer.
+These flags will be discussed below.
+.PP
+Seven routines constitute
+the most important part of the interface with the
+rest of the system.
+Given a device and block number,
+both
+.I bread
+and
+.I getblk
+return a pointer to a buffer header for the block;
+the difference is that
+.I bread
+is guaranteed to return a buffer actually containing the
+current data for the block,
+while
+.I getblk
+returns a buffer which contains the data in the
+block only if it is already in core (whether it is
+or not is indicated by the
+.I B_DONE
+bit; see below).
+In either case the buffer, and the corresponding
+device block, is made ``busy,''
+so that other processes referring to it
+are obliged to wait until it becomes free.
+.I Getblk
+is used, for example,
+when a block is about to be totally rewritten,
+so that its previous contents are
+not useful;
+still, no other process can be allowed to refer to the block
+until the new data is placed into it.
+.PP
+The
+.I breada
+routine is used to implement read-ahead.
+it is logically similar to
+.I bread,
+but takes as an additional argument the number of
+a block (on the same device) to be read asynchronously
+after the specifically requested block is available.
+.PP
+Given a pointer to a buffer,
+the
+.I brelse
+routine
+makes the buffer again available to other processes.
+It is called, for example, after
+data has been extracted following a
+.I bread.
+There are three subtly-different write routines,
+all of which take a buffer pointer as argument,
+and all of which logically release the buffer for
+use by others and place it on the free list.
+.I Bwrite
+puts the
+buffer on the appropriate device queue,
+waits for the write to be done,
+and sets the user's error flag if required.
+.I Bawrite
+places the buffer on the device's queue, but does not wait
+for completion, so that errors cannot be reflected directly to
+the user.
+.I Bdwrite
+does not start any I/O operation at all,
+but merely marks
+the buffer so that if it happens
+to be grabbed from the free list to contain
+data from some other block, the data in it will
+first be written
+out.
+.PP
+.I Bwrite
+is used when one wants to be sure that
+I/O takes place correctly, and that
+errors are reflected to the proper user;
+it is used, for example, when updating i-nodes.
+.I Bawrite
+is useful when more overlap is desired
+(because no wait is required for I/O to finish)
+but when it is reasonably certain that the
+write is really required.
+.I Bdwrite
+is used when there is doubt that the write is
+needed at the moment.
+For example,
+.I bdwrite
+is called when the last byte of a
+.I write
+system call falls short of the end of a
+block, on the assumption that
+another
+.I write
+will be given soon which will re-use the same block.
+On the other hand,
+as the end of a block is passed,
+.I bawrite
+is called, since probably the block will
+not be accessed again soon and one might as
+well start the writing process as soon as possible.
+.PP
+In any event, notice that the routines
+.I "getblk"
+and
+.I bread
+dedicate the given block exclusively to the
+use of the caller, and make others wait,
+while one of
+.I "brelse, bwrite, bawrite,"
+or
+.I bdwrite
+must eventually be called to free the block for use by others.
+.PP
+As mentioned, each buffer header contains a flag
+word which indicates the status of the buffer.
+Since they provide
+one important channel for information between the drivers and the
+block I/O system, it is important to understand these flags.
+The following names are manifest constants which
+select the associated flag bits.
+.IP B_READ 10
+This bit is set when the buffer is handed to the device strategy routine
+(see below) to indicate a read operation.
+The symbol
+.I B_WRITE
+is defined as 0 and does not define a flag; it is provided
+as a mnemonic convenience to callers of routines like
+.I swap
+which have a separate argument
+which indicates read or write.
+.IP B_DONE 10
+This bit is set
+to 0 when a block is handed to the the device strategy
+routine and is turned on when the operation completes,
+whether normally as the result of an error.
+It is also used as part of the return argument of
+.I getblk
+to indicate if 1 that the returned
+buffer actually contains the data in the requested block.
+.IP B_ERROR 10
+This bit may be set to 1 when
+.I B_DONE
+is set to indicate that an I/O or other error occurred.
+If it is set the
+.I b_error
+byte of the buffer header may contain an error code
+if it is non-zero.
+If
+.I b_error
+is 0 the nature of the error is not specified.
+Actually no driver at present sets
+.I b_error;
+the latter is provided for a future improvement
+whereby a more detailed error-reporting
+scheme may be implemented.
+.IP B_BUSY 10
+This bit indicates that the buffer header is not on
+the free list, i.e. is
+dedicated to someone's exclusive use.
+The buffer still remains attached to the list of
+blocks associated with its device, however.
+When
+.I getblk
+(or
+.I bread,
+which calls it) searches the buffer list
+for a given device and finds the requested
+block with this bit on, it sleeps until the bit
+clears.
+.IP B_PHYS 10
+This bit is set for raw I/O transactions that
+need to allocate the Unibus map on an 11/70.
+.IP B_MAP 10
+This bit is set on buffers that have the Unibus map allocated,
+so that the
+.I iodone
+routine knows to deallocate the map.
+.IP B_WANTED 10
+This flag is used in conjunction with the
+.I B_BUSY
+bit.
+Before sleeping as described
+just above,
+.I getblk
+sets this flag.
+Conversely, when the block is freed and the busy bit
+goes down (in
+.I brelse)
+a
+.I wakeup
+is given for the block header whenever
+.I B_WANTED
+is on.
+This strategem avoids the overhead
+of having to call
+.I wakeup
+every time a buffer is freed on the chance that someone
+might want it.
+.IP B_AGE
+This bit may be set on buffers just before releasing them; if it
+is on,
+the buffer is placed at the head of the free list, rather than at the
+tail.
+It is a performance heuristic
+used when the caller judges that the same block will not soon be used again.
+.IP B_ASYNC 10
+This bit is set by
+.I bawrite
+to indicate to the appropriate device driver
+that the buffer should be released when the
+write has been finished, usually at interrupt time.
+The difference between
+.I bwrite
+and
+.I bawrite
+is that the former starts I/O, waits until it is done, and
+frees the buffer.
+The latter merely sets this bit and starts I/O.
+The bit indicates that
+.I relse
+should be called for the buffer on completion.
+.IP B_DELWRI 10
+This bit is set by
+.I bdwrite
+before releasing the buffer.
+When
+.I getblk,
+while searching for a free block,
+discovers the bit is 1 in a buffer it would otherwise grab,
+it causes the block to be written out before reusing it.
+.SH
+Block Device Drivers
+.PP
+The
+.I bdevsw
+table contains the names of the interface routines
+and that of a table for each block device.
+.PP
+Just as for character devices, block device drivers may supply
+an
+.I open
+and a
+.I close
+routine
+called respectively on each open and on the final close
+of the device.
+Instead of separate read and write routines,
+each block device driver has a
+.I strategy
+routine which is called with a pointer to a buffer
+header as argument.
+As discussed, the buffer header contains
+a read/write flag, the core address,
+the block number, a (negative) word count,
+and the major and minor device number.
+The role of the strategy routine
+is to carry out the operation as requested by the
+information in the buffer header.
+When the transaction is complete the
+.I B_DONE
+(and possibly the
+.I B_ERROR)
+bits should be set.
+Then if the
+.I B_ASYNC
+bit is set,
+.I brelse
+should be called;
+otherwise,
+.I wakeup.
+In cases where the device
+is capable, under error-free operation,
+of transferring fewer words than requested,
+the device's word-count register should be placed
+in the residual count slot of
+the buffer header;
+otherwise, the residual count should be set to 0.
+This particular mechanism is really for the benefit
+of the magtape driver;
+when reading this device
+records shorter than requested are quite normal,
+and the user should be told the actual length of the record.
+.PP
+Although the most usual argument
+to the strategy routines
+is a genuine buffer header allocated as discussed above,
+all that is actually required
+is that the argument be a pointer to a place containing the
+appropriate information.
+For example the
+.I swap
+routine, which manages movement
+of core images to and from the swapping device,
+uses the strategy routine
+for this device.
+Care has to be taken that
+no extraneous bits get turned on in the
+flag word.
+.PP
+The device's table specified by
+.I bdevsw
+has a
+byte to contain an active flag and an error count,
+a pair of links which constitute the
+head of the chain of buffers for the device
+.I "(b_forw, b_back),"
+and a first and last pointer for a device queue.
+Of these things, all are used solely by the device driver
+itself
+except for the buffer-chain pointers.
+Typically the flag encodes the state of the
+device, and is used at a minimum to
+indicate that the device is currently engaged in
+transferring information and no new command should be issued.
+The error count is useful for counting retries
+when errors occur.
+The device queue is used to remember stacked requests;
+in the simplest case it may be maintained as a first-in
+first-out list.
+Since buffers which have been handed over to
+the strategy routines are never
+on the list of free buffers,
+the pointers in the buffer which maintain the free list
+.I "(av_forw, av_back)"
+are also used to contain the pointers
+which maintain the device queues.
+.PP
+A couple of routines
+are provided which are useful to block device drivers.
+.I "iodone(bp)"
+arranges that the buffer to which
+.I bp
+points be released or awakened,
+as appropriate,
+when the
+strategy module has finished with the buffer,
+either normally or after an error.
+(In the latter case the
+.I B_ERROR
+bit has presumably been set.)
+.PP
+The routine
+.I "geterror(bp)"
+can be used to examine the error bit in a buffer header
+and arrange that any error indication found therein is
+reflected to the user.
+It may be called only in the non-interrupt
+part of a driver when I/O has completed
+.I (B_DONE
+has been set).
+.SH
+Raw Block-device I/O
+.PP
+A scheme has been set up whereby block device drivers may
+provide the ability to transfer information
+directly between the user's core image and the device
+without the use of buffers and in blocks as large as
+the caller requests.
+The method involves setting up a character-type special file
+corresponding to the raw device
+and providing
+.I read
+and
+.I write
+routines which set up what is usually a private,
+non-shared buffer header with the appropriate information
+and call the device's strategy routine.
+If desired, separate
+.I open
+and
+.I close
+routines may be provided but this is usually unnecessary.
+A special-function routine might come in handy, especially for
+magtape.
+.PP
+A great deal of work has to be done to generate the
+``appropriate information''
+to put in the argument buffer for
+the strategy module;
+the worst part is to map relocated user addresses to physical addresses.
+Most of this work is done by
+.I "physio(strat, bp, dev, rw)
+whose arguments are the name of the
+strategy routine
+.I strat,
+the buffer pointer
+.I bp,
+the device number
+.I dev,
+and a read-write flag
+.I rw
+whose value is either
+.I B_READ
+or
+.I B_WRITE.
+.I Physio
+makes sure that the user's base address and count are
+even (because most devices work in words)
+and that the core area affected is contiguous
+in physical space;
+it delays until the buffer is not busy, and makes it
+busy while the operation is in progress;
+and it sets up user error return information.
diff --git a/doc/7thEdMan/vol2/learn.bun b/doc/7thEdMan/vol2/learn.bun
new file mode 100644 (file)
index 0000000..71fa44f
--- /dev/null
@@ -0,0 +1,1389 @@
+# To unbundle, run this file
+echo p0
+sed 's/.//' >p0 <<'//GO.SYSIN DD p0'
+-.RP
+-.TM "79-1274-xx 79-1273-yy" 39199 39199-11
+-....ND June 18, 1976
+-....TM "76-1274-6 76-1273-5" 39199 39199-11
+-.TL
+-LEARN \(em Computer-Aided Instruction on UNIX
+-.br
+-(Second Edition)
+-.AU "MH 2C-518" 6021
+-Brian W. Kernighan
+-.AU "MH 2C-569" 6377
+-Michael E. Lesk
+-.AI
+-.MH
+-.OK
+-CAI
+-.AB
+-.PP
+-This paper describes the
+-second version of the
+-.I
+-learn
+-.R
+-program for interpreting CAI
+-scripts on
+-the
+-.UX 
+-operating system,
+-and a set of scripts that provide a computerized introduction
+-to the system.
+-.PP
+-Six current scripts cover basic commands and file
+-handling, the editor, additional file handling commands, the
+-.I
+-eqn
+-.R
+-program for mathematical
+-typing,
+-the ``\-ms'' package of formatting macros,
+-and an introduction to the C programming language.
+-These scripts now include a total of
+-about 530 lessons.
+-.PP
+-Many users from a wide variety of backgrounds have used
+-.I learn
+-to acquire basic UNIX skills.
+-Most usage involves the first two scripts,
+-an introduction to
+-.UX
+-files and commands, and
+-the
+-.UX
+-editor.
+-.PP
+-The second version of
+-.I learn
+-is about four times faster than the previous one
+-in CPU utilization,
+-and much faster in perceived time
+-because of better overlap of computing and printing.
+-It also requires less file space than the first version.
+-Many of the lessons have been revised;
+-new material has been added to reflect changes
+-and enhancements in 
+-.UX
+-itself.
+-Script-writing is also easier
+-because of revisions to the script language.
+-.AE
+-.CS 11 2 13 4 0 0
+//GO.SYSIN DD p0
+echo p2
+sed 's/.//' >p2 <<'//GO.SYSIN DD p2'
+-.NH
+-Educational Assumptions and Design.
+-.PP
+-First, the way to teach people how to do something
+-is to have them do it.  Scripts should
+-not contain long pieces of explanation; they should
+-instead frequently ask the student to do some task.
+-So teaching is always by example: the typical
+-script fragment shows a small example of some
+-technique and then asks the
+-user to either repeat that example or
+-produce a variation on it.
+-All are intended to be easy enough that most students will get most questions
+-right, reinforcing the desired behavior.
+-.PP
+-Most lessons fall into one of three types.
+-The simplest presents a lesson and asks for a yes or no
+-answer to a question.
+-The student is given a chance to experiment before replying.
+-The script checks for the correct reply.
+-Problems of this form are sparingly used.
+-.PP
+-The second type asks for a word or number as an answer.
+-For example a lesson on files might say
+-.IP
+-.I
+-How many files are there in the current directory?
+-Type ``answer N'', where N is the number of files.
+-.R
+-.LP
+-The student is expected to respond (perhaps after experimenting) with
+-.LP
+-.I
+-      answer 17
+-.R
+-.LP
+-or whatever.
+-Surprisingly often, however, the idea of a substitutable argument
+-(i.e., replacing
+-.I
+-N
+-.R
+-by
+-17)
+-is difficult for non-programmer students,
+-so the first few such lessons need real care.
+-.PP
+-The third type of lesson is open-ended \(em
+-a task is set for the student,
+-appropriate parts of the input or output are monitored,
+-and the student types 
+-.ul
+-ready
+-when the task is done.
+-Figure 1 shows a sample dialog that illustrates the last of these, using two
+-lessons about the
+-.I cat
+-(concatenate, i.e., print) command taken
+-from early in the script that teaches
+-file handling.
+-Most
+-.I learn
+-lessons are of this form.
+-.KF
+-.TS
+-box, center;
+-c.
+-T{
+-Figure 1:  Sample dialog from basic files script
+-.sp
+-(Student responses
+-in italics; `$' is the prompt)
+-.nf
+-.sp
+-A file can be printed on your terminal
+-by using the "cat" command.  Just say
+-"cat file" where "file" is the file name.
+-For example, there is a file named
+-"food" in this directory.  List it
+-by saying "cat food"; then type "ready".
+-$ \fIcat food\fR
+-  this is the file
+-  named food.
+-$ \fIready\fR
+-
+-Good.  Lesson 3.3a (1)
+-
+-Of course, you can print any file with "cat".
+-In particular, it is common to first use
+-"ls" to find the name of a file and then "cat"
+-to print it.  Note the difference between
+-"ls", which tells you the name of the file,
+-and "cat", which tells you the contents.
+-One file in the current directory is named for
+-a President.  Print the file, then type "ready".
+-$ \fIcat President\fR
+-cat: can't open President
+-$ \fIready\fR
+-
+-Sorry, that's not right.  Do you want to try again? \fIyes\fR
+-Try the problem again.
+-$ \fIls\fR
+-\&.ocopy
+-X1
+-roosevelt
+-$ \fIcat roosevelt\fR
+-  this file is named roosevelt
+-  and contains three lines of
+-  text.
+-$ \fIready\fR
+-
+-Good.  Lesson 3.3b (0)
+-
+-The "cat" command can also print several files
+-at once.  In fact, it is named "cat" as an abbreviation
+-for "concatenate"....
+-.fi
+-T}
+-.TE
+-.sp
+-.KE
+-.PP
+-After each correct response the computer congratulates
+-the student and indicates the lesson number that
+-has just been completed, permitting the student
+-to restart the script after that lesson.
+-If the answer is wrong, the student
+-is offered a chance to repeat the lesson.
+-The ``speed'' rating of the student (explained in
+-section 5) is given after the lesson number when the lesson is completed successfully; it is
+-printed only for the aid of script authors checking
+-out possible errors in the lessons.
+-.br
+-.PP
+-It is assumed that there is no foolproof way
+-to determine if the student truly ``understands''
+-what he or she is doing;
+-accordingly,
+-the current
+-.I
+-learn
+-.R
+-scripts
+-only measure performance, not comprehension.
+-If the student can perform a given task, that is deemed to be ``learning.''
+-.[
+-skinner teaching 1961
+-.]
+-.PP
+-The main point of using the computer is that what the student
+-does is checked for correctness immediately.
+-Unlike many CAI scripts, however, these scripts provide
+-few facilities for dealing with wrong answers.
+-In practice, if most of the answers are not right the script is
+-a failure; the universal solution to student error is to provide
+-a new, easier script.
+-Anticipating possible wrong answers is an endless job, and it is really
+-easier as well as better to provide a simpler script.
+-.PP
+-Along with this goes the assumption that
+-anything can be taught to anybody if it can
+-be broken into sufficiently small pieces.  Anything
+-not absorbed in a single chunk is just subdivided.
+-.PP
+-To avoid boring the faster students,
+-however,
+-an effort is made in the files and editor scripts to provide
+-three tracks of different difficulty.
+-The fastest sequence of lessons
+-is aimed at roughly the bulk and speed of a typical tutorial
+-manual and should be adequate for review and for
+-well-prepared students.
+-The next track is intended for most users and is roughly
+-twice as long.  Typically, for example, the fast track
+-might present an idea and ask for a variation on the
+-example shown; the normal track will first
+-ask the student to repeat the example that was shown
+-before attempting a variation.
+-The third and slowest track, which is often
+-three or four times the length of the fast track,
+-is intended to be adequate for anyone.
+-(The lessons of Figure 1 are from the third track.)
+-The multiple tracks also mean that a student repeating a course is unlikely
+-to hit the same series of lessons; this makes it profitable for a shaky
+-user to back up and try again, and many students have done so.
+-.PP
+-The tracks are not completely distinct, however.
+-Depending on the number of correct answers the student has given for the
+-last few lessons, the program may switch tracks.
+-The driver is actually capable of following
+-an arbitrary directed graph of lesson sequences, as discussed in section 5.
+-Some more structured arrangement, however, is used in all current scripts
+-to aid the script writer in organizing the material into lessons.
+-It is sufficiently difficult
+-to write lessons
+-that the three-track theory
+-is not followed very closely
+-except in
+-the files and editor scripts.
+-Accordingly,
+-in some cases, the fast track is produced merely by skipping
+-lessons from the slower track.
+-In others, there is essentially only one track.
+-.PP
+-The main reason for using the
+-.I
+-learn
+-.R
+-program rather than
+-simply writing the same material as a workbook
+-is not the selection of tracks, but
+-actual hands-on experience.
+-Learning by doing
+-is much more effective
+-than pencil and paper exercises.
+-.PP
+-.I Learn
+-also provides a mechanical check on performance.
+-The first version in fact would not let
+-the student proceed unless it
+-received correct answers to the questions
+-it set and it would not tell a student the right answer.
+-This somewhat Draconian approach has been moderated
+-in version 2.
+-Lessons are sometimes badly worded or even just plain wrong;
+-in such cases,
+-the student has no recourse.
+-But if a student is simply unable to complete one lesson,
+-that should not prevent access to the rest.
+-Accordingly, the current version of
+-.I learn
+-allows the student to skip
+-a lesson that he cannot pass;
+-a ``no'' answer to the ``Do you want to try again?''
+-question in Figure 1 will pass to the next lesson.
+-It is still true that 
+-.I learn
+-will not tell the student the right answer.
+-.PP
+-Of course, there are valid objections to the
+-assumptions above.
+-In particular, some students may object to
+-not understanding
+-what they are doing;
+-and the procedure of smashing everything into small pieces may provoke
+-the retort ``you can't cross a ditch in two jumps.''
+-Since writing CAI scripts is considerably
+-more tedious than ordinary manuals, however, it is safe
+-to assume that there will always be alternatives to the
+-scripts as a way of learning.
+-In fact, for a reference manual of 3 or 4 pages it would
+-not be surprising to have a tutorial manual of 20 pages
+-and a (multi-track) script of 100 pages.  Thus the reference manual
+-will exist long before the scripts.
+//GO.SYSIN DD p2
+echo p3
+sed 's/.//' >p3 <<'//GO.SYSIN DD p3'
+-.NH
+-Scripts.
+-.PP
+-As mentioned above, the present scripts try
+-at most
+-to follow a three-track theory.  Thus little
+-of the potential complexity of the possible directed graph
+-is employed, since
+-care must be taken in lesson construction to see
+-that every necessary fact is presented in
+-every possible path through the units.  In addition,
+-it is desirable that every unit have alternate successors
+-to deal with student errors.
+-.PP
+-In most existing courses, the first few lessons
+-are devoted to checking prerequisites.  For example,
+-before the student is allowed to proceed through the editor
+-script the script verifies that the student understands files
+-and is able to type.
+-It is felt that the sooner lack of student preparation
+-is detected, the easier it will be on the student.
+-Anyone proceeding through the scripts
+-should be getting mostly correct answers; otherwise, the
+-system will be unsatisfactory both because the wrong
+-habits are being learned and because the
+-scripts make little effort to deal with wrong answers.
+-Unprepared students should not be encouraged
+-to continue with scripts.
+-.PP
+-There are some preliminary items which the student must
+-know before any scripts can be tried.  In particular,
+-the student must know how to connect to
+-a
+-.UX
+-system,
+-set the terminal properly,
+-log in,
+-and execute simple commands (e.g.,
+-.ul
+-learn
+-itself).
+-In addition, the character erase and line kill conventions
+-(# and @) should be known.
+-It is hard to see how this much could be taught by
+-computer-aided instruction, since a student who
+-does not know these basic skills will not be able
+-to run the learning program.
+-A brief description on paper is provided (see Appendix A), although
+-assistance will be needed for the first few
+-minutes.  This assistance, however, need not be highly skilled.
+-.PP
+-The first script in the current set deals with files.  It assumes
+-the basic knowledge above and teaches the student about
+-the
+-.I ls ,
+-.I cat ,
+-.I mv ,
+-.I rm ,
+-.I cp
+-and
+-.I diff
+-commands.
+-.tr ~
+-It also deals with the abbreviation characters *, ?, and [\ ]
+-in file names.
+-It does not cover pipes or I/O redirection,
+-nor does it present the many options
+-on the
+-.ul
+-ls
+-command.
+-.PP
+-This script contains 31 lessons
+-in the fast track;
+-two are
+-intended as prerequisite checks,
+-seven are review exercises.
+-There are a total of 75 lessons in all three tracks,
+-and the instructional passages typed at the student
+-to begin each lesson total 4,476 words.  The average
+-lesson thus begins with a 60-word message.
+-In general, the fast track lessons have somewhat longer
+-introductions, and the slow tracks somewhat shorter ones.
+-The longest message is 144 words and the shortest 14.
+-.PP
+-The second script trains students in the use
+-of the
+-.UX
+-context editor
+-.I ed ,
+-a sophisticated editor
+-using regular expressions for searching.
+-.[
+-ritchie thompson unix  seventh edition 1978
+-%O See section \f2ed\f1 (I).
+-.]
+-All editor
+-features except encryption, mark names and `;' in addressing
+-are covered.
+-The fast track contains 2 prerequisite checks,
+-93 lessons, and a review lesson.
+-It is supplemented by 146 additional lessons in other tracks.
+-.PP
+-A comparison of sizes may be of interest.  The
+-.ul
+-ed
+-description
+-in the reference manual is 2,572 words long.  The
+-.ul
+-ed
+-tutorial
+-.[
+-kernighan editor tutorial 1974
+-.]
+-is 6,138 words long.  
+-The fast track through
+-the
+-.ul
+-ed
+-script is 7,407 words of explanatory messages, and the
+-total
+-.ul
+-ed
+-script, 242 lessons, 
+-has 15,615 words.
+-The average
+-.ul
+-ed
+-lesson is thus also about 60 words; the largest
+-is 171 words and the smallest 10.
+-The
+-original
+-.ul
+-ed
+-script represents about three man-weeks of effort.
+-.PP
+-The advanced file handling script deals with
+-.ul
+-ls
+-options,
+-I/O diversion, pipes, and supporting programs like
+-.I pr ,
+-.I wc ,
+-.I tail ,
+-.I spell
+-and
+-.I grep .
+-(The basic file handling script is a prerequisite.)
+-It is not as refined as the first two scripts;
+-this is reflected at least partly in the fact that
+-it provides much less of a full three-track sequence
+-than they do.
+-On the other hand,
+-since it is perceived as ``advanced,''
+-it is hoped that the student will have somewhat
+-more sophistication
+-and be better able to cope with it at a reasonably
+-high level of performance.
+-.PP
+-A fourth script covers the
+-.ul
+-eqn
+-language for typing mathematics.
+-This script must be run on a terminal capable of printing
+-mathematics, for instance the DASI 300 and similar Diablo-based
+-terminals, or the nearly extinct Model 37 teletype.
+-Again, this script is relatively short of tracks:
+-of 76 lessons, only 17 are in the second track and 2
+-in the third track.
+-Most of these provide additional practice for students
+-who are having trouble in the first track.
+-.PP
+-The
+-.I \-ms
+-script for formatting macros
+-is a short one-track only script.
+-The macro package it describes is no longer the standard,
+-so this script will undoubtedly be superseded
+-in the future.
+-Furthermore, the linear style of a single learn script is somewhat
+-inappropriate for the macros, since the macro package is composed of many
+-independent features, and few users need all of them.
+-It would be better to have a selection of short lesson
+-sequences dealing with the features independently.
+-.PP
+-The script on C is in a state of transition.
+-It was originally designed to follow
+-a tutorial on C,
+-but that document has since become obsolete.
+-The current script has been partially converted
+-to follow the order of presentation in
+-.ul
+-The C Programming Language,
+-.[
+-ritchie kernighan programming 1978 prentice hall
+-.]
+-but this job is not complete.
+-The C script was never intended to teach C;
+-rather it is supposed to be a series of exercises
+-for which the computer provides checking and
+-(upon success) a suggested solution.
+-.PP
+-This combination of scripts covers much of the material which any
+-.UX
+-user
+-will need to know
+-to make effective use of the system.
+-With enlargement of the advanced files
+-course to include more on the command interpreter, there
+-will be a relatively complete introduction to
+-.UX
+-available via
+-.ul
+-learn.
+-Although we make no pretense that 
+-.ul
+-learn
+-will replace other instructional materials,
+-it should provide a useful supplement to existing tutorials and reference manuals.
+//GO.SYSIN DD p3
+echo p4
+sed 's/.//' >p4 <<'//GO.SYSIN DD p4'
+-.NH
+-Experience with Students.
+-.PP
+-.I
+-Learn
+-.R
+-has been installed on
+-many different 
+-.UX
+-systems.
+-Most of the usage is on the first two scripts, so these
+-are more thoroughly debugged and polished.
+-As a (random) sample of user experience,
+-the
+-.I learn
+-program has been used at Bell Labs at Indian Hill
+-for 10,500 lessons in a four month period.
+-About 3600 of these are in the files script,
+-4100 in the editor,
+-and 1400 in advanced files.
+-The passing rate is about 80%,
+-that is, about 4 lessons are passed for every one
+-failed.
+-There have been 86 distinct users of the files script,
+-and 58 of the editor.
+-On our system at Murray Hill, there have been nearly 2000 lessons
+-over two weeks that include
+-Christmas and New Year.
+-Users have ranged in age from six up.
+-.PP
+-It is difficult to characterize typical sessions with the
+-scripts;
+-many instances exist of someone doing one or two lessons
+-and then logging out, as do instances of someone pausing
+-in a script for twenty minutes or more.
+-In the earlier version of
+-.I learn ,
+-the average session in the files course took 32 minutes and covered
+-23 lessons.
+-The distribution is quite
+-broad and skewed, however; the longest session was
+-130 minutes and there were five sessions shorter than
+-five minutes.
+-The average lesson took about 80 seconds.
+-These numbers are roughly typical for non-programmers;
+-a
+-.UX
+-expert can do the scripts at approximately 30 seconds
+-per lesson, most of which is the system printing.
+-.PP
+-At present working through a section of the middle of the files
+-script took about 1.4 seconds of processor time per lesson,
+-and a system expert typing quickly took 15 seconds of real time per lesson.
+-A novice would probably take at least a minute.
+-Thus a UNIX system could support ten students working simultaneously
+-with some spare capacity.
+//GO.SYSIN DD p4
+echo p5
+sed 's/.//' >p5 <<'//GO.SYSIN DD p5'
+-.NH
+-The Script Interpreter.
+-.PP
+-The
+-.I
+-learn
+-.R
+-program itself merely interprets scripts.  It provides
+-facilities for the script writer to capture student
+-responses and their effects, and simplifies the job
+-of passing control to and recovering control from the student.
+-This section describes the operation and
+-usage of the driver program,
+-and indicates what is
+-required to produce a new script.
+-Readers only interested in
+-the existing scripts may skip this section.
+-.PP
+-The file structure used by
+-.I learn
+-is shown in Figure 2.
+-There is one parent directory (named \f2lib\f1\^) containing the script data.
+-Within this directory are subdirectories, one for each
+-subject in which a course is available,
+-one for logging (named
+-.I log ),
+-and one in which user sub-directories
+-are created (named
+-.I play ).
+-The subject directory contains master copies of all lessons,
+-plus any supporting material for that subject.
+-In a given subdirectory,
+-each lesson is a single text file.
+-Lessons are usually named systematically;
+-the file that contains lesson
+-.I n
+-is called
+-.I Ln .
+-.br
+-.KF
+-.sp
+-.TS
+-center, box;
+-c s s s
+-l l l l.
+-Figure 2:  Directory structure for \fIlearn\fR
+-.sp
+-.nf
+-lib
+-.if t .sp .5
+-      play
+-              student1
+-                      files for student1...
+-              student2
+-                      files for student2...
+-.if t .sp .5
+-      files
+-              L0.1a   lessons for files course
+-              L0.1b
+-              ...
+-.if t .sp .5
+-      editor
+-              ...
+-.if t .sp .5
+-      (other courses)
+-.if t .sp .5
+-      log
+-.TE
+-.sp
+-.KE
+-.PP
+-When
+-.I
+-learn
+-.R
+-is executed, it makes a private directory
+-for the user to work in,
+-within the
+-.I
+-learn
+-.R
+-portion of the file system.
+-A fresh copy of all the files used in each lesson
+-(mostly data for the student to operate upon) is made each
+-time a student starts a lesson,
+-so the script writer may assume that everything
+-is reinitialized each time a lesson is entered.
+-The student directory is deleted after each session; any permanent records
+-must be kept elsewhere.
+-.PP
+-The script writer must provide certain basic items
+-in each
+-lesson:
+-.IP (1)
+-the text of the lesson;
+-.IP (2)
+-the set-up commands to be executed before the user gets control;
+-.IP (3)
+-the data, if any, which the user is supposed to edit, transform, or otherwise
+-process;
+-.IP (4)
+-the evaluating commands to be executed after the user
+-has finished the lesson, to decide whether the answer is right;
+-and
+-.IP (5)
+-a list of possible successor lessons.
+-.LP
+-.I
+-Learn
+-.R
+-tries to minimize the work
+-of bookkeeping and installation, so
+-that most of the effort involved in
+-script production is in planning lessons,
+-writing tutorial paragraphs,
+-and coding tests of student performance.
+-.PP
+-The basic sequence of events is
+-as follows.
+-First,
+-.I learn
+-creates the working directory.
+-Then, for each lesson,
+-.I learn
+-reads the script for the lesson and processes
+-it a line at a time.
+-The lines in the script are:
+-(1) commands to the script interpreter
+-to print something, to create a files,
+-to test something, etc.;
+-(2) text to be printed or put in a file;
+-(3) other lines, which are sent to
+-the shell to be executed.
+-One line in each lesson turns control over
+-to the user;
+-the user can run any 
+-.UX 
+-commands.
+-The user mode terminates when the user
+-types 
+-.I yes ,
+-.I no ,
+-.I ready ,
+-or
+-.I answer .
+-At this point, the user's work is tested;
+-if the lesson is passed,
+-a new lesson is selected, and if not
+-the old one is repeated.
+-.PP
+-Let us illustrate this with the script
+-for the second lesson of Figure 1;
+-this is shown in Figure 3.
+-.KF
+-.sp
+-.TS
+-center, box;
+-c.
+-T{
+-Figure 3:  Sample Lesson
+-.sp
+-.nf
+-#print
+-Of course, you can print any file with "cat".
+-In particular, it is common to first use
+-"ls" to find the name of a file and then "cat"
+-to print it.  Note the difference between
+-"ls", which tells you the name of the files,
+-and "cat", which tells you the contents.
+-One file in the current directory is named for
+-a President.  Print the file, then type "ready".
+-#create roosevelt
+-  this file is named roosevelt
+-  and contains three lines of
+-  text.
+-#copyout
+-#user
+-#uncopyout
+-tail \-3 .ocopy >X1
+-#cmp X1 roosevelt
+-#log
+-#next
+-3.2b 2
+-.fi
+-T}
+-.TE
+-.sp
+-.KE
+-.LP
+-Lines which begin with
+-# are commands to the
+-.I  learn 
+-script interpreter.
+-For example,
+-.LP
+-.ul
+-      #print
+-.LP
+-causes printing of any text that follows,
+-up to the next line that begins with a sharp.
+-.LP
+-.ul
+-      #print file
+-.LP
+-prints the contents of
+-.I file ;
+-it
+-is the same as
+-.ul
+-cat file 
+-but has
+-less overhead.
+-Both forms of
+-.I #print
+-have the added property that if a lesson is failed,
+-the
+-.ul
+-#print
+-will not be executed the second time through;
+-this avoids annoying the student by repeating the preamble
+-to a lesson.
+-.LP
+-.ul
+-      #create filename
+-.LP
+-creates a file of the specified name,
+-and copies any subsequent text up to a
+-# to the file.
+-This is used for creating and initializing working files
+-and reference data for the lessons.
+-.LP
+-.ul
+-      #user
+-.LP
+-gives control to the student;
+-each line he or she types is passed to the shell
+-for execution.
+-The
+-.I #user
+-mode
+-is terminated when the student types one of
+-.I yes ,
+-.I no ,
+-.I ready 
+-or
+-.I answer .
+-At that time, the driver
+-resumes interpretation of the script.
+-.LP
+-.ul
+-      #copyin
+-.br
+-.ul
+-      #uncopyin
+-.LP
+-Anything the student types between these
+-commands is copied onto a file
+-called
+-.ul
+-\&.copy.
+-This lets the script writer interrogate the student's
+-responses upon regaining control.
+-.LP
+-.ul
+-      #copyout
+-.br
+-.ul
+-      #uncopyout
+-.LP
+-Between these commands, any material typed at the student
+-by any program
+-is copied to the file
+-.ul
+-\&.ocopy.
+-This lets the script writer interrogate the
+-effect of what the student typed, 
+-which true believers in the performance theory of learning
+-usually
+-prefer to the student's actual input.
+-.LP
+-.ul
+-      #pipe
+-.br
+-.ul
+-      #unpipe
+-.LP
+-Normally the student input and the script commands
+-are fed to the
+-.UX
+-command interpreter (the ``shell'') one line at a time. This won't do
+-if, for example, a sequence of editor commands
+-is provided,
+-since the input to the editor must be handed to the editor,
+-not to the shell.
+-Accordingly, the material between 
+-.ul
+-#pipe
+-and
+-.ul
+-#unpipe
+-commands
+-is fed
+-continuously through a pipe so that such sequences
+-work.
+-If
+-.ul
+-copyout
+-is also desired
+-the
+-.ul
+-copyout
+-brackets must include
+-the
+-.ul
+-pipe
+-brackets.
+-.PP
+-There are several commands for setting status
+-after the student has attempted the lesson.
+-.LP
+-.ul
+-      #cmp file1 file2
+-.LP
+-is an in-line implementation of
+-.I cmp ,
+-which compares two files for identity.
+-.LP
+-.ul
+-      #match stuff
+-.LP
+-The last line of the student's input
+-is compared to
+-.I stuff ,
+-and the success or fail status is set
+-according to it.
+-Extraneous things like the word
+-.I answer
+-are stripped before the comparison is made.
+-There may be several 
+-.I #match
+-lines;
+-this provides a convenient mechanism for handling multiple
+-``right'' answers.
+-Any text up to a
+-# on subsequent lines after a successful
+-.I #match
+-is printed; 
+-this is illustrated in Figure 4, another sample lesson.
+-.br
+-.KF
+-.sp
+-.TS
+-center, box;
+-c.
+-T{
+-Figure 4:  Another Sample Lesson
+-.sp
+-.nf
+-#print
+-What command will move the current line
+-to the end of the file?  Type 
+-"answer COMMAND", where COMMAND is the command.
+-#copyin
+-#user
+-#uncopyin
+-#match m$
+-#match .m$
+-"m$" is easier.
+-#log
+-#next
+-63.1d 10
+-T}
+-.TE
+-.sp
+-.KE
+-.LP
+-.ul
+-      #bad stuff
+-.LP
+-This is similar to
+-.I #match ,
+-except that it corresponds to specific failure answers;
+-this can be used to produce hints for particular wrong answers
+-that have been anticipated by the script writer.
+-.LP
+-.ul
+-      #succeed
+-.br
+-.ul
+-      #fail
+-.LP
+-print a message
+-upon success or failure
+-(as determined by some previous mechanism).
+-.PP
+-When the student types
+-one of the ``commands''
+-.I yes ,
+-.I no ,
+-.I ready ,
+-or
+-.I answer ,
+-the driver terminates the
+-.I #user
+-command,
+-and evaluation of the student's work can begin.
+-This can be done either by
+-the built-in commands above, such as
+-.I #match
+-and
+-.I #cmp ,
+-or by status returned by normal
+-.UX 
+-commands, typically
+-.I grep
+-and
+-.I test .
+-The last command
+-should return status true
+-(0) if the task was done successfully and
+-false (non-zero) otherwise;
+-this status return tells the driver
+-whether or not the student
+-has successfully passed the lesson.
+-.PP
+-Performance can be logged:
+-.LP
+-.ul
+-      #log file
+-.LP
+-writes the date, lesson, user name and speed rating, and
+-a success/failure indication on
+-.ul
+-file.
+-The command
+-.LP
+-.ul
+-      #log
+-.LP
+-by itself writes the logging information
+-in the logging directory
+-within the
+-.I learn
+-hierarchy,
+-and is the normal form.
+-.LP
+-.ul
+-      #next
+-.LP
+-is followed by a few lines, each with a successor
+-lesson name and an optional speed rating on it.
+-A typical set might read
+-.LP
+-.nf
+-      25.1a   10
+-      25.2a   5
+-      25.3a   2
+-.fi
+-.LP
+-indicating that unit 25.1a is a suitable follow-on lesson
+-for students with
+-a speed rating of 10 units,
+-25.2a for student with speed near 5,
+-and 25.3a for speed near 2.
+-Speed ratings are maintained for
+-each session with a student; the
+-rating is increased by one each tiee
+-the student gets a lesson right and decreased
+-by four each
+-time the student gets a lesson wrong.
+-Thus the driver tries to maintain a devel such
+-that the users get 80% right answers.
+-The maximum rating is limited to 10 afd the minimum to 0.
+-The initial rating is zero unless the studeft
+-specifies a differeft rating when starting
+-a session.
+-.PP
+-If the student passes a lesson,
+-a new lesson is sedected and the process repeats.
+-If the student fails, a false status is returned
+-and the program
+-reverts to the previous lesson and tries
+-another alternative.
+-If it can not find another alternative, it skips forward
+-a lesson.
+-.I bye ,
+-bye,
+-which causes a graceful exit
+-from the 
+-.ul
+-learn
+-system.  Hanging up is the usual novice's way out.
+-.PP
+-The lessons may form an arbitrary directed graph,
+-although the present program imposes a limitation on cycles in that
+-it will not present a lesson twice in the
+-same session.
+-If the student is unable to answer one of the exercises
+-correctly, the driver searches for a previous lesson
+-with a set of alternatives as successors
+-(following the
+-.I #next
+-line).
+-From the previous lesson with alternatives one route was taken
+-earlier; the program simply tries a different one.
+-.PP
+-It is perfectly possible
+-to write sophisticated scripts that evaluate
+-the student's speed of response, or try to estimate the
+-elegance of the answer, or provide detailed
+-analysis of wrong answers.
+-Lesson writing is so tedious already, however, that most
+-of these abilities are likely to go unused.
+-.PP
+-The driver program depends heavily on features
+-of
+-.UX
+-that are not available on many other operating systems.
+-These include
+-the ease of manipulating files and directories,
+-file redirection,
+-the ability to use the command interpreter
+-as just another program (even in a pipeline),
+-command status testing and branching,
+-the ability to catch signals like interrupts,
+-and of course
+-the pipeline mechanism itself.
+-Although some parts of 
+-.ul
+-learn
+-might be transferable to other systems,
+-some generality will probably be lost.
+-.PP
+-A bit of history:
+-The first version of
+-.I learn
+-had fewer built-in words
+-in the driver program,
+-and made more use of the
+-facilities of
+-.UX .
+-For example,
+-file comparison was done by creating a
+-.I cmp
+-process,
+-rather than comparing the two files within
+-.I learn .
+-Lessons were not stored as text files,
+-but as archives.
+-There was no concept of the in-line document;
+-even 
+-.I #print
+-had to be followed by a file name.
+-Thus the initialization for each lesson
+-was to extract the archive into the working directory
+-(typically 4-8 files),
+-then 
+-.I #print
+-the lesson text.
+-.PP
+-The combination of such things made
+-.I learn
+-slower.
+-The new version is about 4 or 5 times faster.
+-Furthermore, it appears even faster to the user
+-because in a typical lesson,
+-the printing of the message comes first,
+-and file setup with
+-.I #create
+-can be overlapped with the printng,
+-so that when the program
+-finishes printing,
+-it is really ready for the user
+-to type at it.
+-.PP
+-It is also a great advantage to the script maintainer
+-that lessons are now just ordinary text files.
+-They can be edited without any difficulty,
+-and  
+-.UX
+-text manipulation tools can be applied
+-to them.
+-The result has been that
+-there is much less resistance
+-to going in and fixing substandard lessons.
+//GO.SYSIN DD p5
+echo p6
+sed 's/.//' >p6 <<'//GO.SYSIN DD p6'
+-.NH
+-Conclusions
+-.PP
+-The following observations can be made about
+-secretaries, typists, and
+-other non-programmers who have used
+-.I learn :
+-.IP (a)
+-A novice must have assistance with the mechanics
+-of communicating with the computer to get through to
+-the first lesson or two;
+-once the first few lessons are passed people can proceed
+-on their own.
+-.IP (b)
+-The terminology used in the first few lessons
+-is obscure to those inexperienced with computers.
+-It would help if there were a low level
+-reference card for
+-.UX
+-to supplement the existing
+-programmer oriented bulky manual and bulky reference card.
+-.IP (c)
+-The concept of ``substitutable argument'' is hard
+-to grasp, and requires help.
+-.IP (d)
+-They enjoy the system for the most part.
+-Motivation matters a great deal, however.
+-.LP
+-It takes an hour or two for a novice to get through
+-the script on file handling.
+-The total time for a reasonably intelligent and motivated novice to proceed from ignorance
+-to a reasonable ability to create new files and manipulate old ones
+-seems to be a few days, with perhaps half of each day
+-spent on the machine.
+-.PP
+-The normal way of proceeding has been to have students in the same
+-room with someone who knows
+-.UX
+-and the scripts.
+-Thus the student is not brought to a halt by
+-difficult questions.  The burden on the counselor, however,
+-is much lower than that on a teacher of a course.
+-Ideally, the students should be encouraged to proceed with instruction
+-immediately prior to their actual use of the computer.
+-They should exercise the scripts on the same computer and the same
+-kind of terminal that they will later use
+-for their real work, and
+-their first few jobs for the computer should be
+-relatively easy ones.
+-Also, both training and initial work should take place on days
+-when the
+-.UX
+-hardware and software
+-are working reliably.
+-Rarely is all of this possible, but the closer one comes the better
+-the result.
+-For example, if it is known that the hardware is shaky one day, it is better
+-to attempt to reschedule training for another one.  Students are very
+-frustrated by machine downtime; when nothing is happening, it takes
+-some sophistication and experience to distinguish
+-an infinite loop, a slow but functioning program,
+-a program waiting for the user, and a broken machine.*
+-.FS
+-* We have even known an expert programmer to decide the computer
+-was broken when he had simply left his terminal in local mode.
+-Novices have great difficulties with such problems.
+-.FE
+-.PP
+-One disadvantage
+-of training with
+-.I
+-learn
+-.R
+-is that students come to depend
+-completely on the CAI system, and do not try
+-to read manuals or use other learning aids.
+-This is unfortunate, not only because of the increased
+-demands for completeness and accuracy of the
+-scripts, but because the scripts do not cover all of
+-the
+-.UX
+-system.
+-New users should have manuals (appropriate for their level) and
+-read them; the scripts ought to be altered
+-to recommend suitable documents and urge
+-students to read them.
+-.PP
+-There are several other difficulties which are clearly evident.
+-From the student's viewpoint,
+-the most serious is that
+-lessons still crop up which simply can't be passed.
+-Sometimes this is due to poor explanations,
+-but just as often it is some error in the lesson itself
+-\(em a botched setup, a missing file,
+-an invalid test for correctness,
+-or some system facility that doesn't work on the local
+-system in the same way it did on the development system.
+-It takes knowledge and a certain healthy arrogance on the part of the user to recognize
+-that the fault is not his or hers,
+-but the script writer's.
+-Permitting the student to get on with the next lesson
+-regardless does alleviate this somewhat,
+-and the logging facilities make it easy
+-to watch for lessons that no one
+-can pass,
+-but it is still a problem.
+-.PP
+-The biggest problem with the previous
+-.I learn
+-was speed (or lack thereof) \(em
+-it was often excruciatingly slow
+-and made a significant drain on the system.
+-The current version so far does not seem
+-to have that difficulty,
+-although some scripts,
+-notably
+-.I eqn ,
+-are intrinsically slow.
+-.I eqn ,
+-for example,
+-must do a lot of work even to print its introductions,
+-let alone check the student responses,
+-but delay is perceptible in all scripts
+-from time to time.
+-.PP
+-Another potential problem is that it is possible
+-to break
+-.ul
+-learn
+-inadvertently, by pushing interrupt at the wrong time,
+-or by removing critical files,
+-or any number of similar slips.
+-The defenses against such problems
+-have steadily been improved, to the point
+-where most students should not notice difficulties.
+-Of course, it will always be possible to break
+-.I
+-learn
+-.R
+-maliciously, but this is not likely to be a problem.
+-.PP
+-One area is more fundamental \(em
+-some
+-.UX
+-commands are sufficiently global in their effect
+-that
+-.ul
+-learn
+-currently
+-does not allow them to be executed at all.
+-The most obvious is
+-.I cd ,
+-which changes to another directory.
+-The prospect of a student who is learning about directories
+-inadvertently moving to some random directory
+-and removing files has deterred us
+-from even writing lessons on
+-.I cd ,
+-but ultimately lessons on such topics probably should be added.
+//GO.SYSIN DD p6
+echo p7
+sed 's/.//' >p7 <<'//GO.SYSIN DD p7'
+-.NH
+-Acknowledgments
+-.PP
+-We are grateful to all those who have tried
+-.ul
+-learn,
+-for we have benefited greatly from their
+-suggestions and criticisms.
+-In particular,
+-M. E. Bittrich,
+-J. L. Blue,
+-S. I. Feldman,
+-P. A. Fox,
+-and
+-M. J. McAlpin
+-have provided substantial feedback.
+-Conversations with E. Z. Rothkopf also provided many of the ideas in the system.
+-We are also indebted to Don Jackowski
+-for serving as a guinea pig for the second version,
+-and to Tom Plum for his efforts to improve the C script.
+-....SG \s-2MH\s0-1273/4-\s-2MEL/BWK\s0-unix
+-.[
+-$LIST$
+-.]
+//GO.SYSIN DD p7
diff --git a/doc/7thEdMan/vol2/lex b/doc/7thEdMan/vol2/lex
new file mode 100644 (file)
index 0000000..02ebb2c
--- /dev/null
@@ -0,0 +1,2310 @@
+.hc ~
+.bd I 2
+.de TS
+.br
+.nf
+.SP 1v
+.ul 0
+..
+.de TE
+.SP 1v
+.fi
+..
+.de PT
+.if \\n%>1 'tl ''\s7LEX\s0\s9\(mi%\s0''
+.if \\n%>1 'sp
+..
+.ND July 21, 1975
+.RP
+.TM 75-1274-15 39199 39199-11
+.TL
+Lex \- A Lexical Analyzer ~Generator~
+.AU ``MH 2C-569'' 6377
+M. E. Lesk and E. Schmidt
+.AI
+.MH
+.AB
+.sp
+.bd I 2
+.nr PS 8
+.nr VS 9
+.ps 8
+.vs 9p
+Lex helps write programs whose control flow
+is directed by instances of regular
+expressions in the input stream.
+It is well suited for editor-script type transformations and
+for segmenting input in preparation for
+a parsing routine.
+.PP
+Lex source is a table of regular expressions and corresponding program fragments.
+The table is translated to a program
+which reads an input stream, copying it to an output stream
+and partitioning the input
+into strings which match the given expressions.
+As each such string is recognized the corresponding
+program fragment is executed.
+The recognition of the expressions
+is performed by a deterministic finite automaton
+generated by Lex.
+The program fragments written by the user are executed in the order in which the
+corresponding regular expressions occur in the input stream.
+.if n .if \n(tm .ig
+.PP
+The lexical analysis
+programs written with Lex accept ambiguous specifications
+and choose the longest
+match possible at each input point.
+If necessary, substantial look~ahead
+is performed on the input, but the
+input stream will be backed up to the
+end of the current partition, so that the user
+has general freedom to manipulate it.
+.PP
+Lex can generate analyzers in either C or Ratfor, a language
+which can be translated automatically to portable Fortran.
+It is available on the PDP-11 UNIX, Honeywell GCOS,
+and IBM OS systems.
+This manual, however, will only discuss generating analyzers
+in C on the UNIX system, which is the only supported
+form of Lex under UNIX Version 7.
+Lex is designed to simplify
+interfacing with Yacc, for those
+with access to this compiler-compiler system.
+..
+.nr PS 9
+.nr VS 11
+.AE
+.SH
+.ce 1
+Table of Contents
+.LP
+.ce 100
+.TS
+r 1l 2r .
+1.     Introduction.   1
+2.     Lex Source.     3
+3.     Lex Regular Expressions.        3
+4.     Lex Actions.    5
+5.     Ambiguous Source Rules. 7
+6.     Lex Source Definitions. 8
+7.     Usage.  8
+8.     Lex and Yacc.   9
+9.     Examples.       10
+10.    Left Context Sensitivity.       11
+11.    Character Set.  12
+12.    Summary of Source Format.       12
+13.    Caveats and Bugs.       13
+14.    Acknowledgments.        13
+15.    References.     13
+.TE
+.ce 0
+.2C
+.NH
+Introduction.
+.PP
+Lex is a program generator designed for
+lexical processing of character input streams.
+It accepts a high-level, problem oriented specification
+for character string matching,
+and
+produces a program in a general purpose language which recognizes
+regular expressions.
+The regular expressions are specified by the user in the
+source specifications given to Lex.
+The Lex written code recognizes these expressions
+in an input stream and partitions the input stream into
+strings matching the expressions.  At the bound~aries
+between strings
+program sections
+provided by the user are executed.
+The Lex source file associates the regular expressions and the
+program fragments.
+As each expression appears in the input to the program written by Lex,
+the corresponding fragment is executed.
+.PP
+.de MH
+Bell Laboratories, Murray Hill, NJ 07974.
+..
+The user supplies the additional code
+beyond expression matching
+needed to complete his tasks, possibly
+including code written by other generators.
+The program that recognizes the expressions is generated in the
+general purpose programming language employed for the
+user's program fragments.
+Thus, a high level expression
+language is provided to write the string expressions to be
+matched while the user's freedom to write actions
+is unimpaired.
+This avoids forcing the user who wishes to use a string manipulation
+language for input analysis to write processing programs in the same
+and often inappropriate string handling language.
+.PP
+Lex is not a complete language, but rather a generator representing
+a new language feature which can be added to
+different programming languages, called ``host languages.'' 
+Just as general purpose languages
+can produce code to run on different computer hardware,
+Lex can write code in different host languages.
+The host language is used for the output code generated by Lex
+and also for the program fragments added by the user.
+Compatible run-time libraries for the different host languages
+are also provided.
+This makes Lex adaptable to different environments and
+different users.
+Each application
+may be directed to the combination of hardware and host language appropriate
+to the task, the user's background, and the properties of local
+implementations.
+At present, the only supported host language is C,
+although Fortran (in the form of Ratfor [2] has been available
+in the past.
+Lex itself exists on UNIX, GCOS, and OS/370; but the
+code generated by Lex may be taken anywhere the appropriate
+compilers exist.
+.PP
+Lex turns the user's expressions and actions
+(called
+.ul
+source
+in this memo) into the host general-purpose language;
+the generated program is named
+.ul
+yylex.
+The
+.ul
+yylex
+program
+will recognize expressions
+in a stream
+(called
+.ul
+input
+in this memo)
+and perform the specified actions for each expression as it is detected.
+See Figure 1.
+.GS
+.TS
+center;
+l _ r
+l|c|r
+l _ r
+l _ r
+l|c|r
+l _ r
+c s s
+c s s.
+
+Source \(->    Lex     \(-> yylex
+
+.sp 2
+
+Input \(->     yylex   \(-> Output
+
+.sp
+An overview of Lex
+.sp
+Figure 1
+.TE
+.GE
+.PP
+For a trivial example, consider a program to delete
+from the input
+all blanks or tabs at the ends of lines.
+.TS
+center;
+l l.
+%%
+[ \et]+$       ;
+.TE
+is all that is required.
+The program
+contains a %% delimiter to mark the beginning of the rules, and
+one rule.
+This rule contains a regular expression
+which matches one or more
+instances of the characters blank or tab
+(written \et for visibility, in accordance with the C language convention)
+just prior to the end of a line.
+The brackets indicate the character
+class made of blank and tab; the + indicates ``one or more ...'';
+and the $ indicates ``end of line,'' as in QED.
+No action is specified,
+so the program generated by Lex (yylex) will ignore these characters.
+Everything else will be copied.
+To change any remaining
+string of blanks or tabs to a single blank,
+add another rule:
+.TS
+center;
+l l.
+%%
+[ \et]+$       ;
+[ \et]+        printf(" ");
+.TE
+The finite automaton generated for this
+source will scan for both rules at once,
+observing at
+the termination of the string of blanks or tabs
+whether or not there is a newline character, and executing
+the desired rule action.
+The first rule matches all strings of blanks or tabs
+at the end of lines, and the second
+rule all remaining strings of blanks or tabs.
+.PP
+Lex can be used alone for simple transformations, or
+for analysis and statistics gathering on a lexical level.
+Lex can also be used with a parser generator
+to perform the lexical analysis phase; it is particularly
+easy to interface Lex and Yacc [3].
+Lex programs recognize only regular expressions;
+Yacc writes parsers that accept a large class of context free grammars,
+but require a lower level analyzer to recognize input tokens.
+Thus, a combination of Lex and Yacc is often appropriate.
+When used as a preprocessor for a later parser generator,
+Lex is used to partition the input stream,
+and the parser generator assigns structure to
+the resulting pieces.
+The flow of control
+in such a case (which might be the first half of a compiler,
+for example) is shown in Figure 2.
+Additional programs,
+written by other generators
+or by hand, can
+be added easily to programs written by Lex.
+.BS 2
+.TS
+center;
+l c c c l
+l c c c l
+l c c c l
+l _ c _ l
+l|c|c|c|l
+l _ c _ l
+l c c c l
+l _ c _ l
+l|c|c|c|l
+l _ c _ l
+l c s s l
+l c s s l.
+       lexical         grammar
+       rules           rules
+       \(da            \(da
+
+       Lex             Yacc
+
+       \(da            \(da
+
+Input \(->     yylex   \(->    yyparse \(-> Parsed input
+
+.sp
+       Lex with Yacc
+.sp
+       Figure 2
+.TE
+.BE
+Yacc users
+will realize that the name
+.ul
+yylex
+is what Yacc expects its lexical analyzer to be named,
+so that the use of this name by Lex simplifies
+interfacing.
+.PP
+Lex generates a deterministic finite automaton from the regular expressions
+in the source [4].
+The automaton is interpreted, rather than compiled, in order
+to save space.
+The result is still a fast analyzer.
+In particular, the time taken by a Lex program
+to recognize and partition an input stream is
+proportional to the length of the input.
+The number of Lex rules or
+the complexity of the rules is
+not important in determining speed,
+unless rules which include
+forward context require a significant amount of re~scanning.
+What does increase with the number and complexity of rules
+is the size of the finite
+automaton, and therefore the size of the program
+generated by Lex.
+.PP
+In the program written by Lex, the user's fragments
+(representing the
+.ul
+actions
+to be performed as each regular expression
+is found)
+are gathered
+as cases of a switch.
+The automaton interpreter directs the control flow.
+Opportunity is provided for the user to insert either
+declarations or additional statements in the routine containing
+the actions, or to
+add subroutines outside this action routine.
+.PP
+Lex is not limited to source which can
+be interpreted on the basis of one character
+look~ahead.
+For example,
+if there are two rules, one looking for
+.I ab
+and another for
+.I abcdefg ,
+and the input stream is
+.I abcdefh ,
+Lex will recognize
+.I ab
+and leave
+the input pointer just before
+.I "cd. . ."
+Such backup is more costly
+than the processing of simpler languages.
+.2C
+.NH
+Lex Source.
+.PP
+The general format of Lex source is:
+.TS
+center;
+l.
+{definitions}
+%%
+{rules}
+%%
+{user subroutines}
+.TE
+where the definitions and the user subroutines
+are often omitted.
+The second
+.I %%
+is optional, but the first is required
+to mark the beginning of the rules.
+The absolute minimum Lex program is thus
+.TS
+center;
+l.
+%%
+.TE
+(no definitions, no rules) which translates into a program
+which copies the input to the output unchanged.
+.PP
+In the outline of Lex programs shown above, the
+.I
+rules
+.R
+represent the user's control
+decisions; they are a table, in which the left column
+contains
+.I
+regular expressions
+.R
+(see section 3)
+and the right column contains
+.I
+actions,
+.R
+program fragments to be executed when the expressions
+are recognized.
+Thus an individual rule might appear
+.TS
+center;
+l l.
+integer        printf("found keyword INT");
+.TE
+to look for the string
+.I integer
+in the input stream and
+print the message ``found keyword INT'' whenever it appears.
+In this example the host procedural language is C and
+the C library function
+.I
+printf
+.R
+is used to print the string.
+The end
+of the expression is indicated by the first blank or tab character.
+If the action is merely a single C expression,
+it can just be given on the right side of the line; if it is
+compound, or takes more than a line, it should be enclosed in
+braces.
+As a slightly more useful example, suppose it is desired to
+change a number of words from British to American spelling.
+Lex rules such as
+.TS
+center;
+l l.
+colour printf("color");
+mechanise      printf("mechanize");
+petrol printf("gas");
+.TE
+would be a start.  These rules are not quite enough,
+since
+the word
+.I petroleum
+would become
+.I gaseum ;
+a way of dealing
+with this will be described later.
+.2C
+.NH
+Lex Regular Expressions.
+.PP
+The definitions of regular expressions are very similar to those
+in QED [5].
+A regular
+expression specifies a set of strings to be matched.
+It contains text characters (which match the corresponding
+characters in the strings being compared)
+and operator characters (which specify
+repetitions, choices, and other features).
+The letters of the alphabet and the digits are
+always text characters; thus the regular expression
+.TS
+center;
+l l.
+integer
+.TE
+matches the string
+.ul
+integer
+wherever it appears
+and the expression
+.TS
+center;
+l.
+a57D
+.TE
+looks for the string
+.ul
+a57D.
+.PP
+.I
+Operators.
+.R
+The operator characters are
+.TS
+center;
+l.
+" \e [ ] ^ \- ? . \(** + | ( ) $ / { } % < >
+.TE
+and if they are to be used as text characters, an escape
+should be used.
+The quotation mark operator (")
+indicates that whatever is contained between a pair of quotes
+is to be taken as text characters.
+Thus
+.TS
+center;
+l.
+xyz"++"
+.TE
+matches the string
+.I xyz++
+when it appears.  Note that a part of a string may be quoted.
+It is harmless but unnecessary to quote an ordinary
+text character; the expression
+.TS
+center;
+l.
+"xyz++"
+.TE
+is the same as the one above.
+Thus by quoting every non-alphanumeric character
+being used as a text character, the user can avoid remembering
+the list above of current
+operator characters, and is safe should further extensions to Lex
+lengthen the list.
+.PP
+An operator character may also be turned into a text character
+by preceding it with \e as in
+.TS
+center;
+l.
+xyz\e+\e+
+.TE
+which
+is another, less readable, equivalent of the above expressions.
+Another use of the quoting mechanism is to get a blank into
+an expression; normally, as explained above, blanks or tabs end
+a rule.
+Any blank character not contained within [\|] (see below) must
+be quoted.
+Several normal C escapes with \e
+are recognized: \en is newline, \et is tab, and \eb is backspace.
+To enter \e itself, use \e\e.
+Since newline is illegal in an expression, \en must be used;
+it is not
+required to escape tab and backspace.
+Every character but blank, tab, newline and the list above is always
+a text character.
+.PP
+.I
+Character classes.
+.R
+Classes of characters can be specified using the operator pair [\|].
+The construction
+.I [abc]
+matches a
+single character, which may be
+.I a ,
+.I b ,
+or
+.I c .
+Within square brackets,
+most operator meanings are ignored.
+Only three characters are special:
+these are \e \(mi and ^.  The \(mi character
+indicates ranges.  For example,
+.TS
+center;
+l.
+[a\(miz0\(mi9<>_]
+.TE
+indicates the character class containing all the lower case letters,
+the digits,
+the angle brackets, and underline.
+Ranges may be given in either order.
+Using \(mi between any pair of characters which are
+not both upper case letters, both lower case letters, or both digits
+is implementation dependent and will get a warning message.
+(E.g., [0\-z] in ASCII is many more characters
+than it is in EBCDIC).
+If it is desired to include the
+character \(mi in a character class, it should be first or
+last; thus
+.TS
+center;
+l.
+[\(mi+0\(mi9]
+.TE
+matches all the digits and the two signs.
+.PP
+In character classes,
+the ^ operator must appear as the first character
+after the left bracket; it indicates that the resulting string
+is to be complemented with respect to the computer character set.
+Thus
+.TS
+center;
+l.
+[^abc]
+.TE
+matches all characters except a, b, or c, including
+all special or control characters; or
+.TS
+center;
+l.
+[^a\-zA\-Z]
+.TE
+is any character which is not a letter.
+The \e character provides the usual escapes within
+character class brackets.
+.PP
+.I
+Arbitrary character.
+.R
+To match almost any character, the operator character
+.TS
+center;
+l.
+\&.
+.TE
+is the class of all characters except newline.
+Escaping into octal is possible although non-portable:
+.TS
+center;
+l.
+[\e40\-\e176]
+.TE
+matches all printable characters in the ASCII character set, from octal
+40 (blank) to octal 176 (tilde).
+.PP
+.I
+Optional expressions.
+.R
+The operator
+.I ?
+indicates
+an optional element of an expression.
+Thus
+.TS
+center;
+l.
+ab?c
+.TE
+matches either
+.I ac
+or
+.I abc .
+.PP
+.I
+Repeated expressions.
+.R
+Repetitions of classes are indicated by the operators
+.I \(**
+and
+.I + .
+.TS
+center;
+l.
+\f2a\(**\f1
+.TE
+is any number of consecutive
+.I a
+characters, including zero; while
+.TS
+center;
+l.
+a+
+.TE
+is one or more instances of
+.I a.
+For example,
+.TS
+center;
+l.
+[a\-z]+
+.TE
+is all strings of lower case letters.
+And
+.TS
+center;
+l.
+[A\(miZa\(miz][A\(miZa\(miz0\(mi9]\(**
+.TE
+indicates all alphanumeric strings with a leading
+alphabetic character.
+This is a typical expression for recognizing identifiers in
+computer languages.
+.PP
+.I
+Alternation and Grouping.
+.R
+The operator |
+indicates alternation:
+.TS
+center;
+l.
+(ab\||\|cd)
+.TE
+matches either
+.ul
+ab
+or
+.ul
+cd.
+Note that parentheses are used for grouping, although
+they are
+not necessary on the outside level;
+.TS
+center;
+l.
+ab\||\|cd
+.TE
+would have sufficed.
+Parentheses
+can be used for more complex expressions:
+.TS
+center;
+l.
+(ab\||\|cd+)?(ef)\(**
+.TE
+matches such strings as
+.I abefef ,
+.I efefef ,
+.I cdef ,
+or
+.I cddd\| ;
+but not
+.I abc ,
+.I abcd ,
+or
+.I abcdef .
+.PP
+.I
+Context sensitivity.
+.R
+Lex will recognize a small amount of surrounding
+context.  The two simplest operators for this are
+.I ^
+and
+.I $ .
+If the first character of an expression is
+.I ^ ,
+the expression will only be matched at the beginning
+of a line (after a newline character, or at the beginning of
+the input stream).
+This can never conflict with the other meaning of
+.I ^ ,
+complementation
+of character classes, since that only applies within
+the [\|] operators.
+If the very last character is
+.I $ ,
+the expression will only be matched at the end of a line (when
+immediately followed by newline).
+The latter operator is a special case of the
+.I /
+operator character,
+which indicates trailing context.
+The expression
+.TS
+center;
+l.
+ab/cd
+.TE
+matches the string
+.I ab ,
+but only if followed by
+.ul
+cd.
+Thus
+.TS
+center;
+l.
+ab$
+.TE
+is the same as
+.TS
+center;
+l.
+ab/\en
+.TE
+Left context is handled in Lex by
+.I
+start conditions
+.R
+as explained in section 10.  If a rule is only to be executed
+when the Lex automaton interpreter is in start condition
+.I
+x,
+.R
+the rule should be prefixed by
+.TS
+center;
+l.
+<x>
+.TE
+using the angle bracket operator characters.
+If we considered ``being at the beginning of a line'' to be
+start condition
+.I ONE ,
+then the ^ operator
+would be equivalent to
+.TS
+center;
+l.
+<ONE>
+.TE
+Start conditions are explained more fully later.
+.PP
+.I
+Repetitions and Definitions.
+.R
+The operators {} specify
+either repetitions (if they enclose numbers)
+or
+definition expansion (if they enclose a name).  For example
+.TS
+center;
+l.
+{digit}
+.TE
+looks for a predefined string named
+.I digit
+and inserts it
+at that point in the expression.
+The definitions are given in the first part of the Lex
+input, before the rules.
+In contrast,
+.TS
+center;
+l.
+a{1,5}
+.TE
+looks for 1 to 5 occurrences of
+.I a .
+.PP
+Finally, initial
+.I %
+is special, being the separator
+for Lex source segments.
+.2C
+.NH
+Lex Actions.
+.PP
+When an expression written as above is matched, Lex
+executes the corresponding action.  This section describes
+some features of Lex which aid in writing actions.  Note
+that there is a default action, which
+consists of copying the input to the output.  This
+is performed on all strings not otherwise matched.  Thus
+the Lex user who wishes to absorb the entire input, without
+producing any output, must provide rules to match everything.
+When Lex is being used with Yacc, this is the normal
+situation.
+One may consider that actions are what is done instead of
+copying the input to the output; thus, in general,
+a rule which merely copies can be omitted.
+Also, a character combination
+which is omitted from the rules
+and which appears as input
+is likely to be printed on the output, thus calling
+attention to the gap in the rules.
+.PP
+One of the simplest things that can be done is to ignore
+the input.   Specifying a C null statement, \fI;\fR as an action
+causes this result.  A frequent rule is
+.TS
+center;
+l l.
+[ \et\en]      ;
+.TE
+which causes the three spacing characters (blank, tab, and newline)
+to be ignored.
+.PP
+Another easy way to avoid writing actions is the action character
+|, which indicates that the action for this rule is the action
+for the next rule.
+The previous example could also have been written
+.TS
+center;
+l l.
+" "            |
+"\et"          |
+"\en"          ;
+.TE
+with the same result, although in different style.
+The quotes around \en and \et are not required.
+.PP
+In more complex actions, the user
+will
+often want to know the actual text that matched some expression
+like
+.I [a\(miz]+ .
+Lex leaves this text in an external character
+array named
+.I
+yytext.
+.R
+Thus, to print the name found,
+a rule like
+.TS
+center;
+l l.
+[a\-z]+        printf("%s", yytext);
+.TE
+will print
+the string in
+.I
+yytext.
+.R
+The C function
+.I
+printf
+.R
+accepts a format argument and data to be printed;
+in this case, the format is ``print string'' (% indicating
+data conversion, and
+.I s
+indicating string type),
+and the data are the characters
+in
+.I
+yytext.
+.R
+So this just places
+the matched string
+on the output.
+This action
+is so common that
+it may be written as ECHO:
+.TS
+center;
+l l.
+[a\-z]+        ECHO;
+.TE
+is the same as the above.
+Since the default action is just to
+print the characters found, one might ask why
+give a rule, like this one, which merely specifies
+the default action?
+Such rules are often required
+to avoid matching some other rule
+which is not desired.  For example, if there is a rule
+which matches
+.I read
+it will normally match the instances of
+.I read
+contained in
+.I bread
+or
+.I readjust ;
+to avoid
+this,
+a rule
+of the form
+.I [a\(miz]+
+is needed.
+This is explained further below.
+.PP
+Sometimes it is more convenient to know the end of what
+has been found; hence Lex also provides a count
+.I
+yyleng
+.R
+of the number of characters matched.
+To count both the number
+of words and the number of characters in words in the input, the user might write
+.TS
+center;
+l l.
+[a\-zA\-Z]+    {words++; chars += yyleng;}
+.TE
+which accumulates in
+.ul
+chars
+the number
+of characters in the words recognized.
+The last character in the string matched can
+be accessed by
+.TS
+center;
+l.
+yytext[yyleng\-1]
+.TE
+.PP
+Occasionally, a Lex
+action may decide that a rule has not recognized the correct
+span of characters.
+Two routines are provided to aid with this situation.
+First,
+.I
+yymore()
+.R
+can be called to indicate that the next input expression recognized is to be
+tacked on to the end of this input.  Normally,
+the next input string would overwrite the current
+entry in
+.I
+yytext.
+.R
+Second,
+.I
+yyless (n)
+.R
+may be called to indicate that not all the characters matched
+by the currently successful expression are wanted right now.
+The argument
+.I
+n
+.R
+indicates the number of characters
+in
+.I
+yytext
+.R
+to be retained.
+Further characters previously matched
+are
+returned to the input.  This provides the same sort of
+look~ahead offered by the / operator,
+but in a different form.
+.PP
+.I
+Example:
+.R
+Consider a language which defines
+a string as a set of characters between quotation (") marks, and provides that
+to include a " in a string it must be preceded by a \e.  The
+regular expression which matches that is somewhat confusing,
+so that it might be preferable to write
+.TS
+center;
+l l.
+\e"[^"]\(**    {
+       if (yytext[yyleng\-1] == \(fm\e\e\(fm)
+            yymore();
+       else
+            ... normal user processing
+       }
+.TE
+which will, when faced with a string such as
+.I
+"abc\e"def\|"
+.R
+first match
+the five characters
+\fI"abc\e\|\fR;
+then
+the call to
+.I yymore()
+will
+cause the next part of the string,
+\fI"def\|\fR,
+to be tacked on the end.
+Note that the final quote terminating the string should be picked
+up in the code labeled ``normal processing''.
+.PP
+The function
+.I
+yyless()
+.R
+might be used to reprocess
+text in various circumstances.  Consider the C problem of distinguishing
+the ambiguity of ``=\(mia''.
+Suppose it is desired to treat this as ``=\(mi a''
+but print a message.  A rule might be
+.TS
+center;
+l l.
+=\(mi[a\-zA\-Z]        {
+       printf("Operator (=\(mi) ambiguous\en");
+       yyless(yyleng\-1);
+       ... action for =\(mi ...
+       }
+.TE
+which prints a message, returns the letter after the
+operator to the input stream, and treats the operator as ``=\(mi''.
+Alternatively it might be desired to treat this as ``=  \(mia''.
+To do this, just return the minus
+sign as well as the letter to the input:
+.TS
+center;
+l l.
+=\(mi[a\-zA\-Z]        {
+       printf("Operator (=\(mi) ambiguous\en");
+       yyless(yyleng\-2);
+       ... action for = ...
+       }
+.TE
+will perform the other interpretation.
+Note that the expressions for the two cases might more easily
+be written
+.TS
+center;
+l l.
+=\(mi/[A\-Za\-z]
+.TE
+in the first case and
+.TS
+center;
+l.
+=/\-[A\-Za\-z]
+.TE
+in the second;
+no backup would be required in the rule action.
+It is not necessary to recognize the whole identifier
+to observe the ambiguity.
+The
+possibility of ``=\(mi3'', however, makes
+.TS
+center;
+l.
+=\(mi/[^ \et\en]
+.TE
+a still better rule.
+.PP
+In addition to these routines, Lex also permits
+access to the I/O routines
+it uses.
+They are:
+.IP 1)
+.I
+input()
+.R
+which returns the next input character;
+.IP 2)
+.I
+output(c)
+.R
+which writes the character
+.I
+c
+.R
+on the output; and
+.IP 3)
+.I
+unput(c)
+.R
+pushes the character
+.I
+c
+.R
+back onto the input stream to be read later by
+.I
+input().
+.R
+.LP
+By default these routines are provided as macro definitions,
+but the user can override them and supply private versions.
+These routines
+define the relationship between external files and
+internal characters, and must all be retained
+or modified consistently.
+They may be redefined, to
+cause input or output to be transmitted to or from strange
+places, including other programs or internal memory;
+but the character set used must be consistent in all routines;
+a value of zero returned by
+.I
+input
+.R
+must mean end of file; and
+the relationship between
+.I
+unput
+.R
+and
+.I
+input
+.R
+must be retained
+or the Lex look~ahead will not work.
+Lex does not look ahead at all if it does not have to,
+but every rule ending in
+.ft I
++ \(** ?
+.ft R
+or
+.ft I
+$
+.ft R
+or containing
+.ft I
+/
+.ft R
+implies look~ahead.
+Look~ahead is also necessary to match an expression that is a prefix
+of another expression.
+See below for a discussion of the character set used by Lex.
+The standard Lex library imposes
+a 100 character limit on backup.
+.PP
+Another Lex library routine that the user will sometimes want
+to redefine is
+.I
+yywrap()
+.R
+which is called whenever Lex reaches an end-of-file.
+If
+.I
+yywrap
+.R
+returns a 1, Lex continues with the normal wrapup on end of input.
+Sometimes, however, it is convenient to arrange for more
+input to arrive
+from a new source.
+In this case, the user should provide
+a
+.I
+yywrap
+.R
+which
+arranges for new input and
+returns 0.  This instructs Lex to continue processing.
+The default
+.I
+yywrap
+.R
+always returns 1.
+.PP
+This routine is also a convenient place
+to print tables, summaries, etc. at the end
+of a program.  Note that it is not
+possible to write a normal rule which recognizes
+end-of-file; the only access to this condition is
+through
+.I
+yywrap.
+.R
+In fact, unless a private version of
+.I
+input()
+.R
+is supplied
+a file containing nulls
+cannot be handled,
+since a value of 0 returned by
+.I
+input
+.R
+is taken to be end-of-file.
+.PP
+.2C
+.NH
+Ambiguous Source Rules.
+.PP
+Lex can handle ambiguous specifications.
+When more than one expression can match the
+current input, Lex chooses as follows:
+.IP 1)
+The longest match is preferred.
+.IP 2)
+Among rules which matched the same number of characters,
+the rule given first is preferred.
+.LP
+Thus, suppose the rules
+.TS
+center;
+l l.
+integer        keyword action ...;
+[a\-z]+        identifier action ...;
+.TE
+to be given in that order.  If the input is
+.I integers ,
+it is taken as an identifier, because
+.I [a\-z]+
+matches 8 characters while
+.I integer
+matches only 7.
+If the input is
+.I integer ,
+both rules match 7 characters, and
+the keyword rule is selected because it was given first.
+Anything shorter (e.g. \fIint\fR\|) will
+not match the expression
+.I integer
+and so the identifier interpretation is used.
+.PP
+The principle of preferring the longest
+match makes rules containing
+expressions like
+.I \&.\(**
+dangerous.
+For example,
+.TS
+center;
+l.
+\&\(fm.\(**\(fm
+.TE
+might seem a good way of recognizing
+a string in single quotes.
+But it is an invitation for the program to read far
+ahead, looking for a distant
+single quote.
+Presented with the input
+.TS
+center;
+l l.
+\&\(fmfirst\(fm quoted string here, \(fmsecond\(fm here
+.TE
+the above expression will match
+.TS
+center;
+l l.
+\&\(fmfirst\(fm quoted string here, \(fmsecond\(fm
+.TE
+which is probably not what was wanted.
+A better rule is of the form
+.TS
+center;
+l.
+\&\(fm[^\(fm\en]\(**\(fm
+.TE
+which, on the above input, will stop
+after
+.I \(fmfirst\(fm .
+The consequences
+of errors like this are mitigated by the fact
+that the
+.I \&.
+operator will not match newline.
+Thus expressions like
+.I \&.\(**
+stop on the
+current line.
+Don't try to defeat this with expressions like
+.I [.\en]+
+or
+equivalents;
+the Lex generated program will try to read
+the entire input file, causing
+internal buffer overflows.
+.PP
+Note that Lex is normally partitioning
+the input stream, not searching for all possible matches
+of each expression.
+This means that each character is accounted for
+once and only once.
+For example, suppose it is desired to
+count occurrences of both \fIshe\fR and \fIhe\fR in an input text.
+Some Lex rules to do this might be
+.TS
+center;
+l l.
+she    s++;
+he     h++;
+\en    |
+\&.    ;
+.TE
+where the last two rules ignore everything besides \fIhe\fR and \fIshe\fR.
+Remember that . does not include newline.
+Since \fIshe\fR includes \fIhe\fR, Lex will normally
+.I
+not
+.R
+recognize
+the instances of \fIhe\fR included in \fIshe\fR,
+since once it has passed a \fIshe\fR those characters are gone.
+.PP
+Sometimes the user would like to override this choice.  The action
+REJECT
+means ``go do the next alternative.''
+It causes whatever rule was second choice after the current
+rule to be executed.
+The position of the input pointer is adjusted accordingly.
+Suppose the user really wants to count the included instances of \fIhe\fR:
+.TS
+center;
+l l.
+she    {s++; REJECT;}
+he     {h++; REJECT;}
+\en    |
+\&.    ;
+.TE
+these rules are one way of changing the previous example
+to do just that.
+After counting each expression, it is rejected; whenever appropriate,
+the other expression will then be counted.  In this example, of course,
+the user could note that \fIshe\fR includes \fIhe\fR but not
+vice versa, and omit the REJECT action on \fIhe\fR;
+in other cases, however, it
+would not be possible a priori to tell
+which input characters
+were in both classes.
+.PP
+Consider the two rules
+.TS
+center;
+l l.
+a[bc]+ { ... ; REJECT;}
+a[cd]+ { ... ; REJECT;}
+.TE
+If the input is
+.I ab ,
+only the first rule matches,
+and on
+.I ad
+only the second matches.
+The input string
+.I accb
+matches the first rule for four characters
+and then the second rule for three characters.
+In contrast, the input
+.I accd
+agrees with
+the second rule for four characters and then the first
+rule for three.
+.PP
+In general, REJECT is useful whenever
+the purpose of Lex is not to partition the input
+stream but to detect all examples of some items
+in the input, and the instances of these items
+may overlap or include each other.
+Suppose a digram table of the input is desired;
+normally the digrams overlap, that is the word
+.I the
+is considered to contain
+both
+.I th
+and
+.I he .
+Assuming a two-dimensional array named
+.ul
+digram
+to be incremented, the appropriate
+source is
+.TS
+center;
+l l.
+%%
+[a\-z][a\-z]   {digram[yytext[0]][yytext[1]]++; REJECT;}
+.      ;
+\en    ;
+.TE
+where the REJECT is necessary to pick up
+a letter pair beginning at every character, rather than at every
+other character.
+.2C
+.NH
+Lex Source Definitions.
+.PP
+Remember the format of the Lex
+source:
+.TS
+center;
+l.
+{definitions}
+%%
+{rules}
+%%
+{user routines}
+.TE
+So far only the rules have been described.  The user needs
+additional options,
+though, to define variables for use in his program and for use
+by Lex.
+These can go either in the definitions section
+or in the rules section.
+.PP
+Remember that Lex is turning the rules into a program.
+Any source not intercepted by Lex is copied
+into the generated program.  There are three classes
+of such things.
+.IP 1)
+Any line which is not part of a Lex rule or action
+which begins with a blank or tab is copied into
+the Lex generated program.
+Such source input prior to the first %% delimiter will be external
+to any function in the code; if it appears immediately after the first
+%%,
+it appears in an appropriate place for declarations
+in the function written by Lex which contains the actions.
+This material must look like program fragments,
+and should precede the first Lex rule.
+.IP
+As a side effect of the above, lines which begin with a blank
+or tab, and which contain a comment,
+are passed through to the generated program.
+This can be used to include comments in either the Lex source or
+the generated code.  The comments should follow the host
+language convention.
+.IP 2)
+Anything included between lines containing
+only
+.I %{
+and
+.I %}
+is
+copied out as above.  The delimiters are discarded.
+This format permits entering text like preprocessor statements that
+must begin in column 1,
+or copying lines that do not look like programs.
+.IP 3)
+Anything after the third %% delimiter, regardless of formats, etc.,
+is copied out after the Lex output.
+.PP
+Definitions intended for Lex are given
+before the first %% delimiter.  Any line in this section
+not contained between %{ and %}, and begining
+in column 1, is assumed to define Lex substitution strings.
+The format of such lines is
+.TS
+center;
+l l.
+name translation
+.TE
+and it
+causes the string given as a translation to
+be associated with the name.
+The name and translation
+must be separated by at least one blank or tab, and the name must begin with a letter.
+The translation can then be called out
+by the {name} syntax in a rule.
+Using {D} for the digits and {E} for an exponent field,
+for example, might abbreviate rules to recognize numbers:
+.TS
+center;
+l l.
+D      [0\-9]
+E      [DEde][\-+]?{D}+
+%%
+{D}+   printf("integer");
+{D}+"."{D}\(**({E})?   |
+{D}\(**"."{D}+({E})?   |
+{D}+{E}                printf("real");
+.TE
+Note the first two rules for real numbers;
+both require a decimal point and contain
+an optional exponent field,
+but the first requires at least one digit before the
+decimal point and the second requires at least one
+digit after the decimal point.
+To correctly handle the problem
+posed by a Fortran expression such as
+.I 35.EQ.I ,
+which does not contain a real number, a context-sensitive
+rule such as
+.TS
+center;
+l l.
+[0\-9]+/"."EQ  printf("integer");
+.TE
+could be used in addition to the normal rule for integers.
+.PP
+The definitions
+section may also contain other commands, including the
+selection of a host language, a character set table,
+a list of start conditions, or adjustments to the default
+size of arrays within Lex itself for larger source programs.
+These possibilities
+are discussed below under ``Summary of Source Format,''
+section 12.
+.2C
+.NH
+Usage.
+.PP
+There are two steps in
+compiling a Lex source program.
+First, the Lex source must be turned into a generated program
+in the host general purpose language.
+Then this program must be compiled and loaded, usually with
+a library of Lex subroutines.
+The generated program
+is on a file named
+.I lex.yy.c .
+The I/O library is defined in terms of the C standard
+library [6].
+.PP
+The C programs generated by Lex are slightly different
+on OS/370, because the
+OS compiler is less powerful than the UNIX or GCOS compilers,
+and does less at compile time.
+C programs generated on GCOS and UNIX are the same.
+.PP
+.I
+UNIX.
+.R
+The library is accessed by the loader flag
+.I \-ll .
+So an appropriate
+set of commands is
+.KS
+.in 5
+lex source
+cc lex.yy.c \-ll
+.in 0
+.KE
+The resulting program is placed on the usual file
+.I
+a.out
+.R
+for later execution.
+To use Lex with Yacc see below.
+Although the default Lex I/O routines use the C standard library,
+the Lex automata themselves do not do so;
+if private versions of
+.I
+input,
+output
+.R
+and
+.I unput
+are given, the library can be avoided.
+.PP
+.2C
+.NH
+Lex and Yacc.
+.PP
+If you want to use Lex with Yacc, note that what Lex writes is a program
+named
+.I
+yylex(),
+.R
+the name required by Yacc for its analyzer.
+Normally, the default main program on the Lex library
+calls this routine, but if Yacc is loaded, and its main
+program is used, Yacc will call
+.I
+yylex().
+.R
+In this case each Lex rule should end with
+.TS
+center;
+l.
+return(token);
+.TE
+where the appropriate token value is returned.
+An easy way to get access
+to Yacc's names for tokens is to
+compile the Lex output file as part of
+the Yacc output file by placing the line
+.TS
+center;
+l.
+# include "lex.yy.c"
+.TE
+in the last section of Yacc input.
+Supposing the grammar to be
+named ``good'' and the lexical rules to be named ``better''
+the UNIX command sequence can just be:
+.TS
+center;
+l.
+yacc good
+lex better
+cc y.tab.c \-ly \-ll
+.TE
+The Yacc library (\-ly) should be loaded before the Lex library,
+to obtain a main program which invokes the Yacc parser.
+The generations of Lex and Yacc programs can be done in
+either order.
+.2C
+.NH
+Examples.
+.PP
+As a trivial problem, consider copying an input file while
+adding 3 to every positive number divisible by 7.
+Here is a suitable Lex source program
+.TS
+center;
+l l.
+%%
+       int k;
+[0\-9]+        {
+       k = atoi(yytext);
+       if (k%7 == 0)
+            printf("%d", k+3);
+       else
+            printf("%d",k);
+       }
+.TE
+to do just that.
+The rule [0\-9]+ recognizes strings of digits;
+.I
+atoi
+.R
+converts the digits to binary
+and stores the result in
+.ul
+k.
+The operator % (remainder) is used to check whether
+.ul
+k
+is divisible by 7; if it is,
+it is incremented by 3 as it is written out.
+It may be objected that this program will alter such
+input items as
+.I 49.63
+or
+.I X7 .
+Furthermore, it increments the absolute value
+of all negative numbers divisible by 7.
+To avoid this, just add a few more rules after the active one,
+as here:
+.TS
+center;
+l l.
+%%
+       int k;
+\-?[0\-9]+     {
+       k = atoi(yytext);
+       printf("%d", k%7 == 0 ? k+3 : k);
+       }
+\-?[0\-9.]+    ECHO;
+[A-Za-z][A-Za-z0-9]+   ECHO;
+.TE
+Numerical strings containing
+a ``.'' or preceded by a letter will be picked up by
+one of the last two rules, and not changed.
+The
+.I if\-else
+has been replaced by
+a C conditional expression to save space;
+the form
+.ul
+a?b:c
+means ``if
+.I a
+then
+.I b
+else
+.I c ''.
+.PP
+For an example of statistics gathering, here
+is a program which histograms the lengths
+of words, where a word is defined as a string of letters.
+.TS
+center;
+l l.
+       int lengs[100];
+%%
+[a\-z]+        lengs[yyleng]++;
+\&.    |
+\en    ;
+%%
+.T&
+l s.
+yywrap()
+{
+int i;
+printf("Length  No. words\en");
+for(i=0; i<100; i++)
+     if (lengs[i] > 0)
+          printf("%5d%10d\en",i,lengs[i]);
+return(1);
+}
+.TE
+This program
+accumulates the histogram, while producing no output.  At the end
+of the input it prints the table.
+The final statement
+.I
+return(1);
+.R
+indicates that Lex is to perform wrapup.  If
+.I
+yywrap
+.R
+returns zero (false)
+it implies that further input is available
+and the program is
+to continue reading and processing.
+To provide a
+.I
+yywrap
+.R
+that never
+returns true causes an infinite loop.
+.PP
+As a larger example,
+here are some parts of a program written by N. L. Schryer
+to convert double precision Fortran to single precision Fortran.
+Because Fortran does not distinguish upper and lower case letters,
+this routine begins by defining a set of classes including
+both cases of each letter:
+.TS
+center;
+l l.
+a      [aA]
+b      [bB]
+c      [cC]
+\&...
+z      [zZ]
+.TE
+An additional class recognizes white space:
+.TS
+center;
+l l.
+W      [ \et]\(**
+.TE
+The first rule changes
+``double precision'' to ``real'', or ``DOUBLE PRECISION'' to ``REAL''.
+.TS
+center;
+l.
+{d}{o}{u}{b}{l}{e}{W}{p}{r}{e}{c}{i}{s}{i}{o}{n} {
+     printf(yytext[0]==\(fmd\(fm? "real" : "REAL");
+     }
+.TE
+Care is taken throughout this program to preserve the case
+(upper or lower)
+of the original program.
+The conditional operator is used to
+select the proper form of the keyword.
+The next rule copies continuation card indications to
+avoid confusing them with constants:
+.TS
+center;
+l l.
+^"     "[^ 0]  ECHO;
+.TE
+In the regular expression, the quotes surround the
+blanks.
+It is interpreted as
+``beginning of line, then five blanks, then
+anything but blank or zero.'' 
+Note the two different meanings of
+.I ^ .
+There follow some rules to change double precision
+constants to ordinary floating constants.
+.TS
+center;
+l.
+[0\-9]+{W}{d}{W}[+\-]?{W}[0\-9]+     |
+[0\-9]+{W}"."{W}{d}{W}[+\-]?{W}[0\-9]+     |
+"."{W}[0\-9]+{W}{d}{W}[+\-]?{W}[0\-9]+     {
+     /\(** convert constants \(**/
+     for(p=yytext; \(**p != 0; p++)
+          {
+          if (\(**p == \(fmd\(fm || \(**p == \(fmD\(fm)
+               \(**p=+ \(fme\(fm\- \(fmd\(fm;
+          ECHO;
+          }
+.TE
+After the floating point constant is recognized, it is
+scanned by the
+.ul
+for
+loop
+to find the letter
+.I d
+or
+.I D .
+The program than adds
+.c
+.I \(fme\(fm\-\(fmd\(fm ,
+which converts
+it to the next letter of the alphabet.
+The modified constant, now single-precision,
+is written out again.
+There follow a series of names which must be respelled to remove
+their initial \fId\fR.
+By using the
+array
+.I
+yytext
+.R
+the same action suffices for all the names (only a sample of
+a rather long list is given here).
+.TS
+center;
+l l.
+{d}{s}{i}{n}   |
+{d}{c}{o}{s}   |
+{d}{s}{q}{r}{t}        |
+{d}{a}{t}{a}{n}        |
+\&...
+{d}{f}{l}{o}{a}{t}     printf("%s",yytext+1);
+.TE
+Another list of names must have initial \fId\fR changed to initial \fIa\fR:
+.TS
+center;
+l l.
+{d}{l}{o}{g}   |
+{d}{l}{o}{g}10 |
+{d}{m}{i}{n}1  |
+{d}{m}{a}{x}1  {
+       yytext[0] =+ \(fma\(fm \- \(fmd\(fm;
+       ECHO;
+       }
+.TE
+And one routine
+must have initial \fId\fR changed to initial \fIr\fR:
+.TS
+center;
+l l.
+{d}1{m}{a}{c}{h}       {yytext[0] =+ \(fmr\(fm  \- \(fmd\(fm;
+               ECHO;
+               }
+.TE
+To avoid such names as \fIdsinx\fR being detected as instances
+of \fIdsin\fR, some final rules pick up longer words as identifiers
+and copy some surviving characters:
+.TS
+center;
+l l.
+[A\-Za\-z][A\-Za\-z0\-9]\(**   |
+[0\-9]+        |
+\en    |
+\&.    ECHO;
+.TE
+Note that this program is not complete; it
+does not deal with the spacing problems in Fortran or
+with the use of keywords as identifiers.
+.br
+.2C
+.NH
+Left Context Sensitivity.
+.PP
+Sometimes
+it is desirable to have several sets of lexical rules
+to be applied at different times in the input.
+For example, a compiler preprocessor might distinguish
+preprocessor statements and analyze them differently
+from ordinary statements.
+This requires
+sensitivity
+to prior context, and there are several ways of handling
+such problems.
+The \fI^\fR operator, for example, is a prior context operator,
+recognizing immediately preceding left context just as \fI$\fR recognizes
+immediately following right context.
+Adjacent left context could be extended, to produce a facility similar to
+that for adjacent right context, but it is unlikely
+to be as useful, since often the relevant left context
+appeared some time earlier, such as at the beginning of a line.
+.PP
+This section describes three means of dealing
+with different environments: a simple use of flags,
+when only a few rules change from one environment to another,
+the use of
+.I
+start conditions
+.R
+on rules,
+and the possibility of making multiple lexical analyzers all run
+together.
+In each case, there are rules which recognize the need to change the
+environment in which the
+following input text is analyzed, and set some parameter
+to reflect the change.  This may be a flag explicitly tested by
+the user's action code; such a flag is the simplest way of dealing
+with the problem, since Lex is not involved at all.
+It may be more convenient,
+however,
+to have Lex remember the flags as initial conditions on the rules.
+Any rule may be associated with a start condition.  It will only
+be recognized when Lex is in
+that start condition.
+The current start condition may be changed at any time.
+Finally, if the sets of rules for the different environments
+are very dissimilar,
+clarity may be best achieved by writing several distinct lexical
+analyzers, and switching from one to another as desired.
+.PP
+Consider the following problem: copy the input to the output,
+changing the word \fImagic\fR to \fIfirst\fR on every line which began
+with the letter \fIa\fR, changing \fImagic\fR to \fIsecond\fR on every line
+which began with the letter \fIb\fR, and changing
+\fImagic\fR to \fIthird\fR on every line which began
+with the letter \fIc\fR.  All other words and all other lines
+are left unchanged.
+.PP
+These rules are so simple that the easiest way
+to do this job is with a flag:
+.TS
+center;
+l l.
+       int flag;
+%%
+^a     {flag = \(fma\(fm; ECHO;}
+^b     {flag = \(fmb\(fm; ECHO;}
+^c     {flag = \(fmc\(fm; ECHO;}
+\en    {flag =  0 ; ECHO;}
+magic  {
+       switch (flag)
+       {
+       case \(fma\(fm: printf("first"); break;
+       case \(fmb\(fm: printf("second"); break;
+\11\11     case \(fmc\(fm: printf("third"); break;
+       default: ECHO; break;
+       }
+       }
+.TE
+should be adequate.
+.PP
+To handle the same problem with start conditions, each
+start condition must be introduced to Lex in the definitions section
+with a line reading
+.TS
+center;
+l l.
+%Start name1 name2 ...
+.TE
+where the conditions may be named in any order.
+The word \fIStart\fR may be abbreviated to \fIs\fR or \fIS\fR.
+The conditions may be referenced at the
+head of a rule with the <> brackets:
+.TS
+center;
+l.
+<name1>expression
+.TE
+is a rule which is only recognized when Lex is in the
+start condition \fIname1\fR.
+To enter a start condition,
+execute the action statement
+.TS
+center;
+l.
+BEGIN name1;
+.TE
+which changes the start condition to \fIname1\fR.
+To resume the normal state,
+.TS
+center;
+l.
+BEGIN 0;
+.TE
+resets the initial condition
+of the Lex automaton interpreter.
+A rule may be active in several
+start conditions:
+.TS
+center;
+l.
+<name1,name2,name3>
+.TE
+is a legal prefix.  Any rule not beginning with the
+<> prefix operator is always active.
+.PP
+The same example as before can be written:
+.TS
+center;
+l l.
+%START AA BB CC
+%%
+^a     {ECHO; BEGIN AA;}
+^b     {ECHO; BEGIN BB;}
+^c     {ECHO; BEGIN CC;}
+\en    {ECHO; BEGIN 0;}
+<AA>magic      printf("first");
+<BB>magic      printf("second");
+<CC>magic      printf("third");
+.TE
+where the logic is exactly the same as in the previous
+method of handling the problem, but Lex does the work
+rather than the user's code.
+.2C
+.NH
+Character Set.
+.PP
+The programs generated by Lex handle
+character I/O only through the routines
+.I
+input,
+output,
+.R
+and
+.I
+unput.
+.R
+Thus the character representation
+provided in these routines
+is accepted by Lex and employed to return
+values in
+.I
+yytext.
+.R
+For internal use
+a character is represented as a small integer
+which, if the standard library is used,
+has a value equal to the integer value of the bit
+pattern representing the character on the host computer.
+Normally, the letter
+.I a
+is represented as the same form as the character constant
+.I \(fma\(fm .
+If this interpretation is changed, by providing I/O
+routines which translate the characters,
+Lex must be told about
+it, by giving a translation table.
+This table must be in the definitions section,
+and must be bracketed by lines containing  only
+``%T''.
+The table contains lines of the form
+.TS
+center;
+l.
+{integer} {character string}
+.TE
+which indicate the value associated with each character.
+Thus the next example
+.GS 2
+.TS
+center;
+l l.
+%T
+ 1     Aa
+ 2     Bb
+\&...
+26     Zz
+27     \en
+28     +
+29     \-
+30     0
+31     1
+\&...
+39     9
+%T
+.TE
+.sp
+.ce 1
+Sample character table.
+.GE
+maps the lower and upper case letters together into the integers 1 through 26,
+newline into 27, + and \- into 28 and 29, and the
+digits into 30 through 39.
+Note the escape for newline.
+If a table is supplied, every character that is to appear either
+in the rules or in any valid input must be included
+in the table.
+No character
+may be assigned the number 0, and no character may be
+assigned a bigger number than the size of the hardware character set.
+.2C
+.NH
+Summary of Source Format.
+.PP
+The general form of a Lex source file is:
+.TS
+center;
+l.
+{definitions}
+%%
+{rules}
+%%
+{user subroutines}
+.TE
+The definitions section contains
+a combination of
+.IP 1)
+Definitions, in the form ``name space translation''.
+.IP 2)
+Included code, in the form ``space code''.
+.IP 3)
+Included code, in the form
+.TS
+center;
+l.
+%{
+code
+%}
+.TE
+.ns
+.IP 4)
+Start conditions, given in the form
+.TS
+center;
+l.
+%S name1 name2 ...
+.TE
+.ns
+.IP 5)
+Character set tables, in the form
+.TS
+center;
+l.
+%T
+number space character-string
+\&...
+%T
+.TE
+.ns
+.IP 6)
+Changes to internal array sizes, in the form
+.TS
+center;
+l.
+%\fIx\fR\0\0\fInnn\fR
+.TE
+where \fInnn\fR is a decimal integer representing an array size
+and \fIx\fR selects the parameter as follows:
+.TS
+center;
+c c
+c l.
+Letter Parameter
+p      positions
+n      states
+e      tree nodes
+a      transitions
+k      packed character classes
+o      output array size
+.TE
+.LP
+Lines in the rules section have the form ``expression  action''
+where the action may be continued on succeeding
+lines by using braces to delimit it.
+.PP
+Regular expressions in Lex use the following
+operators:
+.br
+.TS
+center;
+l l.
+x      the character "x"
+"x"    an "x", even if x is an operator.
+\ex    an "x", even if x is an operator.
+[xy]   the character x or y.
+[x\-z] the characters x, y or z.
+[^x]   any character but x.
+\&.    any character but newline.
+^x     an x at the beginning of a line.
+<y>x   an x when Lex is in start condition y.
+x$     an x at the end of a line.
+x?     an optional x.
+x\(**  0,1,2, ... instances of x.
+x+     1,2,3, ... instances of x.
+x|y    an x or a y.
+(x)    an x.
+x/y    an x but only if followed by y.
+{xx}   the translation of xx from the definitions section.
+x{m,n} \fIm\fR through \fIn\fR occurrences of x
+.TE
+.NH
+Caveats and Bugs.
+.PP
+There are pathological expressions which
+produce exponential growth of the tables when
+converted to deterministic machines;
+fortunately, they are rare.
+.PP
+REJECT does not rescan the input; instead it remembers the results of the previous
+scan.  This means that if a rule with trailing context is found, and
+REJECT executed, the user
+must not have used
+.ul
+unput
+to change the characters forthcoming
+from the input stream.
+This is the only restriction on the user's ability to manipulate
+the not-yet-processed input.
+.PP
+.2C
+.NH
+Acknowledgments.
+.PP
+As should
+be obvious from the above, the outside of Lex
+is patterned
+on Yacc and the inside on Aho's string matching routines.
+Therefore, both S. C. Johnson and A. V. Aho
+are really originators
+of much of Lex,
+as well as debuggers of it.
+Many thanks are due to both.
+.PP
+The code of the current version of Lex was designed, written,
+and debugged by Eric Schmidt.
+.SG MH-1274-MEL-unix
+.sp 1
+.2C
+.NH
+References.
+.SP 1v
+.IP 1.
+B. W. Kernighan and D. M. Ritchie,
+.I
+The C Programming Language,
+.R
+Prentice-Hall, N. J. (1978).
+.IP 2.
+B. W. Kernighan,
+.I
+Ratfor: A Preprocessor for a Rational Fortran,
+.R
+Software \- Practice and Experience,
+\fB5\fR, pp. 395-496 (1975).
+.IP 3.
+S. C. Johnson,
+.I
+Yacc: Yet Another Compiler Compiler,
+.R
+Computing Science Technical Report No. 32,
+1975,
+.MH
+.if \n(tm (also TM 75-1273-6)
+.IP 4.
+A. V. Aho and M. J. Corasick,
+.I
+Efficient String Matching: An Aid to Bibliographic Search,
+.R
+Comm. ACM
+.B
+18,
+.R
+333-340 (1975).
+.IP 5.
+B. W. Kernighan, D. M. Ritchie and K. L. Thompson,
+.I
+QED Text Editor,
+.R
+Computing Science Technical Report No. 5,
+1972,
+.MH
+.IP 6.
+D. M. Ritchie,
+private communication.
+See also
+M. E. Lesk,
+.I
+The Portable C Library,
+.R
+Computing Science Technical Report No. 31,
+.MH
+.if \n(tm (also TM 75-1274-11)
diff --git a/doc/7thEdMan/vol2/lint b/doc/7thEdMan/vol2/lint
new file mode 100644 (file)
index 0000000..d1f5819
--- /dev/null
@@ -0,0 +1,1063 @@
+.RP
+.ND "July 26, 1978"
+.OK
+Program Portability
+Strong Type Checking
+.TL
+Lint, a C Program Checker
+.AU "MH 2C-559" 3968
+S. C. Johnson
+.AI
+.MH
+.AB
+.PP
+.I Lint
+is a command which examines C source programs,
+detecting
+a number of bugs and obscurities.
+It enforces the type rules of C more strictly than
+the C compilers.
+It may also be used to enforce a number of portability
+restrictions involved in moving
+programs between different machines and/or operating systems.
+Another option detects a number of wasteful, or error prone, constructions
+which nevertheless are, strictly speaking, legal.
+.PP
+.I Lint
+accepts multiple input files and library specifications, and checks them for consistency.
+.PP
+The separation of function between
+.I lint
+and the C compilers has both historical and practical
+rationale.
+The compilers turn C programs into executable files rapidly
+and efficiently.
+This is possible in part because the
+compilers do not do sophisticated
+type checking, especially between
+separately compiled programs.
+.I Lint
+takes a more global, leisurely view of the program,
+looking much more carefully at the compatibilities.
+.PP
+This document discusses the use of
+.I lint ,
+gives an overview of the implementation, and gives some hints on the
+writing of machine independent C code.
+.AE
+.CS 10 2 12 0 0 5
+.SH
+Introduction and Usage
+.PP
+Suppose there are two C
+.[
+Kernighan Ritchie Programming Prentice 1978
+.]
+source files,
+.I file1. c
+and
+.I file2.c  ,
+which are ordinarily compiled and loaded together.
+Then the command
+.DS
+lint  file1.c  file2.c
+.DE
+produces messages describing inconsistencies and inefficiencies
+in the programs.
+The program enforces the typing rules of C
+more strictly than the C compilers
+(for both historical and practical reasons)
+enforce them.
+The command
+.DS
+lint  \-p  file1.c  file2.c
+.DE
+will produce, in addition to the above messages, additional messages
+which relate to the portability of the programs to other operating
+systems and machines.
+Replacing the
+.B \-p
+by
+.B \-h
+will produce messages about various error-prone or wasteful constructions
+which, strictly speaking, are not bugs.
+Saying
+.B \-hp
+gets the whole works.
+.PP
+The next several sections describe the major messages;
+the document closes with sections
+discussing the implementation and giving suggestions
+for writing portable C.
+An appendix gives a summary of the
+.I lint
+options.
+.SH
+A Word About Philosophy
+.PP
+Many of the facts which
+.I lint
+needs may be impossible to
+discover.
+For example, whether a given function in a program ever gets called
+may depend on the input data.
+Deciding whether
+.I exit
+is ever called is equivalent to solving the famous ``halting problem,'' known to be
+recursively undecidable.
+.PP
+Thus, most of the
+.I lint
+algorithms are a compromise.
+If a function is never mentioned, it can never be called.
+If a function is mentioned,
+.I lint
+assumes it can be called; this is not necessarily so, but in practice is quite reasonable.
+.PP
+.I Lint
+tries to give information with a high degree of relevance.
+Messages of the form ``\fIxxx\fR might be a bug''
+are easy to generate, but are acceptable only in proportion
+to the fraction of real bugs they uncover.
+If this fraction of real bugs is too small, the messages lose their credibility
+and serve merely to clutter up the output,
+obscuring the more important messages.
+.PP
+Keeping these issues in mind, we now consider in more detail
+the classes of messages which
+.I lint
+produces.
+.SH
+Unused Variables and Functions
+.PP
+As sets of programs evolve and develop,
+previously used variables and arguments to
+functions may become unused;
+it is not uncommon for external variables, or even entire
+functions, to become unnecessary, and yet
+not be removed from the source.
+These ``errors of commission'' rarely cause working programs to fail, but they are a source
+of inefficiency, and make programs harder to understand
+and change.
+Moreover, information about such unused variables and functions can occasionally
+serve to discover bugs; if a function does a necessary job, and
+is never called, something is wrong!
+.PP
+.I Lint
+complains about variables and functions which are defined but not otherwise
+mentioned.
+An exception is variables which are declared through explicit
+.B extern
+statements but are never referenced; thus the statement
+.DS
+extern  float  sin(\|);
+.DE
+will evoke no comment if
+.I sin
+is never used.
+Note that this agrees with the semantics of the C compiler.
+In some cases, these unused external declarations might be of some interest; they
+can be discovered by adding the
+.B \-x
+flag to the
+.I lint
+invocation.
+.PP
+Certain styles of programming
+require many functions to be written with similar interfaces;
+frequently, some of the arguments may be unused
+in many of the calls.
+The
+.B \-v
+option is available to suppress the printing of
+complaints about unused arguments.
+When
+.B \-v
+is in effect, no messages are produced about unused
+arguments except for those
+arguments which are unused and also declared as
+register arguments; this can be considered
+an active (and preventable) waste of the register
+resources of the machine.
+.PP
+There is one case where information about unused, or
+undefined, variables is more distracting
+than helpful.
+This is when
+.I lint
+is applied to some, but not all, files out of a collection
+which are to be loaded together.
+In this case, many of the functions and variables defined
+may not be used, and, conversely,
+many functions and variables defined elsewhere may be used.
+The
+.B \-u
+flag may be used to suppress the spurious messages which might otherwise appear.
+.SH
+Set/Used Information
+.PP
+.I Lint
+attempts to detect cases where a variable is used before it is set.
+This is very difficult to do well;
+many algorithms take a good deal of time and space,
+and still produce messages about perfectly valid programs.
+.I Lint
+detects local variables (automatic and register storage classes)
+whose first use appears physically earlier in the input file than the first assignment to the variable.
+It assumes that taking the address of a variable constitutes a ``use,'' since the actual use
+may occur at any later time, in a data dependent fashion.
+.PP
+The restriction to the physical appearance of variables in the file makes the
+algorithm very simple and quick to implement,
+since the true flow of control need not be discovered.
+It does mean that
+.I lint
+can complain about some programs which are legal,
+but these programs would probably be considered bad on stylistic grounds (e.g. might
+contain at least two \fBgoto\fR's).
+Because static and external variables are initialized to 0,
+no meaningful information can be discovered about their uses.
+The algorithm deals correctly, however, with initialized automatic variables, and variables
+which are used in the expression which first sets them.
+.PP
+The set/used information also permits recognition of those local variables which are set
+and never used; these form a frequent source of inefficiencies, and may also be symptomatic of bugs.
+.SH
+Flow of Control
+.PP
+.I Lint
+attempts to detect unreachable portions of the programs which it processes.
+It will complain about unlabeled statements immediately following
+\fBgoto\fR, \fBbreak\fR, \fBcontinue\fR, or \fBreturn\fR statements.
+An attempt is made to detect loops which can never be left at the bottom, detecting the
+special cases
+\fBwhile\fR( 1 ) and \fBfor\fR(;;) as infinite loops.
+.I Lint
+also complains about loops which cannot be entered at the top;
+some valid programs may have such loops, but at best they are bad style,
+at worst bugs.
+.PP
+.I Lint
+has an important area of blindness in the flow of control algorithm:
+it has no way of detecting functions which are called and never return.
+Thus, a call to
+.I exit
+may cause unreachable code which
+.I lint
+does not detect; the most serious effects of this are in the
+determination of returned function values (see the next section).
+.PP
+One form of unreachable statement is not usually complained about by
+.I lint;
+a
+.B break
+statement that cannot be reached causes no message.
+Programs generated by
+.I yacc ,
+.[
+Johnson Yacc 1975
+.]
+and especially
+.I lex ,
+.[
+Lesk Lex
+.]
+may have literally hundreds of unreachable
+.B break
+statements.
+The
+.B \-O
+flag in the C compiler will often eliminate the resulting object code inefficiency.
+Thus, these unreached statements are of little importance,
+there is typically nothing the user can do about them, and the
+resulting messages would clutter up the
+.I lint
+output.
+If these messages are desired,
+.I lint
+can be invoked with the
+.B \-b
+option.
+.SH
+Function Values
+.PP
+Sometimes functions return values which are never used;
+sometimes programs incorrectly use function ``values''
+which have never been returned.
+.I Lint
+addresses this problem in a number of ways.
+.PP
+Locally, within a function definition,
+the appearance of both
+.DS
+return(  \fIexpr\fR  );
+.DE
+and
+.DS
+return ;
+.DE
+statements is cause for alarm;
+.I lint
+will give the message
+.DS
+function \fIname\fR contains return(e) and return
+.DE
+The most serious difficulty with this is detecting when a function return is implied
+by flow of control reaching the end of the function.
+This can be seen with a simple example:
+.DS
+.ta .5i 1i 1.5i
+\fRf ( a ) {
+       if ( a ) return ( 3 );
+       g (\|);
+       }
+.DE
+Notice that, if \fIa\fR tests false, \fIf\fR will call \fIg\fR and then return
+with no defined return value; this will trigger a complaint from
+.I lint .
+If \fIg\fR, like \fIexit\fR, never returns,
+the message will still be produced when in fact nothing is wrong.
+.PP
+In practice, some potentially serious bugs have been discovered by this feature;
+it also accounts for a substantial fraction of the ``noise'' messages produced
+by
+.I lint .
+.PP
+On a global scale,
+.I lint
+detects cases where a function returns a value, but this value is sometimes,
+or always, unused.
+When the value is always unused, it may constitute an inefficiency in the function definition.
+When the value is sometimes unused, it may represent bad style (e.g., not testing for
+error conditions).
+.PP
+The dual problem, using a function value when the function does not return one,
+is also detected.
+This is a serious problem.
+Amazingly, this bug has been observed on a couple of occasions
+in ``working'' programs; the desired function value just happened to have been computed
+in the function return register!
+.SH
+Type Checking
+.PP
+.I Lint
+enforces the type checking rules of C more strictly than the compilers do.
+The additional checking is in four major areas:
+across certain binary operators and implied assignments,
+at the structure selection operators,
+between the definition and uses of functions,
+and in the use of enumerations.
+.PP
+There are a number of operators which have an implied balancing between types of the operands.
+The assignment, conditional ( ?\|: ), and relational operators
+have this property; the argument
+of a \fBreturn\fR statement,
+and expressions used in initialization also suffer similar conversions.
+In these operations,
+\fBchar\fR, \fBshort\fR, \fBint\fR, \fBlong\fR, \fBunsigned\fR, \fBfloat\fR, and \fBdouble\fR types may be freely intermixed.
+The types of pointers must agree exactly,
+except that arrays of \fIx\fR's can, of course, be intermixed with pointers to \fIx\fR's.
+.PP
+The type checking rules also require that, in structure references, the
+left operand of the \(em> be a pointer to structure, the left operand of the \fB.\fR
+be a structure, and the right operand of these operators be a member
+of the structure implied by the left operand.
+Similar checking is done for references to unions.
+.PP
+Strict rules apply to function argument and return value
+matching.
+The types \fBfloat\fR and \fBdouble\fR may be freely matched,
+as may the types \fBchar\fR, \fBshort\fR, \fBint\fR, and \fBunsigned\fR.
+Also, pointers can be matched with the associated arrays.
+Aside from this, all actual arguments must agree in type with their declared counterparts.
+.PP
+With enumerations, checks are made that enumeration variables or members are not mixed
+with other types, or other enumerations,
+and that the only operations applied are =, initialization, ==, !=, and function arguments and return values.
+.SH
+Type Casts
+.PP
+The type cast feature in C was introduced largely as an aid
+to producing more portable programs.
+Consider the assignment
+.DS
+p = 1 ;
+.DE
+where
+.I p
+is a character pointer.
+.I Lint
+will quite rightly complain.
+Now, consider the assignment
+.DS
+p = (char \(**)1 ;
+.DE
+in which a cast has been used to
+convert the integer to a character pointer.
+The programmer obviously had a strong motivation
+for doing this, and has clearly signaled his intentions.
+It seems harsh for
+.I lint
+to continue to complain about this.
+On the other hand, if this code is moved to another
+machine, such code should be looked at carefully.
+The
+.B \-c
+flag controls the printing of comments about casts.
+When
+.B \-c
+is in effect, casts are treated as though they were assignments
+subject to complaint; otherwise, all legal casts are passed without comment,
+no matter how strange the type mixing seems to be.
+.SH
+Nonportable Character Use
+.PP
+On the PDP-11, characters are signed quantities, with a range
+from \-128 to 127.
+On most of the other C implementations, characters take on only positive
+values.
+Thus,
+.I lint
+will flag certain comparisons and assignments as being
+illegal or nonportable.
+For example, the fragment
+.DS
+char c;
+       ...
+if( (c = getchar(\|)) < 0 ) ....
+.DE
+works on the PDP-11, but
+will fail on machines where characters always take
+on positive values.
+The real solution is to declare
+.I c
+an integer, since
+.I getchar
+is actually returning
+integer values.
+In any case,
+.I lint
+will say
+``nonportable character comparison''.
+.PP
+A similar issue arises with bitfields; when assignments
+of constant values are made to bitfields, the field may
+be too small to hold the value.
+This is especially true because
+on some machines bitfields are considered as signed
+quantities.
+While it may seem unintuitive to consider
+that a two bit field declared of type
+.B int
+cannot hold the value 3, the problem disappears
+if the bitfield is declared to have type
+.B unsigned .
+.SH
+Assignments of longs to ints
+.PP
+Bugs may arise from the assignment of
+.B long
+to
+an
+.B int ,
+which loses accuracy.
+This may happen in programs
+which have been incompletely converted to use
+.B typedefs .
+When a
+.B typedef
+variable
+is changed from \fBint\fR to \fBlong\fR,
+the program can stop working because
+some intermediate results may be assigned
+to \fBints\fR, losing accuracy.
+Since there are a number of legitimate reasons for
+assigning \fBlongs\fR to \fBints\fR, the detection
+of these assignments is enabled
+by the
+.B \-a
+flag.
+.SH
+Strange Constructions
+.PP
+Several perfectly legal, but somewhat strange, constructions
+are flagged by
+.I lint;
+the messages hopefully encourage better code quality, clearer style, and
+may even point out bugs.
+The
+.B \-h
+flag is used to enable these checks.
+For example, in the statement
+.DS
+\(**p++ ;
+.DE
+the \(** does nothing; this provokes the message ``null effect'' from
+.I lint .
+The program fragment
+.DS
+unsigned x ;
+if( x < 0 ) ...
+.DE
+is clearly somewhat strange; the
+test will never succeed.
+Similarly, the test
+.DS
+if( x > 0 ) ...
+.DE
+is equivalent to
+.DS
+if( x != 0 )
+.DE
+which may not be the intended action.
+.I Lint
+will say ``degenerate unsigned comparison'' in these cases.
+If one says
+.DS
+if( 1 != 0 ) ....
+.DE
+.I lint
+will report
+``constant in conditional context'', since the comparison
+of 1 with 0 gives a constant result.
+.PP
+Another construction
+detected by
+.I lint
+involves
+operator precedence.
+Bugs which arise from misunderstandings about the precedence
+of operators can be accentuated by spacing and formatting,
+making such bugs extremely hard to find.
+For example, the statements
+.DS
+if( x&077 == 0 ) ...
+.DE
+or
+.DS
+x<\h'-.3m'<2 + 40
+.DE
+probably do not do what was intended.
+The best solution is to parenthesize such expressions,
+and
+.I lint
+encourages this by an appropriate message.
+.PP
+Finally, when the
+.B \-h
+flag is in force
+.I lint
+complains about variables which are redeclared in inner blocks
+in a way that conflicts with their use in outer blocks.
+This is legal, but is considered by many (including the author) to
+be bad style, usually unnecessary, and frequently a bug.
+.SH
+Ancient History
+.PP
+There are several forms of older syntax which are being officially
+discouraged.
+These fall into two classes, assignment operators and initialization.
+.PP
+The older forms of assignment operators (e.g., =+, =\-, . . . )
+could cause ambiguous expressions, such as
+.DS
+a  =\-1 ;
+.DE
+which could be taken as either
+.DS
+a =\-  1 ;
+.DE
+or
+.DS
+a  =  \-1 ;
+.DE
+The situation is especially perplexing if this
+kind of ambiguity arises as the result of a macro substitution.
+The newer, and preferred operators (+=, \-=, etc. )
+have no such ambiguities.
+To spur the abandonment of the older forms,
+.I lint
+complains about these old fashioned operators.
+.PP
+A similar issue arises with initialization.
+The older language allowed
+.DS
+int  x  \fR1 ;
+.DE
+to initialize
+.I x
+to 1.
+This also caused syntactic difficulties: for example,
+.DS
+int  x  ( \-1 ) ;
+.DE
+looks somewhat like the beginning of a function declaration:
+.DS
+int  x  ( y ) {  . . .
+.DE
+and the compiler must read a fair ways past
+.I x
+in order to sure what the declaration really is..
+Again, the problem is even more perplexing when the
+initializer involves a macro.
+The current syntax places an equals sign between the
+variable and the initializer:
+.DS
+int  x  =  \-1 ;
+.DE
+This is free of any possible syntactic ambiguity.
+.SH
+Pointer Alignment
+.PP
+Certain pointer assignments may be reasonable on some machines,
+and illegal on others, due entirely to
+alignment restrictions.
+For example, on the PDP-11, it is reasonable
+to assign integer pointers to double pointers, since
+double precision values may begin on any integer boundary.
+On the Honeywell 6000, double precision values must begin
+on even word boundaries;
+thus, not all such assignments make sense.
+.I Lint
+tries to detect cases where pointers are assigned to other
+pointers, and such alignment problems might arise.
+The message ``possible pointer alignment problem''
+results from this situation whenever either the
+.B \-p
+or
+.B \-h
+flags are in effect.
+.SH
+Multiple Uses and Side Effects
+.PP
+In complicated expressions, the best order in which to evaluate
+subexpressions may be highly machine dependent.
+For example, on machines (like the PDP-11) in which the stack
+runs backwards, function arguments will probably be best evaluated
+from right-to-left; on machines with a stack running forward,
+left-to-right seems most attractive.
+Function calls embedded as arguments of other functions
+may or may not be treated similarly to ordinary arguments.
+Similar issues arise with other operators which have side effects,
+such as the assignment operators and the increment and decrement operators.
+.PP
+In order that the efficiency of C on a particular machine not be
+unduly compromised, the C language leaves the order
+of evaluation of complicated expressions up to the
+local compiler, and, in fact, the various C compilers have considerable
+differences in the order in which they will evaluate complicated
+expressions.
+In particular, if any variable is changed by a side effect, and
+also used elsewhere in the same expression, the result is explicitly undefined.
+.PP
+.I Lint
+checks for the important special case where
+a simple scalar variable is affected.
+For example, the statement
+.DS
+\fIa\fR[\fIi\|\fR] = \fIb\fR[\fIi\fR++] ;
+.DE
+will draw the complaint:
+.DS
+warning: \fIi\fR evaluation order undefined
+.DE
+.SH
+Implementation
+.PP
+.I Lint
+consists of two programs and a driver.
+The first program is a version of the
+Portable C Compiler
+.[
+Johnson Ritchie BSTJ Portability Programs System
+.]
+.[
+Johnson portable compiler  1978
+.]
+which is the basis of the
+IBM 370, Honeywell 6000, and Interdata 8/32 C compilers.
+This compiler does lexical and syntax analysis on the input text,
+constructs and maintains symbol tables, and builds trees for expressions.
+Instead of writing an intermediate file which is passed to
+a code generator, as the other compilers
+do,
+.I lint
+produces an intermediate file which consists of lines of ascii text.
+Each line contains an external variable name,
+an encoding of the context in which it was seen (use, definition, declaration, etc.),
+a type specifier, and a source file name and line number.
+The information about variables local to a function or file
+is collected
+by accessing the symbol table, and examining the expression trees.
+.PP
+Comments about local problems are produced as detected.
+The information about external names is collected
+onto an intermediate file.
+After all the source files and library descriptions have
+been collected, the intermediate file is sorted
+to bring all information collected about a given external
+name together.
+The second, rather small, program then reads the lines
+from the intermediate file and compares all of the
+definitions, declarations, and uses for consistency.
+.PP
+The driver controls this
+process, and is also responsible for making the options available
+to both passes of
+.I lint .
+.SH
+Portability
+.PP
+C on the Honeywell and IBM systems is used, in part, to write system code for the host operating system.
+This means that the implementation of C tends to follow local conventions rather than
+adhere strictly to
+.UX
+system conventions.
+Despite these differences, many C programs have been successfully moved to GCOS and the various IBM
+installations with little effort.
+This section describes some of the differences between the implementations, and
+discusses the
+.I lint
+features which encourage portability.
+.PP
+Uninitialized external variables are treated differently in different
+implementations of C.
+Suppose two files both contain a declaration without initialization, such as
+.DS
+int a ;
+.DE
+outside of any function.
+The
+.UX
+loader will resolve these declarations, and cause only a single word of storage
+to be set aside for \fIa\fR.
+Under the GCOS and IBM implementations, this is not feasible (for various stupid reasons!)
+so each such declaration causes a word of storage to be set aside and called \fIa\fR.
+When loading or library editing takes place, this causes fatal conflicts which prevent
+the proper operation of the program.
+If
+.I lint
+is invoked with the \fB\-p\fR flag,
+it will detect such multiple definitions.
+.PP
+A related difficulty comes from the amount of information retained about external names during the
+loading process.
+On the
+.UX
+system, externally known names have seven significant characters, with the upper/lower
+case distinction kept.
+On the IBM systems, there are eight significant characters, but the case distinction
+is lost.
+On GCOS, there are only six characters, of a single case.
+This leads to situations where programs run on the
+.UX
+system, but encounter loader
+problems on the IBM or GCOS systems.
+.I Lint
+.B \-p
+causes all external symbols to be mapped to one case and truncated to six characters,
+providing a worst-case analysis.
+.PP
+A number of differences arise in the area of character handling: characters in the
+.UX
+system are eight bit ascii, while they are eight bit ebcdic on the IBM, and
+nine bit ascii on GCOS.
+Moreover, character strings go from high to low bit positions (``left to right'')
+on GCOS and IBM, and low to high (``right to left'') on the PDP-11.
+This means that code attempting to construct strings
+out of character constants, or attempting to use characters as indices
+into arrays, must be looked at with great suspicion.
+.I Lint
+is of little help here, except to flag multi-character character constants.
+.PP
+Of course, the word sizes are different!
+This causes less trouble than might be expected, at least when
+moving from the
+.UX
+system (16 bit words) to the IBM (32 bits) or GCOS (36 bits).
+The main problems are likely to arise in shifting or masking.
+C now supports a bit-field facility, which can be used to write much of
+this code in a reasonably portable way.
+Frequently, portability of such code can be enhanced by
+slight rearrangements in coding style.
+Many of the incompatibilities seem to have the flavor of writing
+.DS
+x &= 0177700 ;
+.DE
+to clear the low order six bits of \fIx\fR.
+This suffices on the PDP-11, but fails badly on GCOS and IBM.
+If the bit field feature cannot be used, the same effect can be obtained by
+writing
+.DS
+x &= \(ap 077 ;
+.DE
+which will work on all these machines.
+.PP
+The right shift operator is arithmetic shift on the PDP-11, and logical shift on most
+other machines.
+To obtain a logical shift on all machines, the left operand can be
+typed \fBunsigned\fR.
+Characters are considered signed integers on the PDP-11, and unsigned on the other machines.
+This persistence of the sign bit may be reasonably considered a bug in the PDP-11 hardware
+which has infiltrated itself into the C language.
+If there were a good way to discover the programs which would be affected, C could be changed;
+in any case,
+.I lint
+is no help here.
+.PP
+The above discussion may have made the problem of portability seem
+bigger than it in fact is.
+The issues involved here are rarely subtle or mysterious, at least to the
+implementor of the program, although they can involve some work to straighten out.
+The most serious bar to the portability of
+.UX
+system utilities has been the inability to mimic
+essential
+.UX
+system functions on the other systems.
+The inability to seek to a random character position in a text file, or to establish a pipe
+between processes, has involved far more rewriting
+and debugging than any of the differences in C compilers.
+On the other hand,
+.I lint
+has been very helpful
+in moving the
+.UX
+operating system and associated
+utility programs to other machines.
+.SH
+Shutting Lint Up
+.PP
+There are occasions when
+the programmer is smarter than
+.I lint .
+There may be valid reasons for ``illegal'' type casts,
+functions with a variable number of arguments, etc.
+Moreover, as specified above, the flow of control information
+produced by
+.I lint
+often has blind spots, causing occasional spurious
+messages about perfectly reasonable programs.
+Thus, some way of communicating with
+.I lint ,
+typically to shut it up, is desirable.
+.PP
+The form which this mechanism should take is not at all clear.
+New keywords would require current and old compilers to
+recognize these keywords, if only to ignore them.
+This has both philosophical and practical problems.
+New preprocessor syntax suffers from similar problems.
+.PP
+What was finally done was to cause a number of words
+to be recognized by
+.I lint
+when they were embedded in comments.
+This required minimal preprocessor changes;
+the preprocessor just had to agree to pass comments
+through to its output, instead of deleting them
+as had been previously done.
+Thus,
+.I lint
+directives are invisible to the compilers, and
+the effect on systems with the older preprocessors
+is merely that the
+.I lint
+directives don't work.
+.PP
+The first directive is concerned with flow of control information;
+if a particular place in the program cannot be reached,
+but this is not apparent to
+.I lint ,
+this can be asserted by the directive
+.DS
+/* NOTREACHED */
+.DE
+at the appropriate spot in the program.
+Similarly, if it is desired to turn off
+strict type checking for
+the next expression, the directive
+.DS
+/* NOSTRICT */
+.DE
+can be used; the situation reverts to the
+previous default after the next expression.
+The
+.B \-v
+flag can be turned on for one function by the directive
+.DS
+/* ARGSUSED */
+.DE
+Complaints about variable number of arguments in calls to a function
+can be turned off by the directive
+.DS
+/* VARARGS */
+.DE
+preceding the function definition.
+In some cases, it is desirable to check the
+first several arguments, and leave the later arguments unchecked.
+This can be done by following the VARARGS keyword immediately
+with a digit giving the number of arguments which should be checked; thus,
+.DS
+/* VARARGS2 */
+.DE
+will cause the first two arguments to be checked, the others unchecked.
+Finally, the directive
+.DS
+/* LINTLIBRARY */
+.DE
+at the head of a file identifies this file as
+a library declaration file; this topic is worth a
+section by itself.
+.SH
+Library Declaration Files
+.PP
+.I Lint
+accepts certain library directives, such as
+.DS
+\-ly
+.DE
+and tests the source files for compatibility with these libraries.
+This is done by accessing library description files whose
+names are constructed from the library directives.
+These files all begin with the directive
+.DS
+/* LINTLIBRARY */
+.DE
+which is followed by a series of dummy function
+definitions.
+The critical parts of these definitions
+are the declaration of the function return type,
+whether the dummy function returns a value, and
+the number and types of arguments to the function.
+The VARARGS and ARGSUSED directives can
+be used to specify features of the library functions.
+.PP
+.I Lint
+library files are processed almost exactly like ordinary
+source files.
+The only difference is that functions which are defined on a library file,
+but are not used on a source file, draw no complaints.
+.I Lint
+does not simulate a full library search algorithm,
+and complains if the source files contain a redefinition of
+a library routine (this is a feature!).
+.PP
+By default,
+.I lint
+checks the programs it is given against a standard library
+file, which contains descriptions of the programs which
+are normally loaded when
+a C program
+is run.
+When the
+.B -p
+flag is in effect, another file is checked containing
+descriptions of the standard I/O library routines
+which are expected to be portable across various machines.
+The
+.B -n
+flag can be used to suppress all library checking.
+.SH
+Bugs, etc.
+.PP
+.I Lint
+was a difficult program to write, partially
+because it is closely connected with matters of programming style,
+and partially because users usually don't notice bugs which cause
+.I lint
+to miss errors which it should have caught.
+(By contrast, if
+.I lint
+incorrectly complains about something that is correct, the
+programmer reports that immediately!)
+.PP
+A number of areas remain to be further developed.
+The checking of structures and arrays is rather inadequate;
+size
+incompatibilities go unchecked,
+and no attempt is made to match up structure and union
+declarations across files.
+Some stricter checking of the use of the
+.B typedef
+is clearly desirable, but what checking is appropriate, and how
+to carry it out, is still to be determined.
+.PP
+.I Lint
+shares the preprocessor with the C compiler.
+At some point it may be appropriate for a
+special version of the preprocessor to be constructed
+which checks for things such as unused macro definitions,
+macro arguments which have side effects which are
+not expanded at all, or are expanded more than once, etc.
+.PP
+The central problem with
+.I lint
+is the packaging of the information which it collects.
+There are many options which
+serve only to turn off, or slightly modify,
+certain features.
+There are pressures to add even more of these options.
+.PP
+In conclusion, it appears that the general notion of having two
+programs is a good one.
+The compiler concentrates on quickly and accurately turning the
+program text into bits which can be run;
+.I lint
+concentrates on issues
+of portability, style, and efficiency.
+.I Lint
+can afford to be wrong, since incorrectness and over-conservatism
+are merely annoying, not fatal.
+The compiler can be fast since it knows that
+.I lint
+will cover its flanks.
+Finally, the programmer can
+concentrate at one stage
+of the programming process solely on the algorithms,
+data structures, and correctness of the
+program, and then later retrofit,
+with the aid of
+.I lint ,
+the desirable properties of universality and portability.
+.SG MH-1273-SCJ-unix
+.bp
+.[
+$LIST$
+.]
+.bp
+.SH
+Appendix:   Current Lint Options
+.PP
+The command currently has the form
+.DS
+lint\fR [\fB\-\fRoptions ] files... library-descriptors...
+.DE
+The options are
+.IP \fBh\fR
+Perform heuristic checks
+.IP \fBp\fR
+Perform portability checks
+.IP \fBv\fR
+Don't report unused arguments
+.IP \fBu\fR
+Don't report unused or undefined externals
+.IP \fBb\fR
+Report unreachable
+.B break
+statements.
+.IP \fBx\fR
+Report unused external declarations
+.IP \fBa\fR
+Report assignments of
+.B long
+to
+.B int
+or shorter.
+.IP \fBc\fR
+Complain about questionable casts
+.IP \fBn\fR
+No library checking is done
+.IP \fBs\fR
+Same as
+.B h
+(for historical reasons)
diff --git a/doc/7thEdMan/vol2/m4 b/doc/7thEdMan/vol2/m4
new file mode 100644 (file)
index 0000000..673dcca
--- /dev/null
@@ -0,0 +1,929 @@
+.if n .ls 2
+.tr _\(em
+.tr *\(**
+.de UC
+\&\\$3\s-1\\$1\\s0\&\\$2
+..
+.de IT
+.if n .ul
+\&\\$3\f2\\$1\fP\&\\$2
+..
+.de UL
+.if n .ul
+\&\\$3\f3\\$1\fP\&\\$2
+..
+.de P1
+.DS I 3n
+.if n .ls 2
+.nf
+.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+.if t .ta .4i .8i 1.2i 1.6i 2i 2.4i 2.8i 3.2i 3.6i 4i 4.4i 4.8i 5.2i 5.6i
+.if t .tr -\(mi|\(bv'\(fm^\(no*\(**
+.tr `\(ga'\(aa
+.if t .tr _\(ul
+.ft 3
+.lg 0
+..
+.de P2
+.ps \\n(PS
+.vs \\n(VSp
+.ft R
+.if n .ls 2
+.tr --||''^^!!
+.if t .tr _\(em
+.fi
+.lg
+.DE
+.if t .tr _\(em
+..
+.hw semi-colon
+.hw estab-lished
+.hy 14
+.              \"2=not last lines; 4= no -xx; 8=no xx-
+.              \"special chars in programs
+.      \" start of text
+.RP
+.....TR 59
+.....TM 77-1273-6 39199 39199-11
+.ND "July 1, 1977"
+.TL
+The M4 Macro Processor
+.AU "MH 2C-518" 6021
+Brian W. Kernighan
+.AU "MH 2C-517" 3770
+Dennis M. Ritchie
+.AI
+.MH
+.AB
+.PP
+M4 is a macro processor available on
+.UX
+and
+.UC GCOS .
+Its primary use has been as a
+front end for Ratfor for those
+cases where parameterless macros 
+are not adequately powerful.
+It has also been used for languages as disparate as C and Cobol.
+M4 is particularly suited for functional languages like Fortran, PL/I and C
+since macros are specified in a functional notation.
+.PP
+M4 provides features seldom found even in much larger
+macro processors, 
+including
+.IP "  \(bu"
+arguments
+.IP "  \(bu"
+condition testing
+.IP "  \(bu"
+arithmetic capabilities
+.IP "  \(bu"
+string and substring functions
+.IP "  \(bu"
+file manipulation
+.LP
+.PP
+This paper is a user's manual for M4.
+.AE
+.CS 6 0 6 0 0 1
+.if t .2C
+.SH
+Introduction
+.PP
+A macro processor is a useful way to enhance a programming language,
+to make it more palatable
+or more readable,
+or to tailor it to a particular application.
+The
+.UL #define
+statement in C
+and the analogous
+.UL define
+in Ratfor
+are examples of the basic facility provided by
+any macro processor _
+replacement of text by other text.
+.PP
+The M4 macro processor is an extension of a macro processor called M3
+which was written by D. M. Ritchie
+for the AP-3 minicomputer;
+M3 was in turn based on a macro processor implemented for [1].
+Readers unfamiliar with the basic ideas of macro processing
+may wish to read some of the discussion there.
+.PP
+M4 is a suitable front end for Ratfor and C,
+and has also been used successfully with Cobol.
+Besides the straightforward replacement of one string of text by another,
+it provides
+macros with arguments,
+conditional macro expansion,
+arithmetic,
+file manipulation,
+and some specialized string processing functions.
+.PP
+The basic operation of M4
+is to copy its input to its output.
+As the input is read, however, each alphanumeric ``token''
+(that is, string of letters and digits) is checked.
+If it is the name of a macro,
+then the name of the macro is replaced by its defining text,
+and the resulting string is pushed back onto the
+input to be rescanned.
+Macros may be called with arguments, in which case the arguments are collected
+and substituted into the right places in the defining text
+before it is rescanned.
+.PP
+M4 provides a collection of about twenty built-in
+macros
+which perform various useful operations;
+in addition, the user can define new macros.
+Built-ins and user-defined macros work exactly the same way, except that
+some of the built-in macros have side effects
+on the state of the process.
+.SH
+Usage
+.PP
+On
+.UC UNIX ,
+use
+.P1
+m4 [files]
+.P2
+Each argument file is processed in order;
+if there are no arguments, or if an argument
+is `\-',
+the standard input is read at that point.
+The processed text is written on the standard output,
+which may be captured for subsequent processing with
+.P1
+m4 [files] >outputfile
+.P2
+On
+.UC GCOS ,
+usage is identical, but the program is called
+.UL \&./m4 .
+.SH
+Defining Macros
+.PP
+The primary built-in function of M4
+is
+.UL define ,
+which is used to define new macros.
+The input
+.P1
+define(name, stuff)
+.P2
+causes the string
+.UL name
+to be defined as
+.UL stuff .
+All subsequent occurrences of
+.UL name
+will be replaced by
+.UL stuff .
+.UL name
+must be alphanumeric and must begin with a letter
+(the underscore \(ul counts as a letter).
+.UL stuff
+is any text that contains balanced parentheses;
+it may stretch over multiple lines.
+.PP
+Thus, as a typical example,
+.P1
+define(N, 100)
+ ...
+if (i > N)
+.P2
+defines
+.UL N
+to be 100, and uses this ``symbolic constant'' in a later
+.UL if
+statement.
+.PP
+The left parenthesis must immediately follow the word
+.UL define ,
+to signal that
+.UL define
+has arguments.
+If a macro or built-in name is not followed immediately by `(',
+it is assumed to have no arguments.
+This is the situation for
+.UL N
+above;
+it is actually a macro with no arguments,
+and thus when it is used there need be no (...) following it.
+.PP
+You should also notice that a macro name is only recognized as such
+if it appears surrounded by non-alphanumerics.
+For example, in
+.P1
+define(N, 100)
+ ...
+if (NNN > 100)
+.P2
+the variable 
+.UL NNN
+is absolutely unrelated to the defined macro
+.UL N ,
+even though it contains a lot of
+.UL N 's.
+.PP
+Things may be defined in terms of other things.
+For example,
+.P1
+define(N, 100)
+define(M, N)
+.P2
+defines both M and N to be 100.
+.PP
+What happens if
+.UL N
+is redefined?
+Or, to say it another way, is
+.UL M 
+defined as
+.UL N
+or as 100?
+In M4,
+the latter is true _
+.UL M
+is 100, so even if
+.UL N 
+subsequently changes,
+.UL M
+does not.
+.PP
+This behavior arises because
+M4 expands macro names into their defining text as soon as it possibly can.
+Here, that means that when the string
+.UL N
+is seen as the arguments of
+.UL define
+are being collected, it is immediately replaced by 100;
+it's just as if you had said
+.P1
+define(M, 100)
+.P2
+in the first place.
+.PP
+If this isn't what you really want, there are two ways out of it.
+The first, which is specific to this situation,
+is to interchange the order of the definitions:
+.P1
+define(M, N)
+define(N, 100)
+.P2
+Now
+.UL M
+is defined to be the string
+.UL N ,
+so when you ask for 
+.UL M
+later, you'll always get the value of
+.UL N 
+at that time
+(because the
+.UL M
+will be replaced by
+.UL N
+which will be replaced by 100).
+.SH
+Quoting
+.PP
+The more general solution is to delay the expansion of
+the arguments of
+.UL define 
+by
+.ul
+quoting
+them.
+Any text surrounded by the single quotes \(ga and \(aa
+is not expanded immediately, but has the quotes stripped off.
+If you say
+.P1
+define(N, 100)
+define(M, `N')
+.P2
+the quotes around the
+.UL N
+are stripped off as the argument is being collected,
+but they have served their purpose, and 
+.UL M
+is defined as
+the string
+.UL N ,
+not 100.
+The general rule is that M4 always strips off
+one level of single quotes whenever it evaluates
+something.
+This is true even outside of
+macros.
+If you want the word
+.UL define
+to appear in the output,
+you have to quote it in the input,
+as in
+.P1
+       `define' = 1;
+.P2
+.PP
+As another instance of the same thing, which is a bit more surprising,
+consider redefining
+.UL N :
+.P1
+define(N, 100)
+ ...
+define(N, 200)
+.P2
+Perhaps regrettably, the
+.UL N
+in the second definition is
+evaluated as soon as it's seen;
+that is, it is
+replaced by
+100, so it's as if you had written
+.P1
+define(100, 200)
+.P2
+This statement is ignored by M4, since you can only define things that look
+like names, but it obviously doesn't have the effect you wanted.
+To really redefine 
+.UL N ,
+you must delay the evaluation by quoting:
+.P1
+define(N, 100)
+ ...
+define(`N', 200)
+.P2
+In M4,
+it is often wise to quote the first argument of a macro.
+.PP
+If \` and \' are not convenient for some reason,
+the quote characters can be changed with the built-in
+.UL changequote :
+.P1
+changequote([, ])
+.P2
+makes the new quote characters the left and right brackets.
+You can restore the original characters with just
+.P1
+changequote
+.P2
+.PP
+There are two additional built-ins related to
+.UL define .
+.UL undefine
+removes the definition of some macro or built-in:
+.P1
+undefine(`N')
+.P2
+removes the definition of
+.UL N .
+(Why are the quotes absolutely necessary?)
+Built-ins can be removed with 
+.UL undefine ,
+as in
+.P1
+undefine(`define')
+.P2
+but once you remove one, you can never get it back.
+.PP
+The built-in 
+.UL ifdef
+provides a way to determine if a macro is currently defined.
+In particular, M4 has pre-defined the names
+.UL unix
+and
+.UL gcos
+on the corresponding systems, so you can
+tell which one you're using:
+.P1
+ifdef(`unix', `define(wordsize,16)' )
+ifdef(`gcos', `define(wordsize,36)' )
+.P2
+makes a definition appropriate for the particular machine.
+Don't forget the quotes!
+.PP
+.UL ifdef
+actually permits three arguments;
+if the name is undefined, the value of
+.UL ifdef
+is then the third argument, as in
+.P1
+ifdef(`unix', on UNIX, not on UNIX)
+.P2
+.SH
+Arguments
+.PP
+So far we have discussed the simplest form of macro processing _
+replacing one string by another (fixed) string.
+User-defined macros may also have arguments, so different invocations
+can have different results.
+Within the replacement text for a macro
+(the second argument of its
+.UL define )
+any occurrence of
+.UL $n
+will be replaced by the 
+.UL n th
+argument when the macro
+is actually used.
+Thus, the macro
+.UL bump ,
+defined as
+.P1
+define(bump, $1 = $1 + 1)
+.P2
+generates code to increment its argument by 1:
+.P1
+bump(x)
+.P2
+is
+.P1
+x = x + 1
+.P2
+.PP
+A macro can have as many arguments as you want,
+but only the first nine are accessible,
+through
+.UL $1
+to
+.UL $9 .
+(The macro name itself is
+.UL $0 ,
+although that is less commonly used.)
+Arguments that are not supplied are replaced by null strings,
+so
+we can define a macro
+.UL cat
+which simply concatenates its arguments, like this:
+.P1
+define(cat, $1$2$3$4$5$6$7$8$9)
+.P2
+Thus
+.P1
+cat(x, y, z)
+.P2
+is equivalent to
+.P1
+xyz
+.P2
+.UL $4
+through
+.UL $9
+are null, since no corresponding arguments were provided.
+.PP
+.PP
+Leading unquoted blanks, tabs, or newlines that occur during argument collection
+are discarded.
+All other white space is retained.
+Thus
+.P1
+define(a,   b   c)
+.P2
+defines
+.UL a
+to be
+.UL b\ \ \ c .
+.PP
+Arguments are separated by commas, but parentheses are counted properly,
+so a comma ``protected'' by parentheses does not terminate an argument.
+That is, in
+.P1
+define(a, (b,c))
+.P2
+there are only two arguments;
+the second is literally
+.UL (b,c) .
+And of course a bare comma or parenthesis can be inserted by quoting it.
+.SH
+Arithmetic Built-ins
+.PP
+M4 provides two built-in functions for doing arithmetic
+on integers (only).
+The simplest is
+.UL incr ,
+which increments its numeric argument by 1.
+Thus to handle the common programming situation
+where you want a variable to be defined as ``one more than N'',
+write
+.P1
+define(N, 100)
+define(N1, `incr(N)')
+.P2
+Then
+.UL N1
+is defined as one more than the current value of
+.UL N .
+.PP
+The more general mechanism for arithmetic is a built-in
+called
+.UL eval ,
+which is capable of arbitrary arithmetic on integers.
+It provides the operators
+(in decreasing order of precedence)
+.DS
+unary + and \(mi
+** or ^        (exponentiation)
+*  /  % (modulus)
++  \(mi
+==  !=  <  <=  >  >=
+!              (not)
+& or &&        (logical and)
+\(or or \(or\(or               (logical or)
+.DE
+Parentheses may be used to group operations where needed.
+All the operands of
+an expression given to
+.UL eval
+must ultimately be numeric.
+The numeric value of a true relation
+(like 1>0)
+is 1, and false is 0.
+The precision in
+.UL eval
+is
+32 bits on
+.UC UNIX
+and 36 bits on
+.UC GCOS .
+.PP
+As a simple example, suppose we want 
+.UL M
+to be 
+.UL 2**N+1 .
+Then
+.P1
+define(N, 3)   
+define(M, `eval(2**N+1)')
+.P2
+As a matter of principle, it is advisable
+to quote the defining text for a macro
+unless it is very simple indeed
+(say just a number);
+it usually gives the result you want,
+and is a good habit to get into.
+.SH
+File Manipulation
+.PP
+You can include a new file in the input at any time by
+the built-in function
+.UL include :
+.P1
+include(filename)
+.P2
+inserts the contents of
+.UL filename
+in place of the
+.UL include
+command.
+The contents of the file is often a set of definitions.
+The value
+of
+.UL include
+(that is, its replacement text)
+is the contents of the file;
+this can be captured in definitions, etc.
+.PP
+It is a fatal error if the file named in
+.UL include
+cannot be accessed.
+To get some control over this situation, the alternate form
+.UL sinclude
+can be used;
+.UL sinclude 
+(``silent include'')
+says nothing and continues if it can't access the file.
+.PP
+It is also possible to divert the output of M4 to temporary files during processing,
+and output the collected material upon command.
+M4 maintains nine of these diversions, numbered 1 through 9.
+If you say
+.P1
+divert(n)
+.P2
+all subsequent output is put onto the end of a temporary file
+referred to as
+.UL n .
+Diverting to this file is stopped by another 
+.UL divert 
+command;
+in particular,
+.UL divert
+or
+.UL divert(0)
+resumes the normal output process.
+.PP
+Diverted text is normally output all at once
+at the end of processing,
+with the diversions output in numeric order.
+It is possible, however, to bring back diversions
+at any time,
+that is, to append them to the current diversion.
+.P1
+undivert
+.P2
+brings back all diversions in numeric order, and
+.UL undivert
+with arguments brings back the selected diversions
+in the order given.
+The act of undiverting discards the diverted stuff,
+as does diverting into a diversion 
+whose number is not between 0 and 9 inclusive.
+.PP
+The value of
+.UL undivert
+is
+.ul
+not
+the diverted stuff.
+Furthermore, the diverted material is
+.ul
+not
+rescanned for macros.
+.PP
+The built-in
+.UL divnum
+returns the number of the currently active diversion.
+This is zero during normal processing.
+.SH
+System Command
+.PP
+You can run any program in the local operating system
+with the
+.UL syscmd
+built-in.
+For example,
+.P1
+syscmd(date)
+.P2
+on
+.UC UNIX
+runs the
+.UL date
+command.
+Normally
+.UL syscmd
+would be used to create a file
+for a subsequent
+.UL include .
+.PP
+To facilitate making unique file names, the built-in
+.UL maketemp
+is provided, with specifications identical to the system function
+.ul
+mktemp:
+a string of XXXXX in the argument is replaced
+by the process id of the current process.
+.SH
+Conditionals
+.PP
+There is a built-in called
+.UL ifelse
+which enables you to perform arbitrary conditional testing.
+In the simplest form,
+.P1
+ifelse(a, b, c, d)
+.P2
+compares the two strings
+.UL a
+and
+.UL b .
+If these are identical, 
+.UL ifelse
+returns
+the string
+.UL c ;
+otherwise it returns
+.UL d .
+Thus we might define a macro called
+.UL compare
+which compares two strings and returns ``yes'' or ``no''
+if they are the same or different.
+.P1
+define(compare, `ifelse($1, $2, yes, no)')
+.P2
+Note the quotes,
+which prevent too-early evaluation of
+.UL ifelse .
+.PP
+If the fourth argument is missing, it is treated as empty.
+.PP
+.UL ifelse
+can actually have any number of arguments,
+and thus provides a limited form of multi-way decision capability.
+In the input
+.P1
+ifelse(a, b, c, d, e, f, g)
+.P2
+if the string
+.UL a
+matches the string
+.UL b ,
+the result is
+.UL c .
+Otherwise, if
+.UL d
+is the same as
+.UL e ,
+the result is
+.UL f .
+Otherwise the result is
+.UL g .
+If the final argument
+is omitted, the result is null,
+so
+.P1
+ifelse(a, b, c)
+.P2
+is
+.UL c
+if 
+.UL a
+matches
+.UL b ,
+and null otherwise.
+.SH
+String Manipulation
+.PP
+The built-in
+.UL len
+returns the length of the string that makes up its argument.
+Thus
+.P1
+len(abcdef)
+.P2
+is 6, and
+.UL len((a,b))
+is 5.
+.PP
+The built-in
+.UL substr
+can be used to produce substrings of strings.
+.UL substr(s,\ i,\ n)
+returns the substring of
+.UL s
+that starts at the
+.UL i th
+position
+(origin zero),
+and is
+.UL n
+characters long.
+If 
+.UL n
+is omitted, the rest of the string is returned,
+so
+.P1
+substr(`now is the time', 1)
+.P2
+is
+.P1
+ow is the time
+.P2
+If 
+.UL i
+or
+.UL n
+are out of range, various sensible things happen.
+.PP
+.UL index(s1,\ s2)
+returns the index (position) in
+.UL s1
+where the string
+.UL s2
+occurs, or \-1
+if it doesn't occur.
+As with
+.UL substr ,
+the origin for strings is 0.
+.PP
+The built-in
+.UL translit
+performs character transliteration.
+.P1
+translit(s, f, t)
+.P2
+modifies
+.UL s
+by replacing any character found in
+.UL f
+by the corresponding character of
+.UL t .
+That is,
+.P1
+translit(s, aeiou, 12345)
+.P2
+replaces the vowels by the corresponding digits.
+If
+.UL t
+is shorter than
+.UL f ,
+characters which don't have an entry in
+.UL t
+are deleted; as a limiting case,
+if
+.UL t
+is not present at all,
+characters from 
+.UL f
+are deleted from 
+.UL s .
+So
+.P1
+translit(s, aeiou)
+.P2
+deletes vowels from 
+.UL s .
+.PP
+There is also a built-in called
+.UL dnl
+which deletes all characters that follow it up to
+and including the next newline;
+it is useful mainly for throwing away 
+empty lines that otherwise tend to clutter up M4 output.
+For example, if you say
+.P1
+define(N, 100)
+define(M, 200)
+define(L, 300)
+.P2
+the newline at the end of each line is not part of the definition,
+so it is copied into the output, where it may not be wanted.
+If you add
+.UL dnl
+to each of these lines, the newlines will disappear.
+.PP
+Another way to achieve this, due to J. E. Weythman,
+is
+.P1
+divert(-1)
+       define(...)
+       ...
+divert
+.P2
+.SH
+Printing
+.PP
+The built-in
+.UL errprint
+writes its arguments out on the standard error file.
+Thus you can say
+.P1
+errprint(`fatal error')
+.P2
+.PP
+.UL dumpdef
+is a debugging aid which
+dumps the current definitions of defined terms.
+If there are no arguments, you get everything;
+otherwise you get the ones you name as arguments.
+Don't forget to quote the names!
+.SH
+Summary of Built-ins
+.PP
+Each entry is preceded by the
+page number where it is described.
+.DS
+.tr '\'`\`
+.ta .25i
+3      changequote(L, R)
+1      define(name, replacement)
+4      divert(number)
+4      divnum
+5      dnl
+5      dumpdef(`name', `name', ...)
+5      errprint(s, s, ...)
+4      eval(numeric expression)
+3      ifdef(`name', this if true, this if false)
+5      ifelse(a, b, c, d)
+4      include(file)
+3      incr(number)
+5      index(s1, s2)
+5      len(string)
+4      maketemp(...XXXXX...)
+4      sinclude(file)
+5      substr(string, position, number)
+4      syscmd(s)
+5      translit(str, from, to)
+3      undefine(`name')
+4      undivert(number,number,...)
+.DE
+.SH
+Acknowledgements
+.PP
+We are indebted to Rick Becker, John Chambers,
+Doug McIlroy,
+and especially Jim Weythman,
+whose pioneering use of M4 has led to several valuable improvements.
+We are also deeply grateful to Weythman for several substantial contributions
+to the code.
+.SG
+.SH
+References
+.LP
+.IP [1]
+B. W. Kernighan and P. J. Plauger,
+.ul
+Software Tools,
+Addison-Wesley, Inc., 1976.
diff --git a/doc/7thEdMan/vol2/make b/doc/7thEdMan/vol2/make
new file mode 100644 (file)
index 0000000..3c87758
--- /dev/null
@@ -0,0 +1,791 @@
+.....TR 57
+.ND August 15, 1978
+.RP
+.de IT
+.if n .ul
+\&\\$3\f2\\$1\fR\^\&\\$2
+..
+.TL
+Make \(em A Program for Maintaining Computer Programs
+.AU
+S. I. Feldman
+.AI
+.MH
+.AB
+.PP
+In a programming project, it is easy to lose track of which files need
+to be reprocessed or recompiled after a change is made in some part of the source.
+.I Make
+provides a simple mechanism for maintaining up-to-date versions of programs that result
+from many operations on a number of files.
+It is possible to tell
+.I Make
+the sequence of commands that create certain files,
+and the list of files that require other files to be current before the operations can be done.
+Whenever a change is made in any part of the program,
+the
+.I Make
+command will create the proper files simply, correctly,
+and with a minimum amount of effort.
+.PP
+The basic operation of
+.I Make
+is to find the name of a needed target in the description, ensure that all of the files on which it depends exist and
+are up to date, and then create the target if it has not been modified since its generators were.
+The description file really defines the graph of dependencies;
+.I Make
+does a depth-first search of this graph
+to determine what work is really necessary.
+.PP
+.I Make
+also provides a simple macro substitution facility
+and the ability to encapsulate commands in a single file
+for convenient administration.
+.AE
+.SH
+Introduction
+.PP
+It is common practice to divide large programs into smaller, more manageable pieces.
+The pieces may require quite different treatments:
+some may need to be run through a macro processor, some may need to be processed by
+a sophisticated program generator (e.g., Yacc[1] or Lex[2]).
+The outputs of these generators may then have to be compiled with special options and with
+certain definitions and declarations.
+The code resulting from these transformations may then need to be loaded together with
+certain libraries under the control of special options.
+Related maintenance activities involve running complicated test scripts
+and installing validated modules.
+Unfortunately, it is very easy for a programmer to forget which files depend on which others,
+which files have been modified recently, and the exact sequence of operations
+needed to make or exercise a new version of the program.
+After a long editing session, one may easily lose track of which files have been changed
+and which object modules are still valid,
+since a change to a declaration can obsolete a dozen other files.
+Forgetting to compile a routine that has been changed or that uses changed declarations will result in
+a program that will not work, and a bug that can be very hard to track down.
+On the other hand, recompiling everything in sight just to be safe is very wasteful.
+.PP
+The program described in this report mechanizes many of the activities of program development
+and maintenance.
+If the information on inter-file dependences and command sequences is stored in a file, the simple command
+.DS
+make
+.DE
+is frequently sufficient to update the interesting files,
+regardless of the number that have been edited since the last ``make''.
+In most cases, the description file is easy to write and changes infrequently.
+It is usually easier to type the
+.IT make
+command than to issue even one of the needed operations, so the typical cycle of program development operations becomes
+.DS
+think \(em edit \(em \fImake\fR \(em test  . . .
+.DE
+.PP
+.IT Make
+is most useful for medium-sized programming projects;
+it does not solve the problems of maintaining multiple source versions
+or of describing huge programs.
+.IT Make
+was designed for use on Unix, but a version runs on GCOS.
+.SH
+Basic Features
+.PP
+The basic operation of
+.IT make
+is to update a target file by ensuring
+that all of the files on which it depends exist and are up to date,
+then creating the target if it has not been modified since its dependents were.
+.IT Make
+does a depth-first search of the graph of dependences.
+The operation of the command depends on the ability to find the date and time
+that a file was last modified.
+.PP
+To illustrate, let us consider a simple example:
+A program named
+.IT prog
+is made by compiling and loading three C-language files
+.IT x.c ,
+.IT y.c ,
+and
+.IT z.c
+with the
+.IT lS
+library.
+By convention, the output of the C compilations will be found in files named
+.IT x.o ,
+.IT y.o ,
+and
+.IT z.o .
+Assume that the files
+.IT x.c
+and
+.IT y.c
+share some declarations in a file named
+.IT defs ,
+but that
+.IT z.c
+does not.
+That is,
+.IT x.c
+and
+.IT y.c
+have the line
+.DS
+#include "defs"
+.DE
+The following text describes the relationships and operations:
+.DS
+prog :  x.o  y.o  z.o
+       cc  x.o  y.o  z.o   \-lS  \-o  prog
+.sp .5
+x.o  y.o :   defs
+.DE
+If this information were stored in a file named
+.IT makefile ,
+the command
+.DS
+make
+.DE
+would perform the operations needed to recreate
+.IT prog
+after any changes had been made to any of the four source files
+.IT x.c ,
+.IT y.c ,
+.IT z.c ,
+or
+.IT defs .
+.PP
+.IT Make
+operates using three sources of information:
+a user-supplied description file (as above),
+file names and ``last-modified'' times from the file system,
+and built-in rules to bridge some of the gaps.
+In our example, the first line says that
+.IT prog
+depends on three ``\fI.o\fR'' files.
+Once these object files are current, the second line describes how to load them to create
+.IT prog .
+The third line says that
+.IT x.o
+and
+.IT y.o
+depend on the file
+.IT defs .
+From the file system,
+.IT make
+discovers that there are three ``\fI.c\fR'' files corresponding to the needed ``\fI.o\fR'' files,
+and uses built-in information on how to generate an object from a source file
+(\fIi.e.,\fR issue a ``cc\ \-c'' command).
+.PP
+The following long-winded description file is equivalent to the one above, but
+takes no advantage of
+.IT make 's
+innate knowledge:
+.DS
+prog :  x.o  y.o  z.o
+       cc  x.o  y.o  z.o  \-lS  \-o  prog
+.sp .3
+x.o :  x.c  defs
+       cc  \-c  x.c
+y.o :  y.c  defs
+       cc  \-c  y.c
+z.o :  z.c
+       cc  \-c  z.c
+.DE
+.PP
+If none of the source or object files had changed since the last time
+.IT prog
+was made, all of the files would be current, and
+the command
+.DS
+make
+.DE
+would just announce this fact and stop.
+If, however, the
+.IT defs
+file had been edited,
+.IT x.c
+and
+.IT y.c
+(but not
+.IT z.c )
+would be recompiled, and then
+.IT prog
+would be created from the new ``\fI.o\fR'' files.
+If only the file
+.IT y.c
+had changed, only it would be recompiled, but it would still be necessary to reload
+.IT prog .
+.PP
+If no target name is given on the
+.IT make
+command line, the first target mentioned in the description is created;
+otherwise the specified targets are made.
+The command
+.DS
+make x.o
+.DE
+would recompile
+.IT x.o
+if
+.IT x.c
+or
+.IT defs
+had changed.
+.PP
+If the file exists after the commands are executed,
+its time of last modification is used in further decisions;
+otherwise the current time is used.
+It is often quite useful to include rules with mnemonic names and commands that do not
+actually produce a file with that name.
+These entries can take advantage of
+.IT make 's
+ability to generate files and substitute macros.
+Thus, an entry
+``save''
+might be included to copy a certain set of files, or an entry
+``cleanup''
+might be used to throw away unneeded intermediate files.
+In other cases one may maintain a zero-length file purely to keep track
+of the time at which certain actions were performed.
+This technique is useful for maintaining remote archives and listings.
+.PP
+.IT Make
+has a simple macro mechanism for substituting in dependency lines and command strings.
+Macros are defined by command arguments or description file lines with embedded equal signs.
+A macro is invoked by preceding the name by a dollar sign;
+macro names longer than one character must be parenthesized.
+The name of the macro is either the single character after the dollar sign or a name inside parentheses.
+The following are valid macro invocations:
+.DS
+$(CFLAGS)
+$2
+$(xy)
+$Z
+$(Z)
+.DE
+The last two invocations are identical.
+$$ is a dollar sign.
+All of these macros are assigned values during input, as shown below.
+Four special macros change values during the execution of the command:
+$\(**, $@, $?, and $<.
+They will be discussed later.
+The following fragment shows the use:
+.DS
+OBJECTS = x.o y.o z.o
+LIBES = \-lS
+prog: $(OBJECTS)
+       cc $(OBJECTS)  $(LIBES)  \-o prog
+  . . .
+.DE
+The command
+.DS
+make
+.DE
+loads the three object files with the
+.IT lS
+library.  The command
+.DS
+make  "LIBES= \-ll \-lS"
+.DE
+loads them with both the Lex (``\-ll'') and the Standard (``\-lS'') libraries,
+since macro definitions on the command line override definitions in the description.
+(It is necessary to quote arguments with embedded blanks in
+.UX
+commands.)
+.PP
+The following sections detail the form of description files and the command line,
+and discuss options and built-in rules in more detail.
+.SH
+Description Files and Substitutions
+.PP
+A description file contains three types of information:
+macro definitions,
+dependency information,
+and executable commands.
+There is also a comment convention:
+all characters after a sharp (#) are ignored, as is the sharp itself.
+Blank lines and lines beginning with a sharp are totally ignored.
+If a non-comment line is too long, it can be continued using a backslash.
+If the last character of a line is a backslash, the backslash, newline,
+and following blanks and tabs are replaced by a single blank.
+.PP
+A macro definition is a line containing an equal sign not preceded by a colon or a tab.
+The name (string of letters and digits) to the left of the equal sign
+(trailing blanks and tabs are stripped) is assigned the string of characters following the equal sign
+(leading blanks and tabs are stripped.)
+The following are valid macro definitions:
+.DS
+2 = xyz
+abc = \-ll \-ly \-lS
+LIBES =
+.DE
+The last definition assigns LIBES the null string.
+A macro that is never explicitly defined has the null string as value.
+Macro definitions may also appear on the
+.IT make
+command line (see below).
+.PP
+Other lines give information about target files.
+The general form of an entry is:
+.DS
+target1 [target2 . . .] :[:] [dependent1 . . .] [; commands] [# . . .]
+[\fI(tab)\fR commands] [# . . .]
+ . . .
+.DE
+Items inside brackets may be omitted.
+Targets and dependents are strings of letters, digits, periods, and slashes.
+(Shell metacharacters ``\(**'' and ``?'' are expanded.)
+A command is any string of characters not including a sharp (except in quotes)
+or newline.
+Commands may appear either after a semicolon on a dependency line
+or on lines beginning with a tab immediately following a dependency line.
+.PP
+A dependency line may have either a single or a double colon.
+A target name may appear on more than one dependency line, but all of those lines must be of the
+same (single or double colon) type.
+.IP 1.
+For the usual single-colon case,
+at most one of these dependency lines may have a command sequence associated with it.
+If the target is out of date with any of the dependents on any of the lines,
+and a command sequence is specified (even a null one following a semicolon or tab),
+it is executed; otherwise a default creation rule may be invoked.
+.IP 2.
+In the double-colon case, a command sequence may be associated with each dependency line;
+if the target is out of date with any of the files on a particular line, the associated
+commands are executed.
+A built-in rule may also be executed.
+This detailed form is of particular value in updating archive-type files.
+.PP
+If a target must be created, the sequence of commands is executed.
+Normally, each command line is printed and then
+passed to a separate invocation of the Shell after substituting for macros.
+(The printing is suppressed in silent mode or if the command line begins with an @ sign).
+.IT Make
+normally stops if any command signals an error by returning a non-zero error code.
+(Errors are ignored if the ``\-i'' flags has been specified on the
+.IT make
+command line,
+if the fake target name ``.IGNORE'' appears in the description file,
+or if the command string in the description file begins with a hyphen.
+Some
+.UX
+commands return meaningless status).
+Because each command line is passed to a separate invocation of the Shell,
+care must be taken with certain commands (e.g., \fIcd\fR and Shell control commands) that have meaning only
+within a single Shell process;
+the results are forgotten before the next line is executed.
+.PP
+Before issuing any command, certain macros are set.
+$@ is set to the name of the file to be ``made''.
+$? is set to the string of names that were found to be younger than the target.
+If the command was generated by an implicit rule (see below),
+$< is the name of the related file that caused the action, and
+$\(** is the prefix shared by the current and the dependent file names.
+.PP
+If a file must be made but there are no explicit commands or relevant
+built-in rules,
+the commands associated with the name ``.DEFAULT'' are used.
+If there is no such name,
+.IT make
+prints a message and stops.
+.SH
+Command Usage
+.PP
+The
+.IT make
+command takes four kinds of arguments:
+macro definitions, flags, description file names, and target file names.
+.DS
+make [ flags ]  [ macro definitions ]  [ targets ]
+.DE
+The following summary of the operation of the command explains how these arguments are interpreted.
+.PP
+First, all macro definition arguments (arguments with embedded equal signs) are analyzed
+and the assignments made.
+Command-line macros override corresponding definitions found in the description files.
+.PP
+Next, the flag arguments are examined.
+The permissible flags are
+.IP \-i
+Ignore error codes returned by invoked commands.
+This mode is entered if the fake target name ``.IGNORE'' appears in the description file.
+.IP \-s
+Silent mode.  Do not print command lines before executing.
+This mode is also entered if the fake target name ``.SILENT'' appears in the description file.
+.IP \-r
+Do not use the built-in rules.
+.IP \-n
+No execute mode.  Print commands, but do not execute them.
+Even lines beginning with an ``@'' sign are printed.
+.IP \-t
+Touch the target files (causing them to be up to date) rather than issue the usual commands.
+.IP \-q
+Question.
+The
+.IT make
+command returns a zero or non-zero status code depending on whether the target file
+is or is not up to date.
+.IP \-p
+Print out the complete set of macro definitions and target descriptions
+.IP \-d
+Debug mode.  Print out detailed information on files and times examined.
+.IP \-f
+Description file name.  The next argument is assumed to be the name of a description file.
+A file name of ``\-'' denotes the standard input.
+If there are no ``\-f\|'' arguments, the file named
+.IT makefile
+or
+.IT Makefile
+in the current directory is read.
+The contents of the description files override the built-in rules if they are present).
+.PP
+Finally, the remaining arguments are assumed to be the names of targets to be made;
+they are done in left to right order.
+If there are no such arguments, the first name in the description files that does not
+begin with a period is ``made''.
+.SH
+Implicit Rules
+.PP
+The
+.ul
+make
+program uses a table of interesting suffixes and a set
+of transformation rules to supply default dependency
+information and implied commands.
+(The Appendix describes these tables and means of overriding
+them.)
+The default suffix list is:
+.KS
+.sp
+.nf
+.ta 0.5i 1.5i
+       \fI.o\fR        Object file
+       \fI.c\fR        C source file
+       \fI.e\fR        Efl source file
+       \fI.r\fR        Ratfor source file
+       \fI.f\fR        Fortran source file
+       \fI.s\fR        Assembler source file
+       \fI.y\fR        Yacc-C source grammar
+       \fI.yr\fR       Yacc-Ratfor source grammar
+       \fI.ye\fR       Yacc-Efl source grammar
+       \fI.l\fR        Lex source grammar
+.fi
+.sp
+.KE
+The following diagram summarizes the default transformation paths.
+If there are two paths connecting a pair of suffixes, the longer
+one is used only if the intermediate file exists or is
+named in the description.
+.KS
+.sp
+.ft I
+.ta 2i
+       .o
+.sp 2
+.ta 0.75i 1.25i 1.6i 2.1i
+       .c      .r      .e      .f  .s  .y  .yr  .ye  .l  .d
+.sp 2
+.ta 0.6i 1.25i 1.6i
+       .y .l   .yr     .ye
+.ft R
+.sp
+.KE
+.PP
+If the file
+.ul
+x.o
+were needed and there were an
+.ul
+x.c
+in the description or directory, it would be compiled.
+If there were also an
+.IT x.l ,
+that grammar would be run through Lex before compiling the result.
+However, if there were no
+.ul
+x.c
+but there were an
+.IT x.l ,
+.IT make
+would discard the intermediate C-language file and use the
+direct link in the graph above.
+.PP
+It is possible to change the names of some of the compilers used in the
+default, or the flag arguments with which they are invoked by knowing
+the macro names used.
+The compiler names are the macros AS, CC, RC, EC, YACC, YACCR, YACCE, and LEX.
+The command
+.DS
+make CC=newcc
+.DE
+will cause the ``newcc'' command to be used instead of the
+usual C compiler.
+The macros CFLAGS, RFLAGS, EFLAGS, YFLAGS, and LFLAGS may be set to
+cause these commands to be issued with optional flags.
+Thus,
+.DS
+make "CFLAGS=\|\(miO"
+.DE
+causes the optimizing C compiler to be used.
+.SH
+Example
+.PP
+As an example of the use of
+.ul
+make,
+we will present the description file used to maintain
+the
+.ul
+make
+command itself.
+The code for
+.ul
+make
+is spread over a number of C source files and a Yacc grammar.
+The description file contains:
+.DS
+# Description file for the Make command
+.sp .3
+P = und \-3 | opr \-r2       # send to GCOS to be printed
+FILES = Makefile version.c defs main.c doname.c misc.c files.c dosys.c\
+       gram.y lex.c gcos.c
+OBJECTS = version.o main.o doname.o misc.o files.o dosys.o gram.o
+LIBES= \-lS
+LINT = lint \-p
+CFLAGS = \-O
+.sp .3
+make:  $(OBJECTS)
+       cc $(CFLAGS) $(OBJECTS) $(LIBES) \-o make
+       size make
+.sp .3
+$(OBJECTS):  defs
+gram.o: lex.c
+.sp .3
+cleanup:
+       -rm *.o gram.c
+       -du
+.sp .3
+install:
+       @size make /usr/bin/make
+       cp make /usr/bin/make ; rm make
+.sp .3
+print:  $(FILES)       # print recently changed files
+       pr $? | $P
+       touch print
+.sp .3
+test:
+       make \-dp | grep \-v TIME >1zap
+       /usr/bin/make \-dp | grep \-v TIME >2zap
+       diff 1zap 2zap
+       rm 1zap 2zap
+.sp .3
+lint :  dosys.c doname.c files.c main.c misc.c version.c gram.c
+       $(LINT) dosys.c doname.c files.c main.c misc.c version.c gram.c
+       rm gram.c
+.sp .3
+arch:
+       ar uv /sys/source/s2/make.a $(FILES)
+.DE
+.IT Make
+usually prints out each command before issuing it.
+The following output results from typing the simple command
+.DS
+make
+.DE
+in a directory containing only the source and description file:
+.DS
+ cc  \-c version.c
+ cc  \-c main.c
+ cc  \-c doname.c
+ cc  \-c misc.c
+ cc  \-c files.c
+ cc  \-c dosys.c
+ yacc  gram.y
+ mv y.tab.c gram.c
+ cc  \-c gram.c
+ cc  version.o main.o doname.o misc.o files.o dosys.o gram.o \-lS \-o make
+ 13188+3348+3044 = 19580b = 046174b
+.DE
+Although none of the source files or grammars were mentioned
+by name in the description file,
+.IT make
+found them using its suffix rules and issued the needed commands.
+The string of digits results from the ``size make''
+command; the printing of the command line itself was
+suppressed by an @ sign.
+The @ sign on the
+.IT size
+command in the description file suppressed the printing of the command,
+so only the sizes are written.
+.PP
+The last few entries in the description file are useful maintenance sequences.
+The ``print'' entry prints only the files that have been changed since the last
+``make print'' command.
+A zero-length file
+.IT print
+is maintained to keep track of the time of the printing;
+the $? macro in the command line then picks up only the names of the files
+changed since
+.IT print
+was touched.
+The printed output can be sent to a different printer or to a file by changing the definition of the
+.IT P
+macro:
+.DS
+make print "P = opr \-sp"
+       \fIor\fR
+make print "P=  cat >zap"
+.DE
+.SH
+Suggestions and Warnings
+.PP
+The most common difficulties arise from
+.IT make 's
+specific meaning of dependency.
+If file
+.IT x.c
+has a ``#include "defs"''
+line, then the object file
+.IT x.o
+depends on
+.IT defs ;
+the source file
+.IT x.c
+does not.
+(If
+.IT defs
+is changed, it is not necessary to do anything
+to the file
+.IT x.c ,
+while it is necessary to recreate
+.IT x.o .)
+.PP
+To discover what
+.IT make
+would do, the ``\-n'' option is very useful.
+The command
+.DS
+make \-n
+.DE
+orders
+.IT make
+to print out the commands it would issue without actually taking the time to execute them.
+If a change to a file is absolutely certain to be benign
+(e.g., adding a new definition to an include file),
+the ``\-t'' (touch) option
+can save a lot of time:
+instead of issuing a large number of superfluous recompilations,
+.IT make
+updates the modification times on the affected file.
+Thus, the command
+.DS
+make \-ts
+.DE
+(``touch silently'') causes the relevant files to appear up to date.
+Obvious care is necessary, since this mode of operation subverts
+the intention of
+.IT make
+and destroys all memory of the previous relationships.
+.PP
+The debugging flag (``\-d'') causes
+.IT make
+to print out a very detailed description of what it is doing, including the
+file times.  The output is verbose, and recommended only as a last resort.
+.SH
+Acknowledgments
+.PP
+I would like to thank S. C. Johnson for suggesting this approach
+to program maintenance control.
+I would like to thank S. C. Johnson and H. Gajewska for being
+the prime guinea pigs during development of
+.IT make .
+.SH
+References
+.IP 1.
+S. C. Johnson,
+``Yacc \(em Yet Another Compiler-Compiler'',
+Bell Laboratories
+Computing Science Technical Report #32,
+July 1978.
+.IP 2.
+M. E. Lesk,
+``Lex \(em A Lexical Analyzer Generator'',
+Computing Science Technical Report #39,
+October 1975.
+.bp
+.SH
+Appendix.  Suffixes and Transformation Rules
+.PP
+The
+.ul
+make
+program itself does not know what file name suffixes are interesting
+or how to transform a file with one suffix into a file with another
+suffix.
+This information is stored in an internal table that has the form of a description file.
+If the ``\-r'' flag is used, this table is not used.
+.PP
+The list of suffixes is actually the dependency list for the name
+``.SUFFIXES'';
+.ul
+make
+looks for a file with any of the suffixes on the list.
+If such a file exists, and if there is a transformation
+rule for that combination,
+.ul
+make
+acts as described earlier.
+The transformation rule names are the concatenation of the
+two suffixes.
+The name of the rule to transform a ``\fI.r\fR'' file to a ``\fI.o\fR'' file
+is thus ``\fI.r.o\fR''.
+If the rule is present and no explicit command sequence
+has been given in the user's description files, the command
+sequence for the rule ``.r.o'' is used.
+If a command is generated by using one of these suffixing rules,
+the macro $\(** is given the value of the stem
+(everything but the suffix) of the name of the file to be made,
+and the macro $< is the name of the dependent that caused the action.
+.PP
+The order of the suffix list is significant, since it is scanned from
+left to right, and the first name that is formed that has both a file
+and a rule associated with it is used.
+If new names are to be appended, the user can just add an entry for
+``.SUFFIXES'' in his own description file; the dependents will be added to the usual list.
+A ``.SUFFIXES'' line without any dependents deletes the current list.
+(It is necessary to clear the current list if the order of names is to be changed).
+.PP
+The following is an excerpt from the default rules file:
+.DS
+.ta .5i 1i
+ .SUFFIXES : .o .c .e .r .f .y .yr .ye .l .s
+ YACC=yacc
+ YACCR=yacc \-r
+ YACCE=yacc \-e
+ YFLAGS=
+ LEX=lex
+ LFLAGS=
+ CC=cc
+ AS=as \-
+ CFLAGS=
+ RC=ec
+ RFLAGS=
+ EC=ec
+ EFLAGS=
+ FFLAGS=
+ .c.o :
+       $(CC) $(CFLAGS) \-c $<
+ .e.o .r.o .f.o :
+       $(EC) $(RFLAGS) $(EFLAGS) $(FFLAGS) \-c $<
+ .s.o :
+       $(AS) \-o $@ $<
+ .y.o :
+       $(YACC) $(YFLAGS) $<
+       $(CC) $(CFLAGS) \-c y.tab.c
+       rm y.tab.c
+       mv y.tab.o $@
+ .y.c :
+       $(YACC) $(YFLAGS) $<
+       mv y.tab.c $@
+.DE
diff --git a/doc/7thEdMan/vol2/msmacros.bun b/doc/7thEdMan/vol2/msmacros.bun
new file mode 100644 (file)
index 0000000..0611dac
--- /dev/null
@@ -0,0 +1,2182 @@
+# To unbundle, run this file
+echo ms
+sed 's/.//' >ms <<'//GO.SYSIN DD ms'
+-.RP
+-....TM 76-1274-16 39199 39199-11
+-....ND October 8, 1976
+-.nr CW 2.85i
+-.nr GW .3i
+-.TL
+-Typing Documents on the UNIX System:
+-.br
+-\!.br
+-Using the \-ms Macros with Troff and Nroff
+-.AU "MH 2C-572" 6377
+-M. E. Lesk
+-.AI
+-.MH
+-.OK
+-Text Formatting
+-Phototypesetting
+-.AB
+-This document describes a set of easy-to-use macros
+-for preparing documents on the UNIX system.
+-Documents may be produced on either the
+-phototypesetter or a on a computer terminal,
+-without changing the input.
+-.PP
+-The macros provide facilities for paragraphs, sections (optionally
+-with automatic numbering), page titles, footnotes,
+-equations,
+-tables, two-column format, and
+-cover pages for papers.
+-.PP
+-This memo includes, as an appendix,
+-the text of the ``Guide to Preparing
+-Documents with \-ms''
+-which contains additional examples
+-of features of \-ms.
+-.PP
+-This manual is a revision of, and replaces,
+-``Typing Documents on UNIX,''
+-dated November 22, 1974.
+-.AE
+-.CS 6 6 12 1 0 8
+-.bd I 3
+-.PP
+-.I
+-Introduction.
+-.R
+-This memorandum describes a package of commands to produce
+-papers
+-using the
+-.bd I
+-.I
+-troff
+-.R
+-and
+-.I nroff
+-formatting programs on the
+-.SM
+-UNIX
+-.NL
+-system.
+-As with other
+-.I roff -derived
+-programs,
+-text is prepared interspersed with formatting commands.
+-However, this package,
+-which itself is written in
+-.I troff
+-commands,
+-provides higher-level commands
+-than those provided with the basic
+-.I troff
+-program.
+-The commands available in this package are listed in
+-Appendix A.
+-.bd I 3
+-.PP
+-.I
+-Text.
+-.R
+-Type normally, except that instead of indenting for paragraphs,
+-place a line reading ``.PP'' before each paragraph.
+-This will produce indenting and extra space.
+-.LP
+-Alternatively, the command .LP that was used here will produce
+-a left-aligned (block) paragraph.
+-The paragraph spacing can be changed: see below under ``Registers.''
+-.PP
+-.I
+-Beginning.
+-.R
+-For a document with a paper-type cover sheet, the input should start as follows:
+-.DS L
+-      [optional overall format .RP \- see below]
+-      .TL
+-      Title of document (one or more lines)
+-      .AU
+-      Author(s) (may also be several lines)
+-      .AI
+-      Author's institution(s)
+-      .AB
+-      Abstract; to be placed on the cover sheet of a paper.
+-      Line length is 5/6 of normal; use .ll here to change.
+-      .AE  (abstract end)
+-      text ... (begins with .PP, which see)
+-.DE
+-To omit some of the standard headings
+-(e.g. no abstract, or no author's institution) just
+-omit the corresponding fields and command lines.
+-The word
+-.SM
+-ABSTRACT
+-.NL
+-can be suppressed by writing ``.AB no'' for ``.AB''.
+-Several interspersed .AU and .AI lines can be used for multiple authors.
+-The headings are not compulsory: beginning
+-with a .PP command is perfectly OK and will just
+-start printing an ordinary paragraph.
+-.I Warning:
+-You can't just begin a document with a line of text.
+-Some \-ms command must
+-precede any text input.  When in doubt, use .LP
+-to get proper initialization, although any of
+-the commands .PP, .LP, .TL, .SH, .NH is good enough.
+-Figure 1 shows the legal arrangement of commands at the
+-start of a document.
+-.PP
+-.I
+-Cover Sheets and First Pages.
+-.R
+-The first line
+-of a document signals the general format of the first page.
+-In particular, if it is ".RP" a cover sheet with title and
+-abstract is prepared.
+-The default format
+-is useful for scanning drafts.
+-.PP
+-In general \-ms is arranged so that only one form
+-of a document need be stored, containing all
+-information;  the first command gives the format,
+-and unnecessary items for that format are ignored.
+-.PP
+-Warning: don't put extraneous material
+-between the .TL and .AE commands.  Processing
+-of the titling items is
+-special, and other data placed in them may not behave
+-as you expect.
+-Don't forget that some \-ms command must precede any input text.
+-.PP
+-.I
+-Page headings.
+-.R
+-The \-ms macros, by default, will print a page heading containing
+-a page number (if greater than 1).
+-A default page footer is provided only in
+-.I nroff ,
+-where the date is used.
+-The user can make minor adjustments to the page headings/footings
+-by redefining the
+-strings
+-LH, CH, and RH
+-which are the left, center and right portions of the page headings,
+-respectively; and the
+-strings
+-LF, CF, and RF,
+-which are the left, center and right portions of the page footer.
+-For more complex formats, the user can redefine
+-the macros PT and BT, which are invoked respectively at the top
+-and bottom of each page.
+-The margins (taken from registers HM and FM for the top and bottom
+-margin respectively) are normally 1 inch; the page header/footer are
+-in the middle of that space.
+-The user who redefines these macros should be careful
+-not to change parameters such as point size or font
+-without resetting them to default values.
+-.PP
+-.2C
+-.I
+-Multi-column formats.
+-.R
+-If you place the command ``.2C'' in your document, the document will
+-be printed in double column format beginning
+-at that point.  This feature is not too useful in computer
+-terminal output, but is often desirable on the typesetter.
+-The command ``.1C'' will go
+-back to one-column format and also skip to a new page.
+-The ``.2C'' command is actually a special case of the command
+-.DS L
+-      .MC [column width [gutter width]]
+-.DE
+-which makes multiple columns with the specified column
+-and gutter width; as many columns as will fit across the page
+-are used.
+-Thus triple, quadruple, ... column pages can be printed.
+-Whenever the number of columns is changed (except going from
+-full width to some larger number of columns)
+-a new page is started.
+-.PP
+-.I
+-Headings.
+-.R
+-To produce a special heading, there are two commands.
+-If you type
+-.DS L
+-      .NH
+-      type section heading here
+-      may be several lines
+-.DE
+-you will get automatically numbered section headings (1, 2, 3, ...),
+-in boldface.
+-For example,
+-.DS L
+-    .NH
+-    Care and Feeding of Department Heads
+-.DE
+-produces
+-.NH
+-Care and Feeding of Department Heads
+-.PP
+-Alternatively,
+-.DS L
+-      .SH
+-      Care and Feeding of Directors
+-.DE
+-will print the heading with no number added:
+-.SH
+-Care and Feeding of Directors
+-.PP
+-Every section heading, of either type, should be followed
+-by a paragraph beginning with .PP or .LP, indicating
+-the end of the heading.
+-Headings may contain more than one line
+-of text.
+-.PP
+-The .NH command also supports more complex numbering schemes.
+-If a numerical argument is given, it is taken to be a
+-``level'' number and an appropriate sub-section
+-number is generated.
+-Larger level numbers indicate deeper
+-sub-sections, as in this example:
+-.DS L
+-      .NH
+-      Erie-Lackawanna
+-      .NH 2
+-      Morris and Essex Division
+-      .NH 3
+-      Gladstone Branch
+-      .NH 3
+-      Montclair Branch
+-      .NH 2
+-      Boonton Line
+-.DE
+-generates:
+-.NH
+-Erie-Lackawanna
+-.NH 2
+-Morris and Essex Division
+-.NH 3
+-Gladstone Branch
+-.NH 3
+-Montclair Branch
+-.NH 2
+-Boonton Line
+-.PP
+-An explicit ``.NH 0'' will reset the numbering of level 1
+-to one, as here:
+-.DS L
+-      .NH 0
+-      Penn Central
+-.DE
+-.ft 3
+-.if n .ul 1
+-.sp 1
+-1.  Penn Central
+-.PP
+-.I
+-Indented paragraphs.
+-.R
+-(Paragraphs with hanging numbers, e.g. references.)
+-The sequence
+-.DS L
+-      .IP [1]
+-      Text for first paragraph, typed
+-      normally for as long as you would
+-      like on as many lines as needed.
+-      .IP [2]
+-      Text for second paragraph, ...
+-.DE
+-produces
+-.IP [1]
+-Text for first paragraph, typed normally for as long
+-as you would like on as many lines as
+-needed.
+-.IP [2]
+-Text for second paragraph, ...
+-.LP
+-A series of indented paragraphs may be followed by an ordinary paragraph
+-beginning with .PP or .LP,
+-depending on whether you wish indenting or not.
+-The command .LP was used here.
+-.PP
+-More sophisticated uses of .IP are also possible.
+-If the label is omitted, for example, a plain block indent
+-is produced.
+-.DS L
+-      .IP
+-      This material will
+-      just be turned into a
+-      block indent suitable for quotations or
+-      such matter.
+-      .LP
+-.DE
+-will produce
+-.IP
+-This material
+-will just be turned
+-into a block indent
+-suitable for
+-quotations or such matter.
+-.LP
+-If a non-standard amount of indenting is required,
+-it may be specified after the label (in character positions)
+-and will remain in effect until the next .PP or .LP.
+-Thus, the general form of the .IP command
+-contains two additional fields: the label and the indenting
+-length.  For example,
+-.DS L
+-      .IP first: 9
+-      Notice the longer label, requiring larger
+-      indenting for these paragraphs.
+-      .IP second:
+-      And so forth.
+-      .LP
+-.DE
+-produces this:
+-.IP first: 9
+-Notice the longer label, requiring larger
+-indenting for these paragraphs.
+-.IP second:
+-And so forth.
+-.LP
+-It is also possible to produce multiple nested indents;
+-the command .RS indicates that the next .IP starts from the
+-current indentation level.
+-Each .RE will eat up one level of indenting
+-so you should balance .RS and .RE commands.
+-The .RS command should be thought of as ``move right'' and
+-the .RE command as ``move left''.
+-As an example
+-.DS L
+-      .IP 1.
+-      Bell Laboratories
+-      .RS
+-      .IP 1.1
+-      Murray Hill
+-      .IP 1.2
+-      Holmdel
+-      .IP 1.3
+-      Whippany
+-      .RS
+-      .IP 1.3.1
+-      Madison
+-      .RE
+-      .IP 1.4
+-      Chester
+-      .RE
+-      .LP
+-.DE
+-will result in
+-.IP 1.
+-Bell Laboratories
+-.RS
+-.IP 1.1
+-Murray Hill
+-.IP 1.2
+-Holmdel
+-.IP 1.3
+-Whippany
+-.RS
+-.IP 1.3.1
+-Madison
+-.RE
+-.IP 1.4
+-Chester
+-.RE
+-.LP
+-All of these variations on .LP leave the right
+-margin untouched.  Sometimes, for purposes
+-such as setting off a quotation, a paragraph indented
+-on both right and left is required.
+-.QP
+-A single paragraph
+-like this is obtained
+-by preceding it with .QP.
+-More complicated material (several paragraphs) should be
+-bracketed with .QS and .QE.
+-.LP
+-.I
+-Emphasis.
+-.R
+-To get
+-italics
+-(on the typesetter) or underlining (on the terminal)
+-say
+-.DS L
+-      .I
+-      as much text as you want
+-      can be typed here
+-      .R
+-.DE
+-.bd I
+-.br
+-as was done for
+-.I
+-these three words.
+-.R
+-The .R command restores the normal (usually Roman) font.
+-If only one word is to be italicized, it
+-may be just given on the line with the .I command,
+-.br
+-.bd I 3
+-.DS
+-      .I word
+-.DE
+-and in this case no .R is needed to restore
+-the previous font.
+-.B
+-Boldface
+-.R
+-can be produced by
+-.DS L
+-      .B
+-      Text to be set in boldface
+-      goes here
+-      .R
+-.DE
+-and also will be underlined on the terminal or line printer.
+-As with .I, a single word can be placed in boldface
+-by placing it on the same line as the .B command.
+-.PP
+-A few size changes
+-can be specified similarly with
+-the commands .LG (make larger), .SM (make smaller), and .NL
+-(return to normal size).
+-The size change
+-is two points; the commands may be repeated for
+-.SM
+-increased
+-.SM
+-effect
+-.NL
+-(here one .NL canceled two .SM commands).
+-.PP
+-If actual
+-.UL underlining
+-as opposed to italicizing is required on the typesetter,
+-the command
+-.DS
+-      .UL word
+-.DE
+-will underline a word.  There is no way to underline
+-multiple words on the typesetter.
+-.PP
+-.I
+-Footnotes.
+-.R
+-Material placed between lines with the commands .FS
+-(footnote) and .FE (footnote end) will
+-be collected, remembered, and finally placed
+-at the bottom of the current page*.
+-By default, footnotes are 11/12th the
+-length of normal text,
+-but this can be changed using the FL register (see below).
+-.FS
+-* Like this.
+-.FE
+-.PP
+-.I
+-Displays and Tables.
+-.R
+-To prepare displays of lines, such as tables, in which
+-the lines should not be re-arranged,
+-enclose them in the commands .DS and .DE
+-.DS L
+-      .DS
+-      table lines, like the
+-      examples here, are placed
+-      between .DS and .DE
+-      .DE
+-.DE
+-By default, lines between .DS and .DE are indented and left-adjusted.
+-You can also center lines, or retain the left margin.
+-Lines bracketed by .DS C and .DE commands are
+-centered (and not re-arranged); lines bracketed
+-by .DS L and .DE are left-adjusted, not indented, and
+-not re-arranged.
+-A plain .DS is equivalent
+-to .DS I, which indents and left-adjusts.  Thus,
+-.DS C
+-these lines were preceded
+-by .DS C and followed by
+-a .DE command;
+-.DE
+-whereas
+-.DS L
+-these lines were preceded
+-by .DS L and followed by
+-a .DE command.
+-.DE
+-Note that .DS C centers each line; there is a variant .DS B
+-that makes the display into a left-adjusted block of text, and
+-then centers that entire block.
+-Normally a display is kept together, on one page.
+-If you wish to have a long display which
+-may be split across page
+-boundaries,
+-use .CD, .LD, or .ID in place of
+-the commands .DS C, .DS L, or .DS I respectively.
+-An extra argument to the .DS I or .DS command is taken
+-as an amount to indent.
+-Note: it is tempting to assume that .DS R will right adjust
+-lines, but it doesn't work.
+-.PP
+-.I
+-Boxing words or lines.
+-.R
+-To draw rectangular boxes around words the command
+-.DS L
+-      .BX word
+-.DE
+-will print
+-.BX word
+-as shown.
+-The boxes will not be neat on a terminal, and this
+-should not be used as a substitute for italics.
+-.B1
+-Longer pieces of text may be boxed
+-by enclosing them with .B1 and .B2:
+-.DS L
+-      .B1
+-      text...
+-      .B2
+-.DE
+-as has been done here.
+-.B2
+-.PP
+-.I
+-Keeping blocks together.
+-.R
+-If you wish to keep a table or other block of lines
+-together on a page, there are ``keep - release'' commands.
+-If a block of lines preceded by .KS and followed by .KE does
+-not fit on the remainder of the current page, it will begin
+-on a new page.
+-Lines bracketed by .DS and .DE commands are automatically
+-kept together this way.
+-There is also a ``keep floating'' command: if the
+-block to be kept together is preceded by .KF instead of .KS
+-and does not fit
+-on the current page, it will be moved down through the text
+-until the top of the next page.  Thus, no large blank space
+-will be introduced in the document.  
+-.PP
+-.I
+-Nroff/Troff commands.
+-.R
+-Among the useful commands from the basic formatting programs
+-are the following.  They all work with both typesetter and
+-computer terminal output:
+-.DS L
+-      .bp - begin new page.
+-      .br - ``break'', stop running text
+-                from line to line.
+-      .sp n - insert n blank lines.
+-      .na - don't adjust right margins.
+-.DE
+-.PP
+-.I
+-Date.
+-.R
+-By default, documents produced on computer terminals have the
+-date at the bottom of each page; documents produced on
+-the typesetter don't.
+-To force the date, say ``.DA''.  To force no date, say ``.ND''.
+-To lie about the date, say ``.DA July 4, 1776''
+-which puts the specified date at the bottom of each page.
+-The command
+-.DS L
+-      .ND May 8, 1945
+-.DE
+-in ".RP" format
+-places the specified date on the cover sheet and nowhere else.
+-Place this line before the title.
+-.PP
+-.I
+-Signature line.
+-.R
+-You can obtain a signature line by placing
+-the command .SG in the document.
+-The authors' names will
+-be output in place of the .SG line.
+-An argument to .SG
+-is used
+-as a typing identification line, and
+-placed after the signatures.
+-The .SG command is ignored
+-in released paper format.
+-.PP
+-.I
+-Registers.
+-.R
+-Certain of the registers used by \-ms can
+-be altered to change default
+-settings.
+-They should be changed with .nr commands,
+-as with
+-.DS
+-      .nr PS 9
+-.DE
+-.bd I
+-to make the default point size 9 point.
+-If the effect is needed immediately, the
+-normal
+-.I
+-troff
+-.R
+-command should be used
+-in addition to changing the number register.
+-.br
+-.ps 9
+-.vs 10p
+-.TS
+-c0 c c c
+-c c c c
+-a l l l.
+-Register      Defines Takes   Default
+-              effect
+-PS    point size      next para.      10
+-VS    line spacing    next para.      12 pts
+-LL    line length     next para.      6\(fm\(fm
+-LT    title length    next para.      6\(fm\(fm
+-PD    para. spacing   next para.      0.3 VS
+-PI    para. indent    next para.      5 ens
+-FL    footnote length next FS 11/12 LL
+-CW    column width    next 2C 7/15 LL
+-GW    intercolumn gap next 2C 1/15 LL
+-PO    page offset     next page       26/27\(fm\(fm
+-HM    top margin      next page       1\(fm\(fm
+-FM    bottom margin   next page       1\(fm\(fm
+-.TE
+-.ps \n(PS
+-.vs \n(VS
+-You may also alter
+-the strings
+-LH, CH, and RH which are the left, center, and right headings
+-respectively; and similarly LF, CF, and RF which are strings in the
+-page footer.
+-The page number on
+-.I
+-output
+-.R
+-is taken from register PN, to permit
+-changing its output style.
+-For more complicated headers and footers
+-the macros PT and BT can be redefined, as
+-explained earlier.
+-.bd I 3
+-.PP
+-.I
+-Accents.
+-.R
+-To simplify typing certain foreign words,
+-strings representing common accent marks are defined.
+-They precede the letter over which the mark
+-is to appear.
+-Here are the strings:
+-.TS
+-center;
+-c c6 c c.
+-Input Output  Input   Output
+-\e*\(fme      \*'e    \e*~a   \*~a
+-\e*\(gae      \*`e    \e*Ce   \h'0.15m'\v'-0.6m'\s6\zv\s0\v'0.6m'\h'-0.15m'e
+-\e*:u \*:u    \e*,c   \*,c
+-\e*^e \o'^e'
+-.TE
+-.PP
+-.I
+-Use.
+-.R
+-After your document is prepared and stored on a file,
+-you can print it on a terminal with the command*
+-.bd I
+-.FS
+-* If .2C was used, pipe the
+-.I nroff
+-output
+-through
+-.I col;
+-make the first line of the input
+-``.pi /usr/bin/col.''
+-.br
+-.FE
+-.DS L
+-.I
+-   nroff \-ms file
+-.R
+-.DE
+-and you can print it on the typesetter with the
+-command
+-.DS L
+-.I
+-   troff \-ms file
+-.R
+-.DE
+-(many options are possible).
+-In each case, if your document is stored in several files,
+-just list all the filenames
+-where we have used ``file''.
+-If equations or tables are used,
+-.I
+-eqn
+-.R
+-and/or
+-.I
+-tbl
+-.R
+-must be invoked as preprocessors.
+-.br
+-.bd I 3
+-.PP
+-.I
+-References and further study.
+-.R
+-If you have to do Greek or mathematics, see
+-.I eqn
+-[1]
+-for equation setting.
+-To aid
+-.I eqn
+-users,
+-.I \-ms
+-provides definitions of .EQ and .EN
+-which normally center the equation and set it off slightly.
+-An argument on .EQ is taken to be an equation
+-number and placed in the right margin near the equation.
+-In addition, there are three special arguments to EQ:
+-the letters C, I, and L indicate centered (default),
+-indented, and left adjusted equations, respectively. 
+-If there is both a format argument
+-and an equation number,
+-give the format argument first, as in
+-.bd I
+-.DS
+-      .EQ L (1.3a)
+-.DE
+-for a left-adjusted equation numbered (1.3a).
+-.PP
+-Similarly,
+-the macros .TS and .TE
+-are defined
+-to separate tables (see [2]) from text with a little space.
+-A very long table with a heading may be broken
+-across pages by beginning it with .TS H
+-instead of .TS,
+-and placing the line .TH in the table data
+-after the heading.  If the table
+-has no heading repeated from page to page,
+-just use the ordinary .TS and .TE macros.
+-.PP
+-To learn more about
+-.I troff
+-see
+-[3] for a general introduction, and [4]
+-for the full details (experts only).
+-Information on related UNIX commands
+-is in [5].
+-For jobs that do not seem well-adapted
+-to \-ms, consider other macro packages.
+-It is often far easier to write a specific macro packages
+-for such tasks as imitating particular journals than
+-to try to adapt \-ms.
+-.PP
+-.bd I 3
+-.I
+-Acknowledgment.
+-.R
+-Many thanks are due to Brian Kernighan for
+-his help in the design and implementation of this package,
+-and for his assistance in preparing this manual.
+-.bd I
+-.SH
+-.ce
+-References
+-.PP
+-.IP [1]
+-B. W. Kernighan and L. L. Cherry,
+-.I
+-Typesetting Mathematics \(em Users Guide (2nd edition),
+-.R
+-Bell Laboratories Computing Science Report no. 17.
+-.IP [2]
+-M. E. Lesk,
+-.I
+-Tbl \(em A Program to Format Tables,
+-.R
+-Bell Laboratories Computing Science Report no. 45.
+-.IP [3]
+-B. W. Kernighan,
+-.I
+-A Troff Tutorial,
+-.R
+-Bell Laboratories, 1976.
+-.IP [4]
+-J. F. Ossanna,
+-.I
+-Nroff\|/Troff Reference Manual,
+-.R
+-Bell Laboratories Computing Science Report no. 51.
+-.IP [5]
+-K. Thompson and D. M. Ritchie,
+-.I
+-UNIX Programmer's Manual,
+-.R
+-Bell Laboratories, 1978.
+-.1C
+-.SH
+-.ce
+-Appendix A
+-.ce
+-List of Commands
+-.ft R
+-.TS
+-expand;
+-l2 l5 l2 l.
+-1C    Return to single column format. LG      Increase type size.
+-2C    Start double column format.     LP      Left aligned block paragraph.
+-AB    Begin abstract. 
+-AE    End abstract.   
+-AI    Specify author's institution.   
+-AU    Specify author. ND      Change or cancel date.
+-B     Begin boldface. NH      Specify numbered heading.
+-DA    Provide the date on each page.  NL      Return to normal type size.
+-DE    End display.    PP      Begin paragraph.
+-DS    Start display (also CD, LD, ID).        
+-EN    End equation.   R       Return to regular font (usually Roman).
+-EQ    Begin equation. RE      End one level of relative indenting.
+-FE    End footnote.   RP      Use released paper format.
+-FS    Begin footnote. RS      Relative indent increased one level.
+-              SG      Insert signature line.
+-I     Begin italics.  SH      Specify section heading.
+-              SM      Change to smaller type size.
+-IP    Begin indented paragraph.       TL      Specify title.
+-KE    Release keep.   
+-KF    Begin floating keep.    UL      Underline one word.
+-KS    Start keep.     
+-.TE
+-.sp
+-.ce
+-.ft B
+-Register Names
+-.ft R
+-.PP
+-The following register names are used by \-ms internally.
+-Independent use of these names in one's own macros may
+-produce incorrect output.
+-Note that no lower case letters are used in any \-ms internal name.
+-.TS
+- expand;
+-c s s  s s s  s s s  s s
+-l l l  l l l  l l l  l l.
+-Number registers used in \-ms
+-:     DW      GW      HM      IQ      LL      NA      OJ      PO      T.      TV
+-#T    EF      H1      HT      IR      LT      NC      PD      PQ      TB      VS
+-.T    FC      H2      IF      IT      MF      ND      PE      PS      TC      WF
+-1T    FL      H3      IK      KI      MM      NF      PF      PX      TD      YE
+-AV    FM      H4      IM      L1      MN      NS      PI      RO      TN      YY
+-CW    FP      H5      IP      LE      MO      OI      PN      ST      TQ      ZN
+-.TE
+-.sp
+-.TS
+-expand;
+-c s s  s s s  s s s  s s
+-l l l  l l l  l l l  l l.
+-String registers used in \-ms
+-\(fm  A5      CB      DW      EZ      I       KF      MR      R1      RT      TL
+-\(ga  AB      CC      DY      FA      I1      KQ      ND      R2      S0      TM
+-^     AE      CD      E1      FE      I2      KS      NH      R3      S1      TQ
+-~     AI      CF      E2      FJ      I3      LB      NL      R4      S2      TS
+-:     AU      CH      E3      FK      I4      LD      NP      R5      SG      TT
+-,     B       CM      E4      FN      I5      LG      OD      RC      SH      UL
+-1C    BG      CS      E5      FO      ID      LP      OK      RE      SM      WB
+-2C    BT      CT      EE      FQ      IE      ME      PP      RF      SN      WH
+-A1    C       D       EL      FS      IM      MF      PT      RH      SY      WT
+-A2    C1      DA      EM      FV      IP      MH      PY      RP      TA      XD
+-A3    C2      DE      EN      FY      IZ      MN      QF      RQ      TE      XF
+-A4    CA      DS      EQ      HO      KE      MO      R       RS      TH      XK
+-.TE
+-.ne 4i
+-.br
+-.ne 5i
+-.ta 1i 2i 3i 4i
+-.vs .6i
+-.nf
+-.in 1i
+-.ll 4.2i
+-.ce
+-Order of Commands in Input
+-
+-      RP
+-TL
+-AU
+-AI
+-      AB
+-      AE
+-
+-              NH, SH
+-                      PP, LP
+-                      text ...
+-.br
+-.ce
+-Figure 1
+-.fi
+-.in 0
+//GO.SYSIN DD ms
+echo refcard
+sed 's/.//' >refcard <<'//GO.SYSIN DD refcard'
+-.fp 3 H
+-.po .5i
+-.de I
+-.ft 2
+-..
+-.de R
+-.ft 1
+-..
+-.de B
+-.bd R 2
+-\\$1
+-.bd R
+-..
+-.de hh
+-.br
+-.vs 10p
+-.ps 12
+-.bd 1 3
+-.ce
+-\\$1
+-.ps 9
+-.br
+-.bd 1
+-.sp
+-..
+-.de NP
+-'po 0
+-.ps 9
+-.ta .25i 3.75i 7.25i 7.7i
+-\(rn\t|\t|\t|\t\(rn
+-'po
+-'sp .2i
+-.mk z
+-..
+-.de FT
+-.po 0
+-.ps 9
+-.ta .25i 3.75i 7.25i
+-      |       |       |
+-.po .5i
+-..
+-.wh -8p FT
+-.de b1
+-.br
+-.tm left col bottom at \\n(nl
+-.po +3.5i
+-.sp |\\nzu
+-.ph
+-..
+-.de b2
+-.br
+-.tm right col bottom at \\n(nl
+-.po -3.5i
+-.bp
+-.ph
+-..
+-.de ph
+-.nr x +1
+-.tl ''\\nx''
+-.sp .2i
+-..
+-.nr x 1
+-.wh 0 NP
+-.ll 3i
+-.lt 3i
+-.nr LL 3i
+-.nr IQ 4
+-.nr IR 4
+-.de IP
+-.RT
+-.if \\n(IP=0 .nr IP +1
+-.if \\n(.$ .LB "\\$1"
+-.if !\\n(.$ .LB
+-..
+-.de RT
+-.if \\n(IP .in -\\n(IQn
+-.if \\n(IP .nr IP -1
+-..
+-.de LP
+-.RT
+-.ti 0
+-.ne 3
+-.if \\n(.$ .LB \\$1
+-..
+-.de LB
+-.in +\\n(IQn
+-.ta \\n(IQn
+-.if \\n(.$ .ti -\\n(IQn
+-.if \\n(.$ \\$1\t\c
+-..
+-.de RS
+-.in +\\n(IRn
+-..
+-.     \"RE - retreat to the left
+-.de RE
+-.br
+-.in -\\n(IRn
+-..
+-.br
+-.rs
+-.sp 1i
+-.ps 14
+-.vs 16p
+-.ce 3
+-A Guide to Preparing
+-Documents with \-ms
+-.sp 2
+-.ps 10
+-.vs 12p
+-.ft I
+-.ce
+-M. E. Lesk
+-.ft R
+-.lt \n(.lu
+-.sp .5
+-.tl 'Bell Laboratories''August 1978'
+-.sp .5
+-.tl xx\l'\n(.lu'xx
+-.sp 1
+-.bd I 2
+-.vs 11p
+-.fi
+-This guide gives some simple examples of
+-document preparation on Bell Labs computers,
+-emphasizing the use of the \fI\-ms\fR macro
+-package.
+-It enormously abbreviates
+-information in
+-.IP 1.
+-.I
+-Typing Documents on UNIX and GCOS,
+-.R
+-by M. E. Lesk;
+-.IP 2.
+-.I
+-Typesetting Mathematics \- User's Guide,
+-.R
+-by B. W. Kernighan and L. L. Cherry; and
+-.IP 3.
+-.I
+-Tbl \- A Program to Format Tables,
+-.R
+-by M. E. Lesk.
+-.LP
+-These memos are all included in the
+-.I
+-UNIX Programmer's Manual, Volume 2.
+-.R
+-The new user should also have
+-.I
+-A Tutorial Introduction to the UNIX Text Editor,
+-.R
+-by B. W. Kernighan.
+-.sp .5
+-For more detailed information, read
+-.I
+-Advanced Editing on UNIX
+-.R
+-and
+-.I
+-A Troff Tutorial,
+-.R
+-by B. W. Kernighan,
+-and (for experts)
+-.I
+-Nroff\^/Troff Reference Manual
+-.R
+-by J. F. Ossanna.
+-Information on related commands is
+-found (for UNIX users) in
+-.I
+-UNIX for Beginners
+-.R
+-by B. W. Kernighan
+-and the
+-.I
+-UNIX Programmer's Manual
+-.R
+-by K. Thompson and D. M. Ritchie.
+-.br
+-.vs 12p
+-.sp 1.5
+-.ce
+-.ps +2
+-Contents
+-.nf
+-.ps
+-.sp .5
+-.in .2i
+-.bd I
+-.ta 2.4i
+-.cs I 25
+-A TM \fI\ 1\fR 2
+-A released paper \fI\ 1\fR 3
+-An internal memo, and headings \fI\ 1\fR 4
+-Lists, displays, and footnotes \fI\ 1\fR 5
+-Indents, keeps, and double column \fI\ 1\fR 6
+-Equations and registers \fI\ 1\fR 7
+-Tables and usage \fI\ 1\fR 8
+-.in 0
+-.cs I
+-.sp 1
+-.fi
+-.EQ
+-delim $$
+-.EN
+-Throughout the examples, input is shown in
+-.ft 3
+-.br
+-.ti +2n
+-this Helvetica sans serif font
+-.ft R
+-.br
+-while the resulting output is shown in
+-.ti +2n
+-this Times Roman font.
+-.nf
+-.sp  2
+-.ce
+-UNIX Document no. 1111
+-.ps 9
+-.vs 10p
+-.EQ
+-gsize 9
+-.EN
+-.b1
+-.hh "Commands for a TM"
+-.nf
+-.ft 3
+-\&.TM 1978-5b3 99999 99999-11
+-\&.ND April 1, 1976
+-\&.TL
+-\&The Role of the Allen Wrench in Modern
+-\&Electronics
+-\&.AU "MH 2G-111" 2345
+-\&J. Q. Pencilpusher
+-\&.AU "MH 1K-222" 5432
+-\&X. Y. Hardwired
+-\&.AI
+-\&.MH
+-\&.OK
+-\&Tools
+-\&Design
+-\&.AB
+-\&This abstract should be short enough to
+-\&fit on a single page cover sheet.
+-\&It must attract the reader into sending for
+-\&the complete memorandum.
+-\&.AE
+-\&.CS 10 2 12 5 6 7
+-\&.NH
+-\&Introduction.
+-\&.PP
+-\&Now the first paragraph of actual text ...
+-\&...
+-\&Last line of text.
+-\&.SG MH-1234-JQP/XYH-unix
+-\&.NH
+-\&References ...
+-.ft
+-.sp
+-.fi
+-Commands not needed in a particular
+-format are ignored.
+-.sp 
+-.ps 8
+-.vs 9p
+-.mk a
+-.sp .20i
+-.ll 3i
+-.nf
+-\h'2n'\s16\(bs\s7 $fat roman size 7  "Bell Laboratories"$        \s8Cover Sheet for TM
+-.sp
+-\s6\l'3i'
+-.fi
+-.ps 7
+-.ft 2
+-.sp 1p
+-This information is for employees of Bell Laboratories.  (GEI 13.9-3)\p
+-.ft 1
+-.nf
+-.vs 4p
+-\s6\l'3i'
+-.vs 9p
+-.sp
+-.ll 3.0i
+-.ps 7
+-.ta .25i 2.25i 2.45i
+-.mk
+-Title- \s8
+-.rt
+-.in .25i
+-.hy 0
+-.bd 1 2
+-The Role of the Allen Wrench
+-in Modern Electronics
+-.hy 14
+-.br
+-.bd 1
+-.rt
+-.ll \\n(LLu
+-.in 2.1i
+-\s7Date- \s8
+-.rt
+-.in 2.35i
+-.bd 1 2
+-.ps 8
+-April 1, 1976
+-.sp
+-.bd 1
+-.ti 2.1i
+-.mk
+-\s7TM- \s8
+-.br
+-.rt
+-.bd 1 2
+-1978-5b3
+-.rt
+-.in 0
+-.bd 1
+-.sp
+-.mk
+-\s7Other Keywords- \kQ 
+-.rt
+-.in \nQu
+-.bd 1 2
+-.ps 8
+-Tools
+-Design
+-.rm OK
+-.rm OD
+-.in 0
+-.bd 1
+-.if t .sp .35i
+-.ps 7
+-.ta 1.05i 1.7i 2.0i
+-Author        Location        Ext.    Charging Case- \s8$fat roman size 8 99999$
+-.nf
+-.mk
+-.bd 1 2
+-.ps 8
+-J. Q. Pencilpusher    MH 2G-111       2345
+-.rt
+-.br
+-.bd 1
+-                      \s7Filing Case- \s8$fat roman size 8 "99999a"$
+-.br
+-.bd 1 2
+-X. Y. Hardwired       MH 1K-222       5432
+-.sp .2i
+-.bd 1
+-.br
+-.ll 3i
+-.ce
+-.ft I
+-ABSTRACT
+-.ft 1
+-.sp
+-.fi
+-.ps 8
+-.ll 2.5i
+-.in +.25i
+-.ti +2
+-This abstract should be short enough to fit
+-on a single page cover sheet.
+-It must attract the reader into sending for the
+-complete memorandum.
+-.in
+-.ll
+-.sp .4i
+-.nf
+-\l'3i'
+-.ta .9i 1.8i 2.7i
+-.sp 5p
+-Pages Text   10       Other   2       Total   12
+-.if t .sp 8p
+-.if n .sp 
+-.if t No. Figures    5        No. Tables   6  No. Refs.   7   \b'|||||\ \ '
+-\l'3i'
+-.ps 6
+-.if n .sp
+-.lt 3i
+-.tl 'E-1932-U (6-73)''SEE REVERSE SIDE FOR DISTRIBUTION LIST'
+-.sp .20i
+-.de eb
+-.sp -1
+-.nf
+-\h'-1m'\L'|\\nau-1'\l'\\n(.lu+2m\(ul'\L'-|\\nau+1'\l'|0u-1m\(ul'
+-.fi
+-..
+-.eb
+-.b2
+-.hh "A Released Paper with Mathematics"
+-.ft 3
+-.nf
+-.EQ
+-delim off
+-.EN
+-\&.EQ
+-\&delim $$
+-\&.EN
+-\&.RP
+-.sp
+-.ft 1
+-\&... (as for a TM)
+-.sp
+-.ft 3
+-\&.CS 10 2 12 5 6 7
+-\&.NH
+-\&Introduction
+-\&.PP
+-\&The solution to the torque handle equation
+-\&.EQ (1)
+-\&sum from 0 to inf F ( x sub i ) = G ( x )
+-\&.EN
+-\&is found with the transformation $ x = rho over
+-\&theta $ where $ rho = G prime (x) $ and $theta$
+-\&is derived ...
+-.ft 1
+-.sp 2
+-.mk a
+-.ll 3i
+-.ps 9
+-.bd 1 2
+-.sp .4i
+-.ce 2
+-.vs 11p
+-The Role of the Allen Wrench
+-in Modern Electronics
+-.sp .7
+-.ce 3
+-.ft 2
+-.bd 1
+-.ps 8
+-.vs 9p
+-J. Q. Pencilpusher
+-.sp .7
+-X. Y. Hardwired
+-.sp .7
+-.ce 2
+-.ft 1
+-Bell Laboratories
+-Murray Hill, New Jersey 07974
+-.sp 2
+-.ce
+-.ft 2
+-ABSTRACT
+-.ft 1
+-.sp .7
+-.in +.25i
+-.ll 2.75i
+-.fi
+-.ad
+-.ti +2n
+-This abstract should be short enough to fit
+-on a single page cover sheet.
+-It must attract the reader into sending for the
+-complete memorandum.
+-.sp 5v
+-.in
+-.ll
+-April 1, 1976
+-.sp .2i
+-.eb
+-.ll 3i
+-.sp .5v
+-.sp 3.5p
+-.mk a
+-.lt 3i
+-.ps 9
+-.sp .25i
+-.bd 1 2
+-.ce 2
+-.vs 11p
+-The Role of the Allen Wrench
+-in Modern Electronics
+-.sp
+-.ce 3
+-.bd 1
+-.ft 2
+-.ps 8
+-.vs 9p
+-J. Q. Pencilpusher
+-.sp
+-X. Y. Hardwired
+-.sp
+-.ce 2
+-.ft 1
+-Bell Laboratories
+-Murray Hill, New Jersey 07974
+-.sp 3
+-.ce
+-.de SH
+-.bd 1 2
+-.sp
+-.ce 0
+-.in 0
+-..
+-.de PP
+-.sp .3
+-.ft 1
+-.bd 1
+-.ti +2n
+-..
+-.SH
+-1. Introduction
+-.PP
+-The solution to the torque handle equation
+-.br
+-.di xx
+-.EQ
+-delim $$
+-gsize 8
+-sum from 0 to inf F ( x sub i ) = G ( x )
+-.EN
+-.br
+-.di
+-.tl ''\*(10'(1)'
+-is found with the transformation
+-$ x = rho over theta $ where $ rho = G prime ( x )$
+-and $theta$ is derived from well-known principles.
+-......PP
+-......ft 2
+-.....The Ascent of the Riffelberg,
+-......ft 1
+-.....by Mark Twain.
+-.....I sat silent some time, then turned to Harris and said:
+-.....``My mind is made up.''
+-.....Something in my tone struck him; and when he glanced
+-.....at my eye and read what was written there, his face paled
+-.....perceptibly.  He hesitated a moment, then said:
+-.....``Speak.''
+-.....I answered, with perfect calmness:
+-......ft 2
+-.....``I will ascend the Riffelberg.''
+-......ft 1
+-.....If I had shot my poor friend he could not have fallen from
+-.....his chair more suddenly.  If I had been his father he
+-.....could not have pleaded harder to get me to give up my
+-.....purpose.  But I turned a deaf ear to all he said.  When he
+-.....perceived at last that nothing could alter my determination,
+-.....he ceased to urge, and for a while the deep\p
+-.sp .5v
+-.sp 3.5p
+-.eb
+-.b1
+-.hh "An Internal Memorandum"
+-.ft 3
+-.nf
+-\&.IM
+-\&.ND January 24, 1956
+-\&.TL
+-\&The 1956 Consent Decree
+-\&.AU
+-\&Able, Baker &
+-\&Charley, Attys.
+-\&.PP
+-Plaintiff, United States of America, having filed
+-its complaint herein on January 14, 1949; the
+-defendants having appeared and filed their
+-answer to such complaint denying the
+-substantive allegations thereof; and the parties,
+-by their attorneys, ...
+-.ft
+-.sp
+-.ft 1
+-.mk a
+-.br
+-.sp .20i
+-.ta 2.1i
+-.ll 3i
+-.ps 18
+-.br
+-      \(bs
+-.vs .20i
+-.ps 7
+-.br
+-.bd 1 2
+-.nf
+-      Bell Laboratories
+-.fi
+-.na
+-.bd 1
+-.ps 7
+-.vs 8p
+-.sp .12i
+-.mk
+-.fi
+-.ll
+-.ll 2.0i
+-Subject:
+-.ps 8
+-.hy 0
+-.br
+-.bd 1 2
+-.sp -1
+-\h'\w'\s7Subject: \s0'u'The 1956 Consent Decree
+-.hy 14
+-.br
+-.bd 1
+-.rt
+-.ll 3.25i
+-.in 2.10i
+-.ps 7
+-.mk
+-.ti -6n
+-date:
+-.br
+-.bd 1 2
+-.rt
+-.ps 8
+-January 24, 1956
+-.sp
+-.bd 1
+-.ps 7
+-.mk
+-.ti -6n
+-from:
+-.ps 8
+-.nf
+-.br
+-.bd 1 2
+-.rt
+-Able, Baker &
+-Charley, Attys.
+-.br
+-.bd 1
+-.sp
+-.sp
+-.ll 3i
+-.ad
+-.fi
+-.in 0
+-.de SH
+-.sp .5
+-.bd 1 2
+-..
+-.de PP
+-.sp .3
+-.bd 1
+-.ti +2n
+-..
+-.PP
+-Plaintiff, United States of America, having filed its complaint
+-herein on January 14, 1949; the defendants having appeared and
+-filed their answer to such complaint denying the substantive
+-allegations thereof; and the parties, by their attorneys, having
+-severally consented to the entry of this Final Judgment without
+-trial or adjudication of any issues of fact or law herein and without
+-this Final Judgment constituting any evidence or admission by any
+-party in respect of any such issues;
+-.PP
+-Now, therefore before any testimony has been taken herein, and
+-without trial or adjudication of any issue of fact or law herein,
+-and upon the consent of all parties hereto, it is hereby
+-.PP
+-Ordered, adjudged and decreed as follows:
+-.SH
+-I.
+-[Sherman Act]
+-.PP
+-This Court has jurisdiction of the subject matter herein and of all
+-the parties hereto.
+-The complaint states a claim upon which relief may be granted
+-against each of the defendants under Sections 1, 2 and 3 of the
+-Act of Congress of July 2, 1890, entitled ``An act to protect
+-trade and commerce against unlawful restraints and monopolies,''
+-commonly known as the Sherman Act, as amended.
+-.SH
+-II.
+-[Definitions]
+-.PP
+-For the purposes of this Final Judgment:
+-.PP
+-(a)  ``Western'' shall mean the defendant Western Electric
+-Company, Incorporated.
+-.sp .25i
+-.eb
+-.sp
+-.ft 1
+-.bd 1
+-
+-.ps 9
+-.vs 10p
+-Other formats possible (specify before \f3.TL\f1) are:
+-\&\f3.MR\f1 (``memo for record''), \f3.MF\f1
+-(``memo for file''),
+-\&\f3.EG\f1 (``engineer's notes'') and \f3.TR\f1
+-(Computing Science Tech. Report).
+-.sp 2
+-.hh "Headings"
+-.sp .5
+-.nf
+-.ft 3
+-.ta 2i
+-\&.NH .SH
+-Introduction. Appendix I
+-\&.PP .PP
+-text text text        text text text
+-.ft 1
+-.bd 1 2
+-.sp
+-.br
+-1.  Introduction      Appendix I
+-.br
+-.sp .3v
+-.bd 1
+-\0\0text text text    \0\0text text text
+-.br
+-.b2
+-.hh "A Simple List"
+-.ft 3
+-.nf
+-\&.IP 1.
+-\&J. Pencilpusher and X. Hardwired,
+-\&.I
+-\&A New Kind of Set Screw,
+-\&.R
+-\&Proc. IEEE
+-\&.B 75
+-\&(1976), 23-255.
+-\&.IP 2.
+-\&H. Nails and R. Irons,
+-\&.I
+-\&Fasteners for Printed Circuit Boards,
+-\&.R
+-\&Proc. ASME
+-\&.B 23
+-\&(1974), 23-24.
+-\&.LP  \fP(terminates list)
+-.sp 1.5
+-.EQ
+-delim $$
+-gsize 9
+-.EN
+-.fi
+-.IP 1.
+-J. Pencilpusher and X. Hardwired,
+-.I
+-A New Kind of Set Screw,
+-.R
+-Proc. IEEE
+-$fat 75$
+-(1976), 23-255.
+-.IP 2.
+-H. Nails and R. Irons,
+-.I
+-Fasteners for Printed Circuit Boards,
+-.R
+-Proc. ASME
+-$fat 23$
+-(1974), 23-24.
+-.LP
+-.sp 2
+-.EQ
+-delim off
+-.EN
+-.hh "Displays"
+-.nf
+-.ft 3
+-\&text text text text text text 
+-\&.DS
+-\&and now
+-\&for something
+-\&completely different
+-\&.DE
+-\&text text text text text text 
+-.ft
+-.sp 1
+-.fi
+-hoboken harrison newark roseville avenue grove street
+-east orange brick church orange highland avenue
+-mountain station south orange maplewood millburn short hills
+-summit new providence
+-.in .4i
+-.sp .5
+-.nf
+-and now
+-for something
+-completely different
+-.sp .5
+-.in
+-.fi
+-murray hill berkeley heights
+-gillette stirling millington lyons basking ridge
+-bernardsville far hills peapack gladstone
+-.sp .5
+-Options: \f3.DS L\f1: left-adjust;
+-\&\f3.DS C\f1: line-by-line center; \f3.DS B\f1: make block, then center.
+-.sp  2
+-.hh "Footnotes"
+-.nf
+-.ft 3
+-\&Among the most important occupants
+-\&of the workbench are the long-nosed pliers.
+-\&Without these basic tools*
+-\&.FS
+-\&* As first shown by Tiger & Leopard
+-\&(1975).
+-\&.FE
+-\&few assemblies could be completed.  They may
+-\&lack the popular appeal of the sledgehammer
+-.ft
+-.sp 1.5
+-.fi
+-Among the most important occupants
+-of the workbench are the long-nosed
+-pliers.
+-Without these basic tools*
+-few assemblies could be completed.
+-They may lack the
+-popular appeal of the sledgehammer
+-.br
+-\l'1i'
+-.ps -1
+-.br
+-* As first shown by Tiger & Leopard (1975).
+-.ps
+-.br
+-.nf
+-.b1
+-.hh "Multiple Indents"
+-.ft 3
+-\&This is ordinary text to point out
+-\&the margins of the page.
+-\&.IP 1.
+-\&First level item
+-\&.RS
+-\&.IP a)
+-\&Second level.
+-\&.IP b)
+-\&Continued here with another second
+-\&level item, but somewhat longer.
+-\&.RE
+-\&.IP 2.
+-\&Return to previous value of the
+-\&indenting at this point.
+-\&.IP 3.
+-\&Another
+-\&line.
+-.ft
+-.sp 1.5v
+-.fi
+-This is ordinary text to point out
+-the margins of the page.
+-.IP 1.
+-First level item
+-.RS
+-.IP a)
+-Second level.
+-.IP b)
+-Continued here with another second level
+-item, but somewhat longer.
+-.RE
+-.IP 2.
+-Return to previous value of the
+-indenting at this point.
+-.IP 3.
+-Another
+-line.
+-.LP
+-.sp 2
+-.hh "Keeps"
+-.fi
+-Lines bracketed by the following commands are kept together,
+-and will appear entirely on one page:
+-.TS
+-center;
+-Lf3 5 L8 Lf3 5 L.
+-\&.KS not moved       .KF     may float
+-\&.KE through text    .KE     in text
+-.TE
+-.nf
+-.sp 2
+-.hh "Double Column"
+-.nf
+-.hy 0
+-.ft 3
+-\&.TL
+-The Declaration of Independence
+-\&.2C
+-.na
+-.fi
+-\&.PP
+-.br
+-When in the course of human events, it becomes
+-necessary for one people to dissolve the political bonds 
+-which have connected them with another, and to assume 
+-among the powers of the earth the separate and equal station
+-to which the laws of Nature and of Nature's God entitle them,
+-a decent respect to the opinions of
+-.ft
+-.de xy
+-.if \\n(xy=0 'rt
+-.if \\n(xy=0 'po +1.58i
+-.nr xy +1
+-..
+-.wh 10.45i xy
+-.br
+-.ad
+-.hy 1 
+-.sp 1.5
+-.ce
+-The Declaration of Independence
+-.sp .5
+-.ll 1.42i
+-.mk
+-.fi
+-.ti +2n
+-When in the course of human events, it becomes
+-necessary for one people to dissolve the political bonds which have
+-connected them with another, and to assume among the 
+-powers of the earth the separate and equal station to which
+-the laws of Nature and of Nature's God entitle them, a decent
+-respect to the opinions of mankind requires that they should
+-declare the causes which impel them to the separation.
+-.ti +2n
+-We hold these truths to be self-evident, that all men
+-are created equal, that they are endowed by their creator
+-with certain unalienable rights, that among these are life, liberty,
+-and the pursuit of happiness.  That to secure these rights,
+-governments are instituted among men,\p
+-.br
+-.po -1.58i
+-.ll 3i
+-.lt 3i
+-.rm xy
+-.b2
+-.hh "Equations"
+-.nf
+-.de EQ  \"equation, breakout and display
+-.nr EF \\n(.u
+-.rm EE
+-.nr LE 1      \" 1 is center
+-.ds EL \\$1
+-.if "\\$1"L" .ds EL \\$2
+-.if "\\$1"L" .nr LE 0
+-.if "\\$1"C" .ds EL \\$2
+-.if "\\$1"I" .nr LE 0
+-.if "\\$1"I" .ds EE \\h'5n'
+-.if "\\$1"I" .if !"\\$3"" .ds EE \\h'\\$3n'
+-.if "\\$1"I" .ds EL \\$2
+-.nf
+-.di EZ
+-..
+-.de EN  \" end of a displayed equation
+-.di
+-.rm EZ
+-.lt \\n(.lu
+-.pc
+-.if \\n(dn>0 .if \\n(LE>0 .tl \(ts\(ts\\*(10\(ts\\*(EL\(ts
+-.if \\n(dn>0 .if \\n(LE=0 .tl '\\*(EE\\*(10''\\*(EL'
+-.pc %
+-.lt \\n(LLu
+-.if \\n(EF>0 .fi
+-.rm EL
+-.rm 10
+-.nr PE \\n(.d
+-..
+-.ft 3
+-A displayed equation is marked
+-with an equation number at the right margin
+-by adding an argument to the EQ line:
+-\&.EQ (1.3)
+-x sup 2 over a sup 2 ~=~ sqrt {p z sup 2 +qz+r}
+-\&.EN
+-.ft
+-.sp
+-.fi
+-A displayed equation is marked with an equation number
+-at the right margin by adding an argument to the EQ line:
+-.sp .4
+-.EQ (1.3)
+-x sup 2 over a  sup 2
+-~=~ sqrt { p z sup 2 + q z + r }
+-.EN
+-.sp 
+-.nf
+-.ft 3
+-\&.EQ  I (2.2a)
+-bold V bar sub nu~=~left [ pile {a above b above
+-c } right ] + left [ matrix { col { A(11) above .
+-above . } col { . above . above .} col {. above .
+-above A(33) }} right ] cdot left [ pile { alpha
+-above beta above  gamma } right ]
+-.nf
+-\&.EN
+-.ft
+-.sp
+-.EQ I (2.2a)
+-fat {roman  V}  bar sub nu~=~left [ pile {a above b above c}
+-right ] + left [ matrix { col { A(11) above .
+-above . } col { . above . above .} col {. above .
+-above A(33) }} right ] cdot left [ pile { alpha
+-above beta above  gamma } right ]
+-.EN
+-.sp
+-.ft 3
+-\&.EQ  L
+-F hat ( chi ) ~ mark = ~ | del V | sup 2
+-\&.EN
+-\&.EQ  L
+-.fi
+-.na
+-lineup =~ {left ( {partial V} over {partial x} right ) } sup 2
+-+ { left ( {partial V} over {partial y} right ) } sup 2
+-~~~~~~ lambda -> inf
+-.nf
+-\&.EN
+-.ft
+-.ta .25i
+-.sp
+-.EQ L
+-F hat ( chi ) ~ mark = ~ | del V | sup 2
+-.EN
+-.sp 1
+-.EQ L
+-delim off
+-lineup =~ {left ( {partial V} over {partial x} right ) } sup 2
+-+ { left ( {partial V} over {partial y} right ) } sup 2
+-~~~~~~ lambda -> inf
+-.EN
+-.rm EQ
+-.rm EN
+-.fi
+-.sp
+-.ft 3
+-$ a dot $,  $ b dotdot$,  $ xi tilde times
+-y vec$:
+-.EQ
+-delim $$
+-.EN
+-.ft R
+-.br
+-.sp
+-$ a dot $,  $ b dotdot$,  $ xi tilde times
+-y vec$.
+-.EQ
+-delim off
+-.EN
+-\h'.3i'(with delim $$ on, see panel 3).
+-.sp .5
+-See also the equations in the second table, panel 8.
+-.nf
+-.br
+-.bd I
+-.sp 2
+-.ft R
+-.hh "Some Registers You Can Change"
+-.nf
+-.mk
+-Line length
+-      .nr LL 7i
+-.sp .4
+-Title length
+-      .nr LT 7i
+-.sp .4
+-Point size
+-      .nr PS 9
+-.sp .4
+-Vertical spacing
+-      .nr VS 11
+-.sp .4
+-Column width
+-      .nr CW 3i
+-.sp .4
+-Intercolumn spacing
+-      .nr GW .5i
+-.sp .4
+-Margins \- head and foot
+-      .nr HM .75i
+-      .nr FM .75i
+-.sp .4
+-Paragraph indent
+-      .nr PI 2n
+-.rt
+-.po +1.6i
+-Paragraph spacing
+-      .nr PD 0
+-.sp .4
+-Page offset
+-      .nr PO 0.5i
+-.sp .4
+-Page heading
+-      .ds CH Appendix 
+-          (center)
+-      .ds RH 7-25-76
+-          (right)
+-      .ds LH Private
+-          (left)
+-.sp .4
+-Page footer
+-      .ds CF Draft
+-      .ds LF
+-      .ds RF  \u similar \d
+-.sp .4
+-Page numbers
+-      .nr % 3
+-.po -1.6i
+-.b1
+-.hh Tables
+-.nf
+-.ds T \|\h'.35n'\v'-.1n'\s6\zT\s0\v'.1n'\h'-.35n'\(ci\|
+-.ft 3
+-.EQ
+-delim off
+-.EN
+-\&.TS\h'.5i'\fR(\f3\*T\f1 indicates a tab)\f3
+-\&allbox;
+-.nr x \n(nl
+-\&c s s
+-\&c c c
+-\&n n n.
+-\&AT&T Common Stock
+-\&Year\*TPrice\*TDividend
+-\&1971\*T41-54\*T$2.60
+-\&2\*T41-54\*T2.70
+-\&3\*T46-55\*T2.87
+-\&4\*T40-53\*T3.24
+-\&5\*T45-52\*T3.40
+-\&6\*T51-59\*T.95*
+-\&.TE
+-\&* (first quarter only)
+-.ft 1
+-.nr y \n(nl
+-.sp |\nxu
+-.di qq
+-.TS
+-allbox;
+-c s s
+-c c c
+-n1 n1 n1.
+-AT&T Common Stock
+-Year  Price   Dividend
+-1971  41-54   $2.60
+-2     41-54   2.70
+-3     46-55   2.87
+-4     40-53   3.24
+-5     45-52   3.40
+-6     51-59   .95*
+-.TE
+-* (first quarter only)
+-.br
+-.di
+-.in 3i-\n(TWu
+-.nf
+-.qq
+-.in 0
+-.if \ny>\n(nl .sp |\nyu
+-.sp .5
+-.ft 1
+-.fi
+-.ad
+-The meanings of the key-letters describing
+-the alignment of each entry are:
+-.br
+-.nf
+-.TS
+-center;
+-cf3 l6 cf3 l.
+-c     center  n       numerical
+-r     right-adjust    a       subcolumn
+-l     left-adjust     s       spanned
+-.TE
+-.fi
+-The global table options are
+-.ft 3
+-.bd I 2
+-.hy 0
+-center, expand, box, doublebox, allbox,
+-tab (\f2x\fP\|)
+-.ft 1
+-and
+-.ft 3
+-linesize (\f2n\fP\|).
+-.br
+-.hy 1
+-.ft 1
+-.bd I
+-.sp 1
+-.nf
+-.ta .1i
+-.ft 3
+-\&.TS\h'.5i'\fR(with delim $$ on, see panel 3)\fP
+-\&doublebox, center;
+-\&c c
+-\&l l.
+-\&Name\*TDefinition
+-\&.sp
+-\&Gamma\*T$GAMMA (z) = int sub 0 sup inf \e
+-       t sup {z-1} e sup -t dt$
+-\&Sine\*T$sin (x) = 1 over 2i ( e sup ix - e sup -ix )$
+-\&Error\*T$ roman erf (z) = 2 over sqrt pi \e
+-      int sub 0 sup z e sup {-t sup 2} dt$
+-\&Bessel\*T$ J sub 0 (z) = 1 over pi \e
+-      int sub 0 sup pi cos ( z sin theta ) d theta $
+-\&Zeta\*T$ zeta (s) = \e
+-      sum from k=1 to inf k sup -s ~~( Re~s > 1)$
+-\&.TE
+-.ft
+-.sp
+-.EQ
+-delim $$
+-.EN
+-.vs +2p
+-.TS
+-doublebox, center;
+-c c
+-l l.
+-Name  Definition
+-.sp
+-Gamma $GAMMA (z) = int sub 0 sup inf  t sup {z-1} e sup -t dt$
+-Sine  $sin (x) = 1 over 2i ( e sup ix - e sup -ix )$
+-Error $ roman erf (z) = 2 over sqrt pi int sub 0 sup z e sup {-t sup 2} dt$
+-Bessel        $ J sub 0 (z) = 1 over pi int sub 0 sup pi cos ( z sin theta ) d theta $
+-Zeta  $ zeta (s) = sum from k=1 to inf k sup -s ~~( Re~s > 1)$
+-.TE
+-.vs -2p
+-.br
+-.bd I 2
+-.sp 1
+-.hh "Usage"
+-.ps 9
+-.vs 10p
+-.ds & \\s-1&\\s0
+-.TS
+-l.
+-\h'.25i'Documents with just text:
+-troff -ms files 
+-\h'.25i'With equations only:
+-eqn files | troff -ms 
+-\h'.25i'With tables only:
+-tbl files | troff -ms 
+-\h'.25i'With both tables and equations:
+-tbl files\||\|eqn\||\|troff -ms
+-_
+-.TE
+-.ft R
+-.fi
+-.sp .5
+-The above generates \s-2STARE\s0 output on
+-\s-2GCOS\s0: replace
+-.ft 3
+-\-st
+-.ft R
+-with
+-.ft 3
+-\-ph
+-.ft R
+-for typesetter output.
+-.ft 1
+-.bd I
+-.b2
+//GO.SYSIN DD refcard
diff --git a/doc/7thEdMan/vol2/password b/doc/7thEdMan/vol2/password
new file mode 100644 (file)
index 0000000..27124b8
--- /dev/null
@@ -0,0 +1,558 @@
+.\" tbl mm ^ eqn ^ troff -ms
+.EQ
+delim $$
+.EN
+.RP
+....TM 78-1271-5 39199 39199-11
+.ND April 3, 1978
+.TL
+Password Security:
+A Case History
+.OK
+Encryption
+Computing
+.AU "MH 2C-524" 3878
+Robert Morris
+.AU "MH 2C-523" 2394
+Ken Thompson
+.AI
+.MH
+.AB
+This paper describes the history of the design of the
+password security scheme on a remotely accessed time-sharing
+system.
+The present design was the result of countering
+observed attempts to penetrate the system.
+The result is a compromise between extreme security and
+ease of use.
+.AE
+.CS 6 0 6 0 0 4
+.SH
+INTRODUCTION
+.PP
+Password security on the
+.UX
+time-sharing system [1] is provided by a
+collection of programs
+whose elaborate and strange design is the outgrowth of
+many years of experience with earlier versions.
+To help develop a secure system, we have had a continuing
+competition to devise new ways to
+attack the security of the system (the bad guy) and, at the same time, to
+devise new techniques to resist the new attacks (the good guy).
+This competition has been in the same vein as the
+competition of long standing between manufacturers of armor
+plate and those of armor-piercing shells.
+For this reason, the description that follows will
+trace the history of the password system rather than simply
+presenting the program in its current state.
+In this way, the reasons for the design will be made clearer,
+as the design cannot be understood without also
+understanding the potential attacks.
+.PP
+An underlying goal has been to provide password security
+at minimal inconvenience to the users of the system.
+For example, those who want to run a completely open
+system without passwords, or to have passwords only at the
+option of the individual users, are able to do so, while
+those who require all of their users to have passwords
+gain a high degree of security
+against penetration of the system by unauthorized
+users.
+.PP
+The password system must be able not only to prevent
+any access to the system by unauthorized users
+(i.e. prevent them from logging in at all),
+but it must also
+prevent users who are already logged in from doing
+things that they are not authorized to do.
+The so called ``super-user'' password, for example, is especially
+critical because the super-user has all sorts of
+permissions and has essentially unlimited access to
+all system resources.
+.PP
+Password security is of course only one component of
+overall system security, but it is an essential component.
+Experience has shown that attempts to penetrate
+remote-access systems have been astonishingly
+sophisticated.
+.PP
+Remote-access systems are peculiarly vulnerable to
+penetration by outsiders as there are threats at the
+remote terminal, along the communications link, as well
+as at the computer itself.
+Although the security of a password encryption algorithm
+is an interesting intellectual and mathematical problem,
+it is only one tiny facet of a very large problem.
+In practice, physical security of the computer, communications
+security of the communications link, and physical control
+of the computer itself loom as far more important issues.
+Perhaps most important of all is control over the actions
+of ex-employees, since they are not under any direct control
+and they may have intimate
+knowledge about the system, its resources, and
+methods of access.
+Good system security involves realistic
+evaluation of the risks not only of deliberate
+attacks but also of casual unauthorized access
+and accidental disclosure.
+.SH
+PROLOGUE
+.PP
+The UNIX system was first implemented with a password file that contained
+the actual passwords of all the users, and for that reason
+the password file had to
+be heavily protected against being either read or written.
+Although historically, this had been the technique used
+for remote-access systems,
+it was completely unsatisfactory for several reasons.
+.PP
+The technique is excessively vulnerable to lapses in
+security.
+Temporary loss of protection can occur when
+the password file is being edited or otherwise modified.
+There is no way to prevent the making of copies by
+privileged users.
+Experience with several earlier remote-access systems
+showed that such lapses occur with frightening frequency.
+Perhaps the most memorable such occasion occurred
+in the early 60's when
+a system administrator on the CTSS system at MIT
+was editing the
+password file and another system administrator was editing
+the daily message that is printed on everyone's terminal
+on login.
+Due to a software design error, the temporary editor files
+of the two users were interchanged and thus, for a time, the password
+file was printed on every terminal when it was logged in.
+.PP
+Once such a lapse in security has been discovered, everyone's
+password must be changed, usually simultaneously, at a considerable
+administrative cost.
+This is not a great matter, but
+far more serious is the high probability of such lapses
+going unnoticed by the system administrators.
+.PP
+Security against unauthorized disclosure of the passwords was,
+in the last analysis, impossible with this system because,
+for example, if the
+contents of the file system are put on to magnetic tape for
+backup, as they must be, then anyone who has physical
+access to the tape
+can read anything on it with no restriction.
+.PP
+Many programs must get information of various kinds
+about the users of the system, and these programs in general
+should have no special permission to read the password file.
+The information which should have been in the password file actually was
+distributed (or replicated) into a number of files, all of
+which had to be updated whenever a user was added to or
+dropped from the system.
+.SH
+THE FIRST SCHEME
+.PP
+The obvious solution is to arrange that the passwords not
+appear in the system at all, and it is not difficult to decide
+that this can be done by encrypting each user's password,
+putting only the encrypted form in the password file, and
+throwing away his original password (the one that
+he typed in).
+When the user later tries to log in to the system, the password
+that he types is encrypted and compared with the encrypted
+version in the password file.
+If the two match, his login attempt is accepted.
+Such a scheme was first described
+in [3, p.91ff.].
+It also seemed advisable to devise
+a system in which neither the password file nor the
+password program itself needed to be
+protected against being read by anyone.
+.PP
+All that was needed to implement these ideas
+was to find a means of encryption that was very difficult
+to invert, even when the encryption program
+is available.
+Most of the standard encryption methods used (in the past)
+for encryption of messages are rather easy to invert.
+A convenient and rather good encryption program happened
+to exist on the system at the time; it simulated the
+M-209 cipher machine [4]
+used by the U.S. Army during World War II.
+It turned out that the M-209 program was usable, but with
+a given key, the ciphers produced by this program are
+trivial to invert.
+It is a much more difficult matter to find out the key
+given the cleartext input and the enciphered output of the program.
+Therefore,
+the password was used not as the text to be encrypted but as the
+key, and a constant was encrypted using this key.
+The encrypted result was entered into the password file.
+.SH
+ATTACKS ON THE FIRST APPROACH
+.PP
+Suppose that the bad guy has available
+the text of the password encryption program and
+the complete password file.
+Suppose also that he has substantial computing
+capacity at his disposal.
+.PP
+One obvious approach to penetrating the password
+mechanism is to attempt to find a general method of inverting
+the encryption algorithm.
+Very possibly this can be done, but few
+successful results
+have come to light, despite substantial efforts extending
+over a period of more than five years.
+The results have not proved to be very useful
+in penetrating systems.
+.PP
+Another approach to penetration is simply to keep trying
+potential
+passwords until one succeeds; this is a general cryptanalytic
+approach called
+.I
+key search.
+.R
+Human beings being what they are, there is a strong tendency
+for people to choose relatively short and simple passwords that
+they can remember.
+Given free choice, most people will choose their passwords
+from a restricted character set (e.g. all lower-case letters),
+and will often choose words or names.
+This human habit makes the key search job a great deal easier.
+.PP
+The critical factor involved in key search is the amount of
+time needed to encrypt a potential password and to check the result
+against an entry in the password file.
+The running time to encrypt one trial password and check
+the result turned out to be approximately 1.25 milliseconds on
+a PDP-11/70 when the encryption algorithm was recoded for
+maximum speed.
+It is takes essentially no more time to test the encrypted
+trial password against all the passwords in
+an entire password file, or for that matter, against
+any collection of encrypted passwords, perhaps collected
+from many installations.
+.PP
+If we want to check all passwords of length
+.I
+n
+.R
+that consist entirely of lower-case letters, the number
+of such passwords is $26 sup n$.
+If we suppose that the password consists of
+printable characters only, then the number of possible passwords
+is somewhat less than $95 sup n$.
+(The standard system ``character erase'' and ``line kill''
+characters are, for example, not prime
+candidates.)
+We can immediately estimate the running time of a program that
+will test every password of a given length with all of its
+characters chosen from some set of characters.
+The following table gives estimates of the running time
+required on a PDP-11/70
+to test all possible character strings of length $n$
+chosen from various sets of characters: namely, all lower-case
+letters, all lower-case letters plus digits,
+all alphanumeric characters, all 95 printable
+ASCII characters, and finally all 128 ASCII characters.
+.TS
+cccccc
+cccccc
+nnnnnn.
+       26 lower-case   36 lower-case letters   62 alphanumeric 95 printable    all 128 ASCII
+n      letters and digits      characters      characters      characters
+.sp .5
+1      30 msec.        40 msec.        80 msec.        120 msec.       160 msec.
+2      800 msec.       2 sec.  5 sec.  11 sec. 20 sec.
+3      22 sec. 58 sec. 5 min.  17 min. 43 min.
+4      10 min. 35 min. 5 hrs.  28 hrs. 93 hrs.
+5      4 hrs.  21 hrs. 318 hrs.
+6      107 hrs.
+.TE
+.LP
+One has to conclude that it is no great matter for someone with
+access to a PDP-11 to test all lower-case alphabetic strings up
+to length five
+and, given access to the machine for, say, several weekends, to test
+all such strings up to six characters in length.
+By using such a program against a collection of actual encrypted
+passwords, a substantial fraction of all the passwords will be
+found.
+.PP
+Another profitable approach for the bad guy is to use the word
+list from a dictionary or to use a list of names.
+For example, a large commercial dictionary contains typicallly about
+250,000 words; these words can be checked in about five minutes.
+Again, a noticeable fraction of any collection of passwords
+will be found.
+Improvements and extensions will be (and have been) found by
+a determined bad guy.
+Some ``good'' things to try are:
+.IP -
+The dictionary with the words spelled backwards.
+.IP -
+A list of first names (best obtained from some mailing list).
+Last names, street names, and city names also work well.
+.IP -
+The above with initial upper-case letters.
+.IP -
+All valid license plate numbers in your state.
+(This takes about five hours in New Jersey.)
+.IP -
+Room numbers, social security numbers, telephone numbers, and
+the like.
+.PP
+The authors have conducted experiments to try to determine
+typical users' habits in the choice of passwords when no
+constraint is put on their choice.
+The results were disappointing, except to the bad guy.
+In a collection of 3,289 passwords
+gathered from many users over a long period of time;
+.IP
+15 were a single ASCII character;
+.IP
+72 were strings of two ASCII characters;
+.IP
+464 were strings of three ASCII characters;
+.IP
+477 were string of four alphamerics;
+.IP
+706 were five letters, all upper-case or all lower-case;
+.IP
+605 were six letters, all lower-case.
+.LP
+An additional 492 passwords appeared in various available
+dictionaries, name lists, and the like.
+A total of 2,831, or 86% of this sample of passwords fell into one of
+these classes.
+.PP
+There was, of course, considerable overlap between the
+dictionary results and the character string searches.
+The dictionary search alone, which required only five
+minutes to run, produced about one third of the passwords.
+.PP
+Users could be urged (or forced) to use either longer passwords
+or passwords chosen from a larger character set, or the system
+could itself choose passwords for the users.
+.SH
+AN ANECDOTE
+.PP
+An entertaining and instructive example is
+the attempt made at one installation to force users to use less predictable
+passwords.
+The users did not choose their own passwords; the system supplied
+them.
+The supplied passwords were eight characters long and 
+were taken from the character set consisting of
+lower-case letters and digits.
+They were generated by a pseudo-random number generator
+with only $2 sup 15$ starting values.
+The time required to search (again on a PDP-11/70) through
+all character strings of length 8 from a 36-character
+alphabet is 112 years.
+.PP
+Unfortunately, only $2 sup 15$ of them need be looked at,
+because that is the number of possible outputs of the random
+number generator.
+The bad guy did, in fact, generate and test each of these strings
+and found every one of the system-generated passwords using
+a total of only about one minute of machine time.
+.SH
+IMPROVEMENTS TO THE FIRST APPROACH
+.NH
+Slower Encryption
+.PP
+Obviously, the first algorithm used was far too fast.
+The announcement of the DES encryption algorithm [2]
+by the National Bureau of Standards
+was timely and fortunate.
+The DES is, by design, hard to invert, but equally valuable
+is the fact that it is extremely slow when implemented in
+software.
+The DES was implemented and used in the following way:
+The first eight characters of the user's password are
+used as a key for the DES; then the algorithm
+is used to encrypt a constant.
+Although this constant is zero at the moment, it is easily
+accessible and can be made installation-dependent.
+Then the DES algorithm is iterated 25 times and the
+resulting 64 bits are repacked to become a string of
+11 printable characters.
+.NH
+Less Predictable Passwords
+.PP
+The password entry program was modified so as to urge
+the user to use more obscure passwords.
+If the user enters an alphabetic password (all upper-case or
+all lower-case) shorter than six characters, or a
+password from a larger character set shorter than five
+characters, then the program asks him to enter a
+longer password.
+This further reduces the efficacy of key search.
+.PP
+These improvements make it exceedingly difficult to find
+any individual password.
+The user is warned of the risks and if he cooperates,
+he is very safe indeed.
+On the other hand, he is not prevented from using
+his spouse's name if he wants to.
+.NH
+Salted Passwords
+.PP
+The key search technique is still
+likely to turn up a few passwords when it is used
+on a large collection of passwords, and it seemed wise to make this
+task as difficult as possible.
+To this end, when a password is first entered, the password program
+obtains a 12-bit random number (by reading the real-time clock)
+and appends this to the password typed in by the user.
+The concatenated string is encrypted and both the
+12-bit random quantity (called the $salt$) and the 64-bit
+result of the encryption are entered into the password
+file.
+.PP
+When the user later logs in to the system, the 12-bit
+quantity is extracted from the password file and appended
+to the typed password.
+The encrypted result is required, as before, to be the same as the
+remaining 64 bits in the password file.
+This modification does not increase the task of finding
+any individual
+password,
+starting from scratch,
+but now the work of testing a given character string
+against a large collection of encrypted passwords has
+been multiplied by 4096 ($2 sup 12$).
+The reason for this is that there are 4096 encrypted
+versions of each password and one of them has been picked more
+or less at random by the system.
+.PP
+With this modification,
+it is likely that the bad guy can spend days of computer
+time trying to find a password on a system with hundreds
+of passwords, and find none at all.
+More important is the fact that it becomes impractical
+to prepare an encrypted dictionary in advance.
+Such an encrypted dictionary could be used to crack
+new passwords in milliseconds when they appear.
+.PP
+There is a (not inadvertent) side effect of this
+modification.
+It becomes nearly impossible to find out whether a
+person with passwords on two or more systems has used
+the same password on all of them,
+unless you already know that.
+.NH
+The Threat of the DES Chip
+.PP
+Chips to perform the DES encryption are already commercially
+available and they are very fast.
+The use of such a chip speeds up the process of password
+hunting by three orders of magnitude.
+To avert this possibility, one of the internal tables
+of the DES algorithm
+(in particular, the so-called E-table)
+is changed in a way that depends on the 12-bit random
+number.
+The E-table is inseparably wired into the DES chip,
+so that the commercial chip cannot be used.
+Obviously, the bad guy could have his own chip designed and
+built, but the cost would be unthinkable.
+.NH
+A Subtle Point
+.PP
+To login successfully on the UNIX system, it is necessary
+after dialing in to type a valid user name, and then the
+correct password for that user name.
+It is poor design to write the login command in such a way that it
+tells an interloper when he has typed in a invalid user name.
+The response to an invalid name should be identical to
+that for a valid name.
+.PP
+When the slow encryption algorithm was first implemented,
+the encryption was done only if the user name was valid,
+because otherwise there was no encrypted password to
+compare with the supplied password.
+The result was that the response was delayed
+by about one-half second if the name was valid, but was
+immediate if invalid.
+The bad guy could find out
+whether a particular user name was valid.
+The routine was modified to do the encryption in either
+case.
+.SH
+CONCLUSIONS
+.PP
+On the issue of password security, UNIX is probably
+better than most systems.
+The use of encrypted passwords appears reasonably
+secure in the absence of serious attention of experts
+in the field.
+.PP
+It is also worth some effort to conceal even the encrypted
+passwords.
+Some UNIX systems have instituted what is called an
+``external security code'' that must be typed when
+dialing into the system, but before logging in.
+If this code is changed periodically, then someone
+with an old password will likely be prevented from
+using it.
+.PP
+Whenever any security procedure is instituted that attempts
+to deny access to unauthorized persons, it is wise to
+keep a record of both successful and unsuccessful attempts
+to get at the secured resource.
+Just as an out-of-hours visitor to a computer center normally
+must not only identify himself, but a record is usually also kept of
+his entry.
+Just so, it is a wise precaution to make and keep a record
+of all attempts to log into a remote-access time-sharing
+system, and certainly all unsuccessful attempts.
+.PP
+Bad guys fall on a spectrum whose one end is someone with
+ordinary access to a system and whose goal is to find
+out a particular password (usually that of the super-user)
+and, at the other end, someone who wishes to collect as
+much password information as possible from as many systems
+as possible.
+Most of the work reported here serves to frustrate the latter type;
+our experience indicates that the former type of bad guy never
+was very successful.
+.PP
+We recognize that a time-sharing system must operate in a
+hostile environment.
+We did not attempt to hide the security aspects of the operating
+system, thereby playing the customary make-believe game in
+which weaknesses of the system are not discussed no matter
+how apparent.
+Rather we advertised the password algorithm and invited attack
+in the belief that this approach would minimize future trouble.
+The approach has been successful.
+.SG MH-1271-RM/KT
+.SH
+References
+.IP [1]
+Ritchie, D.M. and Thompson, K.
+The UNIX Time-Sharing System.
+.I
+Comm. ACM
+.B
+17
+.R
+(July 1974),
+pp. 365-375.
+.IP [2]
+.I
+Proposed Federal Information Processing Data Encryption Standard.
+.R
+Federal Register (40FR12134), March 17, 1975
+.IP [3]
+Wilkes, M. V.
+.I
+Time-Sharing Computer Systems.
+.R
+American Elsevier,
+New York, (1968).
+.IP [4]
+U. S. Patent Number 2,089,603.
diff --git a/doc/7thEdMan/vol2/porttour.bun b/doc/7thEdMan/vol2/porttour.bun
new file mode 100644 (file)
index 0000000..5571822
--- /dev/null
@@ -0,0 +1,2762 @@
+# To unbundle, run this file
+echo porttour1
+sed 's/.//' >porttour1 <<'//GO.SYSIN DD porttour1'
+-.TL
+-A Tour Through the Portable C Compiler
+-.AU
+-S. C. Johnson
+-.AI
+-.MH
+-.SH
+-Introduction
+-.PP
+-A C compiler has been implemented that has proved to be quite portable,
+-serving as the basis for C compilers on roughly a dozen machines, including
+-the Honeywell 6000, IBM 370, and Interdata 8/32.
+-The compiler is highly compatible with the C language standard.
+-.[
+-Kernighan Ritchie Prentice 1978
+-.]
+-.PP
+-Among the goals of this compiler are portability, high reliability,
+-and the use of state-of-the-art techniques and tools wherever practical.
+-Although the efficiency of the compiling process is not
+-a primary goal, the compiler is efficient enough, and produces
+-good enough code, to serve as a production compiler.
+-.PP
+-The language implemented is highly compatible with the current PDP-11 version of C.
+-Moreover, roughly 75% of the compiler, including
+-nearly all the syntactic and semantic routines, is machine independent.
+-The compiler also serves as the major portion of the program
+-.I lint ,
+-described elsewhere.
+-.[
+-Johnson Lint Program Checker
+-.]
+-.PP
+-A number of earlier attempts to make portable compilers are worth noting.
+-While on CO-OP assignment to Bell Labs in 1973, Alan Snyder wrote a portable C
+-compiler which was the basis of his Master's Thesis at M.I.T.
+-.[
+-Snyder Portable C Compiler
+-.]
+-This compiler was very slow and complicated, and contained a number of rather
+-serious implementation difficulties;
+-nevertheless, a number of Snyder's ideas appear in this work.
+-.PP
+-Most earlier portable compilers, including Snyder's, have proceeded by
+-defining an intermediate language, perhaps based
+-on three-address code or code for a stack machine,
+-and writing a machine independent program to
+-translate from the source code to this
+-intermediate code.
+-The intermediate code is then read by a second pass, and interpreted or compiled.
+-This approach is elegant, and has a number of advantages, especially if the
+-target machine is far removed from the host.
+-It suffers from some disadvantages as well.
+-Some constructions, like initialization and subroutine prologs,
+-are difficult or expensive to express in a
+-machine independent way that still allows them
+-to be easily adapted to the target assemblers.
+-Most of these approaches require a symbol table to be constructed
+-in the second (machine dependent) pass, and/or
+-require powerful target assemblers.
+-Also, many conversion operators may be generated
+-that have no effect on a given machine,
+-but may be needed on others (for example, pointer to pointer
+-conversions usually do nothing in C, but must be generated because
+-there are some machines where they are significant).
+-.PP
+-For these reasons, the first pass of the portable compiler
+-is not entirely machine independent.
+-It contains some machine dependent features, such as initialization, subroutine
+-prolog and epilog, certain storage allocation functions,
+-code for the
+-.I switch
+-statement, and code to throw out unneeded conversion operators.
+-.PP
+-As a crude measure of the degree of
+-portability actually achieved,
+-the Interdata 8/32 C compiler has
+-roughly 600 machine dependent lines of source out of 4600 in Pass 1, and 1000
+-out of 3400 in Pass 2.
+-In total, 1600 out of 8000, or 20%,
+-of the total source is machine dependent
+-(12% in Pass 1, 30% in Pass 2).
+-These percentages can be expected to rise slightly as the
+-compiler is tuned.
+-The percentage of machine-dependent code for the IBM is 22%, for
+-the Honeywell 25%.
+-If the assembler format and structure were the same for all
+-these machines, perhaps another 5-10% of the code
+-would become machine independent.
+-.PP
+-These figures are sufficiently misleading as to be almost
+-meaningless.
+-A large fraction of the machine dependent code can be converted
+-in a straightforward, almost mechanical way.
+-On the other hand, a certain amount of the code requres hard
+-intellectual effort to convert, since the algorithms
+-embodied in this part of the code are typically complicated
+-and machine dependent.
+-.PP
+-To summarize, however, if you need a C compiler written for a machine with
+-a reasonable architecture, the compiler is already three quarters finished!
+-.SH
+-Overview
+-.PP
+-This paper discusses the structure and organization of the portable compiler.
+-The intent is to give the big picture, rather than discussing the details of a particular machine
+-implementation.
+-After a brief overview and a discussion of the source file structure,
+-the paper describes the major data structures, and then delves more
+-closely into the two passes.
+-Some of the theoretical work on which the compiler is based, and
+-its application to the compiler, is discussed elsewhere.
+-.[
+-johnson portable theory practice
+-.]
+-One of the major design issues in any C compiler, the design of
+-the calling sequence and stack frame, is the subject of a separate
+-memorandum.
+-.[
+-johnson lesk ritchie calling sequence
+-.]
+-.PP
+-The compiler consists of two passes,
+-.I pass1
+-and
+-.I pass2 ,
+-that together turn C source code into assembler code for the target
+-machine.
+-The two passes are preceded by a preprocessor, that
+-handles the
+-.B "#define"
+-and
+-.B "#include"
+-statements, and related features (e.g.,
+-.B #ifdef ,
+-etc.).
+-It is a nearly machine independent program, and will
+-not be further discussed here.
+-.PP
+-The output of the preprocessor is a text file that is read as the standard
+-input of the first pass.
+-This
+-produces as standard output another text file that becomes the standard
+-input of the second pass.
+-The second pass produces, as standard output, the desired assembler language source code.
+-The preprocessor and the two passes
+-all write error messages on the standard error file.
+-Thus the compiler itself makes few demands on the I/O
+-library support, aiding in the bootstrapping process.
+-.PP
+-Although the compiler is divided into two passes,
+-this represents historical accident more than deep necessity.
+-In fact, the compiler can optionally be loaded
+-so that both passes operate in the same program.
+-This ``one pass'' operation eliminates the overhead of
+-reading and writing the intermediate file, so the compiler
+-operates about 30% faster in this mode.
+-It also occupies about 30% more space than the larger
+-of the two component passes.
+-.PP
+-Because the compiler is fundamentally structured as two
+-passes, even when loaded as one, this document primarily
+-describes the two pass version.
+-.PP
+-The first pass does the lexical analysis, parsing, and
+-symbol table maintenance.
+-It also constructs parse trees for expressions,
+-and keeps track of the types of the nodes in these trees.
+-Additional code is devoted to initialization.
+-Machine dependent portions of the first pass serve to
+-generate subroutine prologs and epilogs,
+-code for switches, and code for branches, label definitions,
+-alignment operations,
+-changes of location counter, etc.
+-.PP
+-The intermediate file is a text file organized into lines.
+-Lines beginning with a right parenthesis are copied by the second
+-pass directly to its output file, with the
+-parenthesis stripped off.
+-Thus, when the first pass produces assembly code, such as subroutine prologs,
+-etc., each line is prefaced with a right parenthesis;
+-the second pass passes these lines to through to the assembler.
+-.PP
+-The major job done by the second pass is generation of code
+-for expressions.
+-The expression parse trees produced in the first pass are
+-written onto the
+-intermediate file in Polish Prefix form:
+-first, there is a line beginning with a period, followed by the source
+-file line number and name on which the expression appeared (for debugging purposes).
+-The successive lines represent the nodes of the parse tree,
+-one node per line.
+-Each line contains the node number, type, and
+-any values (e.g., values of constants)
+-that may appear in the node.
+-Lines representing nodes with descendants are immediately
+-followed by the left subtree of descendants, then the
+-right.
+-Since the number of descendants of any node is completely
+-determined by the node number, there is no need to mark the end
+-of the tree.
+-.PP
+-There are only two other line types in the intermediate file.
+-Lines beginning with a left square bracket (`[') represent the beginning of
+-blocks (delimited by { ... } in the C source);
+-lines beginning with right square brackets (`]') represent the end of blocks.
+-The remainder of these lines tell how much
+-stack space, and how many register variables,
+-are currently in use.
+-.PP
+-Thus, the second pass reads the intermediate files, copies the `)' lines,
+-makes note of the information in the `[' and `]' lines,
+-and devotes most of its effort to the
+-`.' lines and their associated expression trees, turning them
+-turns into assembly code to evaluate the expressions.
+-.PP
+-In the one pass version of the compiler, the expression
+-trees that are built by the first pass have
+-been declared to have room for the second pass
+-information as well.
+-Instead of writing the trees onto an intermediate file,
+-each tree is transformed in place into an acceptable
+-form for the code generator.
+-The code generator then writes the result of compiling
+-this tree onto the standard output.
+-Instead of `[' and `]' lines in the intermediate file, the information is passed
+-directly to the second pass routines.
+-Assembly code produced by the first pass is simply written out,
+-without the need for ')' at the head of each line.
+-.SH
+-The Source Files
+-.PP
+-The compiler source consists of 22 source files.
+-Two files,
+-.I manifest
+-and
+-.I macdefs ,
+-are header files included with all other files.
+-.I Manifest
+-has declarations for the node numbers, types, storage classes,
+-and other global data definitions.
+-.I Macdefs
+-has machine-dependent definitions, such as the size and alignment of the
+-various data representations.
+-Two machine independent header files,
+-.I mfile1
+-and
+-.I mfile2 ,
+-contain the data structure and manifest definitions
+-for the first and second passes, respectively.
+-In the second pass, a machine dependent header file,
+-.I mac2defs ,
+-contains declarations of register names, etc.
+-.PP
+-There is a file,
+-.I common ,
+-containing (machine independent) routines used in both passes.
+-These include routines for allocating and freeing trees, walking over trees,
+-printing debugging information, and printing error messages.
+-There are two dummy files,
+-.I comm1.c
+-and
+-.I comm2.c ,
+-that simply include
+-.I common
+-within the scope of the appropriate pass1 or pass2 header files.
+-When the compiler is loaded as a single pass,
+-.I common
+-only needs to be included once:
+-.I comm2.c
+-is not needed.
+-.PP
+-Entire sections of this document are devoted to the detailed structure of the
+-passes.
+-For the moment, we just give a brief description of the files.
+-The first pass
+-is obtained by compiling and loading
+-.I scan.c ,
+-.I cgram.c ,
+-.I xdefs.c ,
+-.I pftn.c ,
+-.I trees.c ,
+-.I optim.c ,
+-.I local.c ,
+-.I code.c ,
+-and
+-.I comm1.c .
+-.I Scan.c
+-is the lexical analyzer, which is used by
+-.I cgram.c ,
+-the result of applying
+-.I Yacc
+-.[
+-Johnson Yacc Compiler cstr
+-.]
+-to the input grammar
+-.I cgram.y .
+-.I Xdefs.c
+-is a short file of external definitions.
+-.I Pftn.c
+-maintains the symbol table, and does initialization.
+-.I Trees.c
+-builds the expression trees, and computes the node types.
+-.I Optim.c
+-does some machine independent optimizations on the expression trees.
+-.I Comm1.c
+-includes
+-.I common ,
+-that contains service routines common to the two passes of the compiler.
+-All the above files are machine independent.
+-The files
+-.I local.c
+-and
+-.I code.c
+-contain machine dependent code for generating subroutine
+-prologs, switch code, and the like.
+-.PP
+-The second pass
+-is produced by compiling and loading
+-.I reader.c ,
+-.I allo.c ,
+-.I match.c ,
+-.I comm1.c ,
+-.I order.c ,
+-.I local.c ,
+-and
+-.I table.c .
+-.I Reader.c
+-reads the intermediate file, and controls the major logic of the
+-code generation.
+-.I Allo.c
+-keeps track of busy and free registers.
+-.I Match.c
+-controls the matching
+-of code templates to subtrees of the expression tree to be compiled.
+-.I Comm2.c
+-includes the file
+-.I common ,
+-as in the first pass.
+-The above files are machine independent.
+-.I Order.c
+-controls the machine dependent details of the code generation strategy.
+-.I Local2.c
+-has many small machine dependent routines,
+-and tables of opcodes, register types, etc.
+-.I Table.c
+-has the code template tables,
+-which are also clearly machine dependent.
+-.SH
+-Data Structure Considerations.
+-.PP
+-This section discusses the node numbers, type words, and expression trees, used
+-throughout both passes of the compiler.
+-.PP
+-The file
+-.I manifest
+-defines those symbols used throughout both passes.
+-The intent is to use the same symbol name (e.g., MINUS)
+-for the given operator throughout the lexical analysis, parsing, tree building,
+-and code generation phases;
+-this requires some synchronization with the
+-.I Yacc
+-input file,
+-.I cgram.y ,
+-as well.
+-.PP
+-A token
+-like MINUS may be seen in the lexical analyzer before it is known
+-whether it is a unary or binary operator;
+-clearly, it is necessary to know this by the time the parse tree
+-is constructed.
+-Thus, an operator (really a macro) called
+-UNARY is provided, so that MINUS
+-and UNARY MINUS are both distinct node numbers.
+-Similarly, many binary operators exist in an assignment form (for example, \-=),
+-and the operator ASG may be applied to such node names to generate new ones, e.g. ASG MINUS.
+-.PP
+-It is frequently desirable to know if a node represents a leaf (no descendants), a unary operator (one
+-descendant) or a binary operator (two descendants).
+-The macro
+-.I optype(o)
+-returns one of the manifest constants LTYPE, UTYPE, or BITYPE, respectively, depending
+-on the node number
+-.I o .
+-Similarly,
+-.I asgop(o)
+-returns true if
+-.I o
+-is an assignment operator number (=, +=, etc. ), and
+-.I logop(o)
+-returns true if
+-.I o
+-is a relational or logical (&&, \(or\(or, or !) operator.
+-.PP
+-C has a rich typing structure, with a potentially infinite number of types.
+-To begin with, there are the basic types: CHAR, SHORT, INT, LONG, the unsigned versions
+-known as
+-UCHAR, USHORT, UNSIGNED, ULONG, and FLOAT, DOUBLE,
+-and finally
+-STRTY (a structure), UNIONTY, and ENUMTY.
+-Then, there are three operators that can be applied to types to make others:
+-if
+-.I t
+-is a type, we may potentially have types
+-.I "pointer to t" ,
+-.I "function returning t" ,
+-and
+-.I "array of t's"
+-generated from
+-.I t .
+-Thus, an arbitrary type in C consists of a basic type, and zero or more of these operators.
+-.PP
+-In the compiler, a type is represented by an unsigned integer; the rightmost four bits hold the basic
+-type, and the remaining bits are divided into two-bit fields, containing
+-0 (no operator), or one of the three operators
+-described above.
+-The modifiers are read right to left in the word, starting with the two-bit
+-field adjacent to the basic type, until a field with 0 in it is reached.
+-The macros PTR, FTN, and ARY represent the
+-.I "pointer to" ,
+-.I "function returning" ,
+-and
+-.I "array of"
+-operators.
+-The macro values are shifted so that they align with the first two-bit
+-field; thus PTR+INT
+-represents the type for an integer pointer, and
+-.DS
+-ARY + (PTR<<2) + (FTN<<4) + DOUBLE
+-.DE
+-represents the type of an array of pointers to functions returning doubles.
+-.PP
+-The type words are ordinarily manipulated by macros.
+-If
+-.I t
+-is a type word,
+-.I BTYPE(t)
+-gives the basic type.
+-.I ISPTR(t) ,
+-.I ISARY(t) ,
+-and
+-.I ISFTN(t)
+-ask if an object of this type is a pointer, array, or a function,
+-respectively.
+-.I MODTYPE(t,b)
+-sets the basic type of
+-.I t
+-to
+-.I b .
+-.I DECREF(t)
+-gives the type resulting from removing the first operator from
+-.I t .
+-Thus, if
+-.I t
+-is a pointer to
+-.I t' ,
+-a function returning
+-.I t' ,
+-or an array of
+-.I t' ,
+-then
+-.I DECREF(t)
+-would equal
+-.I t' .
+-.I INCREF(t)
+-gives the type representing a pointer to
+-.I t .
+-Finally, there are operators for dealing with the unsigned types.
+-.I ISUNSIGNED(t)
+-returns true if
+-.I t
+-is one of the four basic unsigned types;
+-in this case,
+-.I DEUNSIGN(t)
+-gives the associated `signed' type.
+-Similarly,
+-.I UNSIGNABLE(t)
+-returns true if
+-.I t
+-is one of the four basic types that could become unsigned, and
+-.I ENUNSIGN(t)
+-returns the unsigned analogue of
+-.I t
+-in this case.
+-.PP
+-The other important global data structure is that of expression trees.
+-The actual shapes of the nodes are given in
+-.I mfile1
+-and
+-.I mfile2 .
+-They are not the same in the two passes; the first pass nodes contain
+-dimension and size information, while the second pass
+-nodes contain register allocation information.
+-Nevertheless, all nodes contain fields called
+-.I op ,
+-containing the node number,
+-and
+-.I type ,
+-containing the type word.
+-A function called
+-.I talloc()
+-returns a pointer to a new tree node.
+-To free a node, its
+-.I op
+-field need merely be set to FREE.
+-The other fields in the node will remain intact at least until the next allocation.
+-.PP
+-Nodes representing binary operators contain fields,
+-.I left
+-and
+-.I right ,
+-that contain pointers to the left and right descendants.
+-Unary operator nodes have the
+-.I left
+-field, and a value field called
+-.I rval .
+-Leaf nodes, with no descendants, have two value fields:
+-.I lval
+-and
+-.I rval .
+-.PP
+-At appropriate times, the function
+-.I tcheck()
+-can be called, to check that there are no busy nodes remaining.
+-This is used as a compiler consistency check.
+-The function
+-.I tcopy(p)
+-takes a pointer
+-.I p
+-that points to an expression tree, and returns a pointer
+-to a disjoint copy of the tree.
+-The function
+-.I walkf(p,f)
+-performs a postorder walk of the tree pointed to by
+-.I p ,
+-and applies the function
+-.I f
+-to each node.
+-The function
+-.I fwalk(p,f,d)
+-does a preorder walk of the tree pointed to by
+-.I p .
+-At each node, it calls a function
+-.I f ,
+-passing to it the node pointer, a value passed down
+-from its ancestor, and two pointers to values to be passed
+-down to the left and right descendants (if any).
+-The value
+-.I d
+-is the value passed down to the root.
+-.a
+-.I Fwalk
+-is used for a number of tree labeling and debugging activities.
+-.PP
+-The other major data structure, the symbol table, exists only in pass one,
+-and will be discussed later.
+-.SH
+-Pass One
+-.PP
+-The first pass does lexical analysis, parsing, symbol table maintenance,
+-tree building, optimization, and a number of machine dependent things.
+-This pass is largely machine independent, and the machine independent
+-sections can be pretty successfully ignored.
+-Thus, they will be only sketched here.
+-.SH
+-Lexical Analysis
+-.PP
+-The lexical analyzer is a conceptually simple routine that reads the input
+-and returns the tokens of the C language as it encounters them:
+-names, constants, operators, and keywords.
+-The conceptual simplicity of this job is confounded a bit by several
+-other simple jobs that unfortunately must go on simultaneously.
+-These include
+-.IP \(bu
+-Keeping track of the current filename and line number, and occasionally
+-setting this information as the result of preprocessor control lines.
+-.IP \(bu
+-Skipping comments.
+-.IP \(bu
+-Properly dealing with octal, decimal, hex, floating
+-point, and character constants, as well as character strings.
+-.PP
+-To achieve speed, the program maintains several tables
+-that are indexed into by character value, to tell
+-the lexical analyzer what to do next.
+-To achieve portability, these tables must be initialized
+-each time the compiler is run, in order that the
+-table entries reflect the local character set values.
+-.SH
+-Parsing
+-.PP
+-As mentioned above, the parser is generated by Yacc from the grammar on file
+-.I cgram.y.
+-The grammar is relatively readable, but contains some unusual features
+-that are worth comment.
+-.PP
+-Perhaps the strangest feature of the grammar is the treatment of
+-declarations.
+-The problem is to keep track of the basic type
+-and the storage class while interpreting the various
+-stars, brackets, and parentheses that may surround a given name.
+-The entire declaration mechanism must be recursive,
+-since declarations may appear within declarations of
+-structures and unions, or even within a
+-.B sizeof
+-construction
+-inside a dimension in another declaration!
+-.PP
+-There are some difficulties in using a bottom-up parser,
+-such as produced by Yacc, to handle constructions where a lot
+-of left context information must be kept around.
+-The problem is that the original PDP-11 compiler is top-down in
+-implementation, and some of the semantics of C reflect this.
+-In a top-down parser, the input rules are restricted
+-somewhat, but one can naturally associate temporary
+-storage with a rule at a very early stage in the recognition
+-of that rule.
+-In a bottom-up parser, there is more freedom in the
+-specification of rules, but it is more difficult to know what
+-rule is being matched until the entire rule is seen.
+-The parser described by
+-.I cgram.c
+-makes effective use of
+-the bottom-up parsing mechanism in some places (notably the treatment
+-of expressions), but struggles against the
+-restrictions in others.
+-The usual result is that it is necessary to run a stack of values
+-``on the side'', independent of the Yacc value stack,
+-in order to be able to store and access information
+-deep within inner constructions, where the relationship of the
+-rules being recognized to the total picture is not yet clear.
+-.PP
+-In the case of declarations, the attribute information
+-(type, etc.) for a declaration is carefully
+-kept immediately to the left of the declarator
+-(that part of the declaration involving the name).
+-In this way, when it is time to declare the name, the
+-name and the type information can be quickly brought together.
+-The ``$0'' mechanism of Yacc is used to accomplish this.
+-The result is not pretty, but it works.
+-The storage class information changes more slowly,
+-so it is kept in an external variable, and stacked if
+-necessary.
+-Some of the grammar could be considerably cleaned up by using
+-some more recent features of Yacc, notably actions within
+-rules and the ability to return multiple values for actions.
+-.PP
+-A stack is also used to keep track of the current location
+-to be branched to when a
+-.B break
+-or
+-.B continue
+-statement is processed.
+-.PP
+-This use of external stacks dates from the time when Yacc did not permit
+-values to be structures.
+-Some, or most, of this use of external stacks
+-could be eliminated by redoing the grammar to use the mechanisms now provided.
+-There are some areas, however, particularly the processing of structure, union,
+-and enum declarations, function
+-prologs, and switch statement processing, when having
+-all the affected data together in an array speeds later
+-processing; in this case, use of external storage seems essential.
+-.PP
+-The
+-.I cgram.y
+-file also contains some small functions used as
+-utility functions in the parser.
+-These include routines for saving case values and labels in processing switches,
+-and stacking and popping 
+-values on the external stack described above.
+-.SH
+-Storage Classes
+-.PP
+-C has a finite, but fairly extensive, number of storage classes
+-available.
+-One of the compiler design decisions was to
+-process the storage class information totally in the first pass;
+-by the second pass, this information must have
+-been totally dealt with.
+-This means that all of the storage allocation must take place in the first
+-pass, so that references to automatics and
+-parameters can be turned into references to cells lying a certain
+-number of bytes offset from certain machine registers.
+-Much of this transformation is machine dependent, and strongly
+-depends on the storage class.
+-.PP
+-The classes include EXTERN (for externally declared, but not defined variables),
+-EXTDEF (for external definitions), and similar distinctions for
+-USTATIC and STATIC, UFORTRAN and FORTRAN (for fortran functions) and
+-ULABEL and LABEL.
+-The storage classes REGISTER and AUTO are obvious, as
+-are STNAME, UNAME, and ENAME (for structure, union, and enumeration
+-tags), and the associated MOS, MOU, and MOE (for the members).
+-TYPEDEF is treated as a storage class as well.
+-There are two special storage classes: PARAM and SNULL.
+-SNULL is used to distinguish the case where no explicit
+-storage class has been given; before an entry is made
+-in the symbol table the true storage class is discovered.
+-Similarly, PARAM is used for the temporary entry in the symbol
+-table made before the declaration of function parameters is completed.
+-.PP
+-The most complexity in the storage class process comes from
+-bit fields.
+-A separate storage class is kept for each width bit field;
+-a
+-.I k
+-bit bit field has storage class
+-.I k
+-plus FIELD.
+-This enables the size to be quickly recovered from the storage class.
+-.SH
+-Symbol Table Maintenance.
+-.PP
+-The symbol table routines do far more than simply enter
+-names into the symbol table;
+-considerable semantic processing and checking is done as well.
+-For example, if a new declaration comes in, it must be checked
+-to see if there is a previous declaration of the same symbol.
+-If there is, there are many cases.
+-The declarations may agree and be compatible (for example,
+-an extern declaration can appear twice) in which case the
+-new declaration is ignored.
+-The new declaration may add information (such as an explicit array
+-dimension) to an already present declaration.
+-The new declaration may be different, but still correct (for example,
+-an extern declaration of something may be entered,
+-and then later the definition may be seen).
+-The new declaration may be incompatible, but appear in an inner block;
+-in this case, the old declaration is carefully hidden away, and
+-the new one comes into force until the block is left.
+-Finally, the declarations may be incompatible, and an error
+-message must be produced.
+-.PP
+-A number of other factors make for additional complexity.
+-The type declared by the user is not always the type
+-entered into the symbol table (for example, if an formal parameter to a function
+-is declared to be an array, C requires that this be changed into
+-a pointer before entry in the symbol table).
+-Moreover, there are various kinds of illegal types that
+-may be declared which are difficult to
+-check for syntactically (for example,
+-a function returning an array).
+-Finally, there is a strange feature in C that requires
+-structure tag names and member names for structures and unions
+-to be taken from a different logical symbol table than ordinary identifiers.
+-Keeping track of which kind of name is involved is a bit of struggle
+-(consider typedef names used within structure declarations, for example).
+-.PP
+-The symbol table handling routines have been rewritten a number of times to
+-extend features, improve performance, and fix bugs.
+-They address the above problems with reasonable effectiveness
+-but a singular lack of grace.
+-.PP
+-When a name is read in the input, it is hashed, and the
+-routine
+-.I lookup
+-is called, together with a flag which tells which symbol table
+-should be searched (actually, both symbol tables are stored in one, and a flag
+-is used to distinguish individual entries).
+-If the name is found,
+-.I lookup
+-returns the index to the entry found; otherwise, it makes
+-a new entry, marks it UNDEF (undefined), and returns the
+-index of the new entry.
+-This index is stored in the
+-.I rval
+-field of a NAME node.
+-.PP
+-When a declaration is being parsed, this NAME node is
+-made part of a tree with UNARY MUL nodes for each *,
+-LB nodes for each array descriptor (the right descendant
+-has the dimension), and UNARY CALL nodes for each function
+-descriptor.
+-This tree is passed to the routine
+-.I tymerge ,
+-along with the attribute type of the whole declaration;
+-this routine collapses the tree to a single node, by calling
+-.I tyreduce ,
+-and then modifies the type to reflect the overall
+-type of the declaration.
+-.PP
+-Dimension and size information is stored in a table called
+-.I dimtab .
+-To properly describe a type in C, one needs not just the
+-type information but also size information (for structures and
+-enums) and dimension information (for arrays).
+-Sizes and offsets are dealt with in the compiler by
+-giving the associated indices into
+-.I dimtab .
+-.I Tymerge
+-and
+-.I tyreduce
+-call
+-.I dstash
+-to put the discovered dimensions away into the
+-.I dimtab
+-array.
+-.I Tymerge
+-returns a pointer to a single node that contains
+-the symbol table index in its
+-.I rval
+-field, and the size and dimension indices in
+-fields
+-.I csiz
+-and
+-.I cdim ,
+-respectively.
+-This information is properly considered part of the type in the first pass,
+-and is carried around at all times.
+-.PP
+-To enter an element into the symbol table, the routine
+-.I defid
+-is called; it is handed a storage class, and a pointer
+-to the node produced by
+-.I tymerge .
+-.I Defid
+-calls
+-.I fixtype ,
+-which adjusts and checks the given type depending on the storage
+-class, and converts null types appropriately.
+-It then calls
+-.I fixclass ,
+-which does a similar job for the storage class;
+-it is here, for example, that
+-register declarations are either allowed or changed
+-to auto.
+-.PP
+-The new declaration is now compared against an older one,
+-if present, and several pages of validity checks performed.
+-If the definitions are compatible, with possibly some added information,
+-the processing is straightforward.
+-If the definitions differ, the block levels of the
+-current and the old declaration are compared.
+-The current block level is kept in
+-.I blevel ,
+-an external variable; the old declaration level is kept in the symbol table.
+-Block level 0 is for external declarations, 1 is for arguments to functions,
+-and 2 and above are blocks within a function.
+-If the current block level is the same as the old declaration, an error
+-results.
+-If the current block level is higher, the new declaration overrides the old.
+-This is done by marking the old symbol table entry ``hidden'', and making
+-a new entry, marked ``hiding''.
+-.I Lookup
+-will skip over hidden entries.
+-When a block is left, the symbol table is searched,
+-and any entries defined in that block are destroyed; if
+-they hid other entries, the old entries are ``unhidden''.
+-.PP
+-This nice block structure is warped a bit because labels
+-do not follow the block structure rules (one can do a
+-.B goto
+-into
+-a block, for example);
+-default definitions of functions in inner blocks also persist clear out to the outermost scope.
+-This implies that cleaning up the symbol table after block exit is more
+-subtle than it might first seem.
+-.PP
+-For successful new definitions,
+-.I defid
+-also initializes a ``general purpose'' field,
+-.I offset ,
+-in the symbol table.
+-It contains the stack offset for automatics and parameters, the register number
+-for register variables, the bit offset into the structure for
+-structure members, and
+-the internal label number for static variables and labels.
+-The offset field is set by
+-.I falloc
+-for bit fields, and
+-.I dclstruct
+-for structures and unions.
+-.PP
+-The symbol table entry itself thus contains
+-the name, type word, size and dimension offsets,
+-offset value, and declaration block level.
+-It also has a field of flags, describing what symbol table the
+-name is in, and whether the entry is hidden, or hides another.
+-Finally, a field gives the line number of the last use,
+-or of the definition, of the name.
+-This is used mainly for diagnostics, but is useful to
+-.I lint
+-as well.
+-.PP
+-In some special cases, there is more than the above amount of information kept
+-for the use of the compiler.
+-This is especially true with structures; for use in initialization,
+-structure declarations must have access to a list of the members of the
+-structure.
+-This list is also kept in
+-.I dimtab .
+-Because a structure can be mentioned long before the
+-members are known, it is necessary to have another
+-level of indirection in the table.
+-The two words following the
+-.I csiz
+-entry in
+-.I dimtab
+-are used to hold the alignment of the structure, and
+-the index in dimtab of the list of members.
+-This list contains the symbol table indices for the structure members, terminated by a
+-\-1.
+-.SH
+-Tree Building
+-.PP
+-The portable compiler transforms expressions
+-into expression trees.
+-As the parser recognizes each rule making up an
+-expression,
+-it calls
+-.I buildtree
+-which is given an operator number, and pointers to the
+-left and right descendants.
+-.I Buildtree
+-first examines the left and right descendants,
+-and, if they are both constants, and the operator
+-is appropriate, simply does the constant
+-computation at compile time, and returns
+-the result as a constant.
+-Otherwise,
+-.I buildtree
+-allocates a node for the head of the tree,
+-attaches the descendants to it, and ensures that
+-conversion operators are generated if needed, and that
+-the type of the new node is consistent with the types
+-of the operands.
+-There is also a considerable amount of semantic complexity here;
+-many combinations of types are illegal, and the portable
+-compiler makes a strong effort to check
+-the legality of expression types completely.
+-This is done both for
+-.I lint
+-purposes, and to prevent such semantic errors
+-from being passed through to the code generator.
+-.PP
+-The heart of
+-.I buildtree
+-is a large table, accessed by the routine
+-.I opact .
+-This routine maps the types of the left and right
+-operands into a rather smaller set of descriptors, and then
+-accesses a table (actually encoded in a switch statement) which
+-for each operator and pair of types causes
+-an action to be returned.
+-The actions are logical or's of a number of
+-separate actions, which may be
+-carried out by
+-.I buildtree .
+-These component actions may include
+-checking the left side to ensure that it
+-is an lvalue (can be stored into),
+-applying a type conversion to the left or right operand,
+-setting the type of the new node to
+-the type of the left or right operand, calling various
+-routines to balance the types of the left and right operands,
+-and suppressing the ordinary conversion
+-of arrays and function operands to pointers.
+-An important operation is OTHER, which causes
+-some special code to be invoked
+-in
+-.I buildtree ,
+-to handle issues which are unique to a particular operator.
+-Examples of this are
+-structure and union reference
+-(actually handled by
+-the routine
+-.I stref ),
+-the building of NAME, ICON, STRING and FCON (floating point constant) nodes,
+-unary * and &, structure assignment, and calls.
+-In the case of unary * and &,
+-.I buildtree
+-will cancel a * applied to a tree, the top node of which
+-is &, and conversely.
+-.PP
+-Another special operation is
+-PUN; this
+-causes the compiler to check for type mismatches,
+-such as intermixing pointers and integers.
+-.PP
+-The treatment of conversion operators is still a rather
+-strange area of the compiler (and of C!).
+-The recent introduction of type casts has only confounded this
+-situation.
+-Most of the conversion operators are generated by
+-calls to
+-.I tymatch
+-and
+-.I ptmatch ,
+-both of which are given a tree, and asked to make the
+-operands agree in type.
+-.I Ptmatch
+-treats the case where one of the operands is a pointer;
+-.I tymatch
+-treats all other cases.
+-Where these routines have decided on the
+-proper type for an operand, they call
+-.I makety ,
+-which is handed a tree, and a type word, dimension offset, and size offset.
+-If necessary, it inserts a conversion operation to make the
+-types correct.
+-Conversion operations are never inserted on the left side of
+-assignment operators, however.
+-There are two conversion operators used;
+-PCONV, if the conversion is to a non-basic type (usually a pointer),
+-and
+-SCONV, if the conversion is to a basic type (scalar).
+-.PP
+-To allow for maximum flexibility, every node produced by
+-.I buildtree
+-is given to a machine dependent routine,
+-.I clocal ,
+-immediately after it is produced.
+-This is to allow more or less immediate rewriting of those
+-nodes which must be adapted for the local machine.
+-The conversion operations are given to
+-.I clocal
+-as well; on most machines, many of these
+-conversions do nothing, and should be thrown away
+-(being careful to retain the type).
+-If this operation is done too early,
+-however,
+-later calls to
+-.I buildtree
+-may get confused about correct type of the
+-subtrees;
+-thus
+-.I clocal
+-is given the conversion ops only after the entire tree is built.
+-This topic will be dealt with in more detail later.
+-.SH
+-Initialization
+-.PP
+-Initialization is one of the messier areas in the portable compiler.
+-The only consolation is that most of the mess takes place
+-in the machine independent part, where it
+-is may be safely ignored by the implementor of the
+-compiler for a particular machine.
+-.PP
+-The basic problem is that the semantics of initialization
+-really calls for a co-routine structure; one collection
+-of programs reading constants from the input stream, while another,
+-independent set of programs places these constants into the
+-appropriate spots in memory.
+-The dramatic differences in the local assemblers also
+-come to the fore here.
+-The parsing problems are dealt with by keeping a rather
+-extensive stack containing the current
+-state of the initialization; the assembler
+-problems are dealt with by having a fair number of machine dependent routines.
+-.PP
+-The stack contains the symbol table number,
+-type, dimension index, and size index for the current identifier
+-being initialized.
+-Another entry has the offset, in bits, of the beginning
+-of the current identifier.
+-Another entry keeps track of how many elements have been seen,
+-if the current identifier is an array.
+-Still another entry keeps track of the current
+-member of a structure being initialized.
+-Finally, there is an entry containing flags
+-which keep track of the current state of the initialization process
+-(e.g., tell if a } has been seen for the current identifier.)
+-.PP
+-When an initialization begins, the routine
+-.I beginit
+-is called; it handles the alignment restrictions, if
+-any, and calls
+-.I instk
+-to create the stack entry.
+-This is done by first making an entry on the top of the stack for the item
+-being initialized.
+-If the top entry is an array, another entry is made on the stack
+-for the first element.
+-If the top entry is a structure, another entry is made on the
+-stack for the first member of the structure.
+-This continues until the top element of the stack is a scalar.
+-.I Instk
+-then returns, and the parser begins collecting initializers.
+-.PP
+-When a constant is obtained, the routine
+-.I doinit
+-is called; it examines the stack, and does whatever
+-is necessary to assign the current constant to the
+-scalar on the top of the stack.
+-.I gotscal
+-is then called, which rearranges the stack so that the
+-next scalar to be initialized gets placed on top of the stack.
+-This process continues until the end of the initializers;
+-.I endinit
+-cleans up.
+-If a { or } is encountered in the
+-string of initializers, it is handled by calling
+-.I ilbrace
+-or
+-.I irbrace ,
+-respectively.
+-.PP
+-A central issue is the treatment of the ``holes'' that
+-arise as a result of alignment restrictions or explicit
+-requests for holes in bit fields.
+-There is a global variable,
+-.I inoff ,
+-which contains the current offset in the initialization
+-(all offsets in the first pass of the compiler are in bits).
+-.I Doinit
+-figures out from the top entry on the stack the expected
+-bit offset of the next identifier; it calls the
+-machine dependent
+-routine
+-.I inforce
+-which, in a machine dependent way, forces
+-the assembler to
+-set aside space if need be so that the
+-next scalar seen will go into the appropriate
+-bit offset position.
+-The scalar itself is passed to one of the machine dependent
+-routines
+-.I fincode 
+-(for floating point initialization),
+-.I incode
+-(for fields, and other initializations less than an int in
+-size),
+-and
+-.I cinit
+-(for all other initializations).
+-The size is passed to all these routines, and it is up to
+-the machine dependent routines to ensure that the
+-initializer occupies exactly the right size.
+-.PP
+-Character strings represent a bit of an exception.
+-If a character string is seen as the initializer for
+-a pointer, the characters making up the string must
+-be put out under a different location counter.
+-When the lexical analyzer sees the quote at the head
+-of a character string, it returns the token STRING,
+-but does not do anything with the contents.
+-The parser calls
+-.I getstr ,
+-which sets up the appropriate location counters
+-and flags, and calls
+-.I lxstr
+-to read and process the contents of the string.
+-.PP
+-If the string is being used to initialize a character array,
+-.I lxstr
+-calls
+-.I putbyte ,
+-which in effect simulates
+-.I doinit
+-for each character read.
+-If the string is used to initialize a character pointer,
+-.I lxstr
+-calls a machine dependent routine,
+-.I bycode ,
+-which stashes away each character.
+-The pointer to this string is then returned,
+-and processed normally by
+-.I doinit .
+-.PP
+-The null at the end of the string is treated as if it
+-were read explicitly by
+-.I lxstr .
+-.SH
+-Statements
+-.PP
+-The first pass addresses four main areas; declarations, expressions, initialization, and statements.
+-The statement processing is relatively simple; most of it is carried out in the
+-parser directly.
+-Most of the logic is concerned with allocating
+-label numbers, defining the labels, and branching appropriately.
+-An external symbol,
+-.I reached ,
+-is 1 if a statement can be reached, 0 otherwise; this is
+-used to do a bit of simple flow analysis as the program is being parsed,
+-and also to avoid generating the subroutine return sequence if the subroutine
+-cannot ``fall through'' the last statement.
+-.PP
+-Conditional branches are handled by generating an expression
+-node, CBRANCH,
+-whose left descendant is the conditional expression and the
+-right descendant is an ICON node containing the internal label
+-number to be branched to.
+-For efficiency, the semantics are that
+-the label is gone to if the condition is
+-.I false .
+-.PP
+-The switch statement is 
+-compiled by collecting the case entries, and an indication as to whether
+-there is a default case;
+-an internal label number is generated for each of these,
+-and remembered in a big array.
+-The expression comprising the value to be switched on is
+-compiled when the switch keyword is encountered,
+-but the expression tree is headed by
+-a special node, FORCE, which tells the code generator to
+-put the expression value into a special distinguished
+-register (this same mechanism is used for processing the
+-return statement).
+-When the end of the switch block is reached, the array
+-containing the case values is sorted, and checked for
+-duplicate entries (an error); if all is
+-correct, the machine dependent routine
+-.I genswitch
+-is called, with this array of labels and values in increasing order.
+-.I Genswitch
+-can assume that the value to be tested is already in the
+-register which is the usual integer return value register.
+-.SH
+-Optimization
+-.PP
+-There is a machine independent file,
+-.I optim.c ,
+-which contains a relatively short optimization routine,
+-.I optim .
+-Actually the word optimization is something of a misnomer;
+-the results are not optimum, only improved, and the
+-routine is in fact not optional; it must
+-be called for proper operation of the compiler.
+-.PP
+-.I Optim
+-is called after an expression tree is built, but
+-before the code generator is called.
+-The essential part of its job is to call
+-.I clocal
+-on the conversion operators.
+-On most machines, the treatment of
+-& is also essential:
+-by this time in the processing, the only node which
+-is a legal descendant of & is NAME.
+-(Possible descendants of * have been eliminated by
+-.I buildtree.)
+-The address of a static name is, almost by definition, a
+-constant, and can be represented by an ICON node on most machines
+-(provided that the loader has enough power).
+-Unfortunately, this is not universally true; on some machine, such as the IBM 370,
+-the issue of addressability rears its ugly head;
+-thus, before turning a NAME node into an ICON node,
+-the machine dependent function
+-.I andable
+-is called.
+-.PP
+-The optimization attempts of
+-.I optim
+-are currently quite limited.
+-It is primarily concerned with improving the behavior of
+-the compiler with operations one of whose arguments is a constant.
+-In the simplest case, the constant is placed on the right if the
+-operation is commutative.
+-The compiler also makes a limited search for expressions
+-such as
+-.DS
+-.I "( x + a ) + b"
+-.DE
+-where
+-.I a
+-and
+-.I b
+-are constants, and attempts to combine
+-.I a
+-and
+-.I b
+-at compile time.
+-A number of special cases are also examined;
+-additions of 0 and multiplications by 1 are removed,
+-although the correct processing of these cases to get
+-the type of the resulting tree correct is
+-decidedly nontrivial.
+-In some cases, the addition or multiplication must be replaced by
+-a conversion op to keep the types from becoming
+-fouled up.
+-Finally, in cases where a relational operation is being done,
+-and one operand is a constant, the operands are permuted, and the operator altered, if necessary,
+-to put the constant on the right.
+-Finally, multiplications by a power of 2 are changed to shifts.
+-.PP
+-There are dozens of similar optimizations that can be, and should be,
+-done.
+-It seems likely that this routine will be expanded in the relatively near future.
+-.SH
+-Machine Dependent Stuff
+-.PP
+-A number of the first pass machine dependent routines have been discussed above.
+-In general, the routines are short, and easy to adapt from
+-machine to machine.
+-The two exceptions to this general rule are
+-.I clocal
+-and
+-the function prolog and epilog generation routines,
+-.I bfcode
+-and
+-.I efcode .
+-.PP
+-.I Clocal
+-has the job of rewriting, if appropriate and desirable,
+-the nodes constructed by
+-.I buildtree .
+-There are two major areas where this
+-is important;
+-NAME nodes and conversion operations.
+-In the case of NAME nodes,
+-.I clocal
+-must rewrite the NAME node to reflect the
+-actual physical location of the name in the machine.
+-In effect, the NAME node must be examined, the symbol table
+-entry found (through the
+-.I rval
+-field of the node),
+-and, based on the storage class of the node,
+-the tree must be rewritten.
+-Automatic variables and parameters are typically
+-rewritten by treating the reference to the variable as
+-a structure reference, off the register which
+-holds the stack or argument pointer;
+-the
+-.I stref
+-routine is set up to be called in this way, and to
+-build the appropriate tree.
+-In the most general case, the tree consists
+-of a unary * node, whose descendant is
+-a + node, with the stack or argument register as left operand,
+-and a constant offset as right operand.
+-In the case of LABEL and internal static nodes, the
+-.I rval
+-field is rewritten to be the negative of the internal
+-label number; a negative
+-.I rval 
+-field is taken to be an internal label number.
+-Finally, a name of class REGISTER must be converted into a REG node,
+-and the
+-.I rval
+-field replaced by the register number.
+-In fact, this part of the
+-.I clocal
+-routine is nearly machine independent; only for machines
+-with addressability problems (IBM 370 again!) does it
+-have to be noticeably different,
+-.a
+-.PP
+-The conversion operator treatment is rather tricky.
+-It is necessary to handle the application of conversion operators
+-to constants in
+-.I clocal ,
+-in order that all constant expressions can have their values known
+-at compile time.
+-In extreme cases, this may mean that some simulation of the
+-arithmetic of the target machine might have to be done in a
+-cross-compiler.
+-In the most common case,
+-conversions from pointer to pointer do nothing.
+-For some machines, however, conversion from byte pointer to short or long
+-pointer might require a shift or rotate operation, which would
+-have to be generated here.
+-.PP
+-The extension of the portable compiler to machines where the size of a pointer
+-depends on its type would be straightforward, but has not yet been done.
+-.PP
+-The other major machine dependent issue involves the subroutine prolog and epilog
+-generation.
+-The hard part here is the design of the stack frame
+-and calling sequence; this design issue is discussed elsewhere.
+-.[
+-Johnson Lesk Ritchie calling sequence
+-.]
+-The routine
+-.I bfcode
+-is called with the number of arguments
+-the function is defined with, and
+-an array containing the symbol table indices of the
+-declared parameters.
+-.I Bfcode
+-must generate the code to establish the new stack frame,
+-save the return address and previous stack pointer
+-value on the stack, and save whatever
+-registers are to be used for register variables.
+-The stack size and the number of register variables is not
+-known when
+-.I bfcode
+-is called, so these numbers must be
+-referred to by assembler constants, which are
+-defined when they are known (usually in the second pass,
+-after all register variables, automatics, and temporaries have been seen).
+-The final job is to find those parameters which may have been declared
+-register, and generate the code to initialize
+-the register with the value passed on the stack.
+-Once again, for most machines, the general logic of
+-.I bfcode
+-remains the same, but the contents of the
+-.I printf
+-calls in it will change from machine to machine.
+-.I efcode
+-is rather simpler, having just to generate the default
+-return at the end of a function.
+-This may be nontrivial in the case of a function returning a structure or union, however.
+-.PP
+-There seems to be no really good place to discuss structures and unions, but
+-this is as good a place as any.
+-The C language now supports structure assignment,
+-and the passing of structures as arguments to functions,
+-and the receiving of structures back from functions.
+-This was added rather late to C, and thus to the portable compiler.
+-Consequently, it fits in less well than the older features.
+-Moreover, most of the burden of making these features work is
+-placed on the machine dependent code.
+-.PP
+-There are both conceptual and practical problems.
+-Conceptually, the compiler is structured around
+-the idea that to compute something, you put it into
+-a register and work on it.
+-This notion causes a bit of trouble on some machines (e.g., machines with 3-address opcodes), but
+-matches many machines quite well.
+-Unfortunately, this notion breaks down with structures.
+-The closest that one can come is to keep the addresses of the
+-structures in registers.
+-The actual code sequences used to move structures vary from the
+-trivial (a multiple byte move) to the horrible (a
+-function call), and are very machine dependent.
+-.PP
+-The practical problem is more painful.
+-When a function returning a structure is called, this function
+-has to have some place to put the structure value.
+-If it places it on the stack, it has difficulty popping its stack frame.
+-If it places the value in a static temporary, the routine fails to be
+-reentrant.
+-The most logically consistent way of implementing this is for the
+-caller to pass in a pointer to a spot where the called function
+-should put the value before returning.
+-This is relatively straightforward, although a bit tedious, to implement,
+-but means that the caller must have properly declared
+-the function type, even if the value is never used.
+-On some machines, such as the Interdata 8/32, the return value
+-simply overlays the argument region (which on the 8/32 is part
+-of the caller's stack frame).
+-The caller takes care of leaving enough room if the returned value is larger
+-than the arguments.
+-This also assumes that the caller know and declares the
+-function properly.
+-.PP
+-The PDP-11 and the VAX have stack hardware which is used in function calls and returns;
+-this makes it very inconvenient to
+-use either of the above mechanisms.
+-In these machines, a static area within the called functionis allocated, and
+-the function return value is copied into it on return; the function
+-returns the address of that region.
+-This is simple to implement, but is non-reentrant.
+-However, the function can now be called as a subroutine
+-without being properly declared, without the disaster which would otherwise ensue.
+-No matter what choice is taken, the convention is that the function
+-actually returns the address of the return structure value.
+-.PP
+-In building expression trees, the portable compiler takes a bit for granted about
+-structures.
+-It assumes that functions returning structures
+-actually return a pointer to the structure, and it assumes that
+-a reference to a structure is actually a reference to its address.
+-The structure assignment operator is rebuilt so that the left
+-operand is the structure being assigned to, but the
+-right operand is the address of the structure being assigned;
+-this makes it easier to deal with
+-.DS
+-.I "a = b = c"
+-.DE
+-and similar constructions.
+-.PP
+-There are four special tree nodes associated with these
+-operations:
+-STASG (structure assignment), STARG (structure argument
+-to a function call), and STCALL and UNARY STCALL
+-(calls of a function with nonzero and zero arguments, respectively).
+-These four nodes are unique in that the size and alignment information, which can be determined by
+-the type for all other objects in C, 
+-must be known to carry out these operations; special
+-fields are set aside in these nodes to contain
+-this information, and special
+-intermediate code is used to transmit this information.
+-.SH
+-First Pass Summary
+-.PP
+-There are may other issues which have been ignored here,
+-partly to justify the title ``tour'', and partially
+-because they have seemed to cause little trouble.
+-There are some debugging flags
+-which may be turned on, by giving the compiler's first pass
+-the argument
+-.DS
+-\-X[flags]
+-.DE
+-Some of the more interesting flags are
+-\-Xd for the defining and freeing of symbols,
+-\-Xi for initialization comments, and
+-\-Xb for various comments about the building of trees.
+-In many cases, repeating the flag more than once gives more information;
+-thus,
+-\-Xddd gives more information than \-Xd.
+-In the two pass version of the compiler, the
+-flags should not be set when the output is sent to the second
+-pass, since the debugging output and the intermediate code both go onto the standard
+-output.
+-.PP
+-We turn now to consideration of the second pass.
+//GO.SYSIN DD porttour1
+echo porttour2
+sed 's/.//' >porttour2 <<'//GO.SYSIN DD porttour2'
+-.SH
+-Pass Two
+-.PP
+-Code generation is far less well understood than
+-parsing or lexical analysis, and for this reason
+-the second pass is far harder to discuss in a file by file manner.
+-A great deal of the difficulty is in understanding the issues
+-and the strategies employed to meet them.
+-Any particular function is likely to be reasonably straightforward.
+-.PP
+-Thus, this part of the paper will concentrate a good deal on the broader
+-aspects of strategy in the code generator,
+-and will not get too intimate with the details.
+-.SH
+-Overview.
+-.PP
+-It is difficult to organize a code generator to be flexible enough to
+-generate code for a large number of machines,
+-and still be efficient for any one of them.
+-Flexibility is also important when it comes time to tune
+-the code generator to improve the output code quality.
+-On the other hand, too much flexibility can lead to semantically
+-incorrect code, and potentially a combinatorial explosion in the
+-number of cases to be considered in the compiler.
+-.PP
+-One goal of the code generator is to have a high degree of correctness.
+-It is very desirable to have the compiler detect its own inability to
+-generate correct code, rather than to produce incorrect code.
+-This goal is achieved by having a simple model of the job
+-to be done (e.g., an expression tree)
+-and a simple model of the machine state
+-(e.g., which registers are free).
+-The act of generating an instruction performs a transformation
+-on the tree and the machine state;
+-hopefully, the tree eventually gets
+-reduced to a single node.
+-If each of these instruction/transformation pairs is correct,
+-and if the machine state model really represents the actual machine,
+-and if the transformations reduce the input tree to the desired single node, then the
+-output code will be correct.
+-.PP
+-For most real machines, there is no definitive theory of code generation that
+-encompasses all the C operators.
+-Thus the selection of which instruction/transformations to generate, and in what
+-order, will have a heuristic flavor.
+-If, for some expression tree, no transformation applies, or, more
+-seriously, if the heuristics select a sequence of instruction/transformations
+-that do not in fact reduce the tree, the compiler
+-will report its inability to generate code, and abort.
+-.PP
+-A major part of the code generator is concerned with the model and the transformations,
+-\(em most of this is machine independent, or depends only on simple tables.
+-The flexibility comes from the heuristics that guide the transformations
+-of the trees, the selection of subgoals, and the ordering of the computation.
+-.SH
+-The Machine Model
+-.PP
+-The machine is assumed to have a number of registers, of at most two different
+-types:
+-.I A
+-and
+-.I B .
+-Within each register class, there may be scratch (temporary) registers and dedicated registers
+-(e.g., register variables, the stack pointer, etc.).
+-Requests to allocate and free registers involve only the temporary registers.
+-.PP
+-Each of the registers in the machine is given a name and a number
+-in the
+-.I mac2defs
+-file; the numbers are used as indices into various tables
+-that describe the registers, so they should be kept small.
+-One such table is the
+-.I rstatus
+-table on file
+-.I local2.c .
+-This table is indexed by register number, and
+-contains expressions made up from manifest constants describing the register types:
+-SAREG for dedicated AREG's, SAREG\(orSTAREG for scratch AREGS's,
+-and SBREG and SBREG\(orSTBREG similarly for BREG's.
+-There are macros that access this information:
+-.I isbreg(r)
+-returns true if register number
+-.I r
+-is a BREG, and
+-.I istreg(r)
+-returns true if register number
+-.I r
+-is a temporary AREG or BREG.
+-Another table,
+-.I rnames ,
+-contains the register names; this is used when
+-putting out assembler code and diagnostics.
+-.PP
+-The usage of registers is kept track of by an array called
+-.I busy .
+-.I Busy[r]
+-is the number of uses of register
+-.I r
+-in the current tree being processed.
+-The allocation and freeing of registers will be discussed later as part of the code generation
+-algorithm.
+-.SH
+-General Organization
+-.PP
+-As mentioned above, the second pass reads lines from
+-the intermediate file, copying through to the output unchanged
+-any lines that begin with a `)', and making note of the
+-information about stack usage and register allocation contained on
+-lines beginning with `]' and `['.
+-The expression trees, whose beginning is indicated by a line beginning with `.',
+-are read and rebuilt into trees.
+-If the compiler is loaded as one pass, the expression trees are
+-immediately available to the code generator.
+-.PP
+-The actual code generation is done by a hierarchy of routines.
+-The routine
+-.I delay
+-is first given the tree; it attempts to delay some postfix
+-++ and \-\- computations that might reasonably be done after the
+-smoke clears.
+-It also attempts to handle comma (,) operators by computing the
+-left side expression first, and then rewriting the tree
+-to eliminate the operator.
+-.I Delay
+-calls
+-.I codgen
+-to control the actual code generation process.
+-.I Codgen
+-takes as arguments a pointer to the expression tree,
+-and a second argument that, for socio-historical reasons, is called a
+-.I cookie .
+-The cookie describes a set of goals that would be acceptable
+-for the code generation: these are assigned to individual bits,
+-so they may be logically or'ed together to form a large number of possible goals.
+-Among the possible goals are FOREFF (compute for side effects only;
+-don't worry about the value), INTEMP (compute and store value into a temporary location
+-in memory), INAREG (compute into an A register), INTAREG (compute into a scratch
+-A register), INBREG and INTBREG similarly, FORCC (compute for condition codes),
+-and FORARG (compute it as a function argument; e.g., stack it if appropriate).
+-.PP
+-.I Codgen
+-first canonicalizes the tree by calling
+-.I canon .
+-This routine looks for certain transformations that might now be
+-applicable to the tree.
+-One, which is very common and very powerful, is to
+-fold together an indirection operator (UNARY MUL)
+-and a register (REG); in most machines, this combination is
+-addressable directly, and so is similar to a NAME in its
+-behavior.
+-The UNARY MUL and REG are folded together to make
+-another node type called OREG.
+-In fact, in many machines it is possible to directly address not just the
+-cell pointed to by a register, but also cells differing by a constant
+-offset from the cell pointed to by the register.
+-.I Canon
+-also looks for such cases, calling the
+-machine dependent routine 
+-.I notoff
+-to decide if the offset is acceptable (for example, in the IBM 370 the offset
+-must be between 0 and 4095 bytes).
+-Another optimization is to replace bit field operations
+-by shifts and masks if the operation involves extracting the field.
+-Finally, a machine dependent routine,
+-.I sucomp ,
+-is called that computes the Sethi-Ullman numbers
+-for the tree (see below).
+-.PP
+-After the tree is canonicalized,
+-.I codgen
+-calls the routine
+-.I store
+-whose job is to select a subtree of the tree to be computed
+-and (usually) stored before beginning the
+-computation of the full tree.
+-.I Store
+-must return a tree that can be computed without need
+-for any temporary storage locations.
+-In effect, the only store operations generated while processing the subtree must be as a response
+-to explicit assignment operators in the tree.
+-This division of the job marks one of the more significant, and successful,
+-departures from most other compilers.
+-It means that the code generator can operate
+-under the assumption that there are enough
+-registers to do its job, without worrying about
+-temporary storage.
+-If a store into a temporary appears in the output, it is always
+-as a direct result of logic in the
+-.I store
+-routine; this makes debugging easier.
+-.PP
+-One consequence of this organization is that
+-code is not generated by a treewalk.
+-There are theoretical results that support this decision.
+-.[
+-Aho Johnson Optimal Code Trees jacm
+-.]
+-It may be desirable to compute several subtrees and store
+-them before tackling the whole tree;
+-if a subtree is to be stored, this is known before the code
+-generation for the subtree is begun, and the subtree is computed
+-when all scratch registers are available.
+-.PP
+-The
+-.I store
+-routine decides what subtrees, if any, should be
+-stored by making use of numbers,
+-called
+-.I "Sethi-Ullman numbers" ,
+-that give, for each subtree of an expression tree,
+-the minimum number of scratch registers required to
+-compile the subtree, without any stores into temporaries.
+-.[
+-Sethi Ullman jacm 1970
+-.]
+-These numbers are computed by the machine-dependent
+-routine
+-.I sucomp ,
+-called by
+-.I canon .
+-The basic notion is that, knowing the Sethi-Ullman numbers for
+-the descendants of a node, and knowing the operator of the
+-node and some information about the machine, the
+-Sethi-Ullman number of the node itself can be computed.
+-If the Sethi-Ullman number for a tree exceeds the number of scratch
+-registers available, some subtree must be stored.
+-Unfortunately, the theory behind the Sethi-Ullman numbers
+-applies only to uselessly simple machines and operators.
+-For the rich set of C operators, and for machines with
+-asymmetric registers, register pairs, different kinds of registers,
+-and exceptional forms of addressing,
+-the theory cannot be applied directly.
+-The basic idea of estimation is a good one, however,
+-and well worth applying; the application, especially
+-when the compiler comes to be tuned for high code
+-quality, goes beyond the park of theory into the
+-swamp of heuristics.
+-This topic will be taken up again later, when more of the compiler
+-structure has been described.
+-.PP
+-After examining the Sethi-Ullman numbers,
+-.I store
+-selects a subtree, if any, to be stored, and returns the subtree and the associated cookie in
+-the external variables
+-.I stotree
+-and
+-.I stocook .
+-If a subtree has been selected, or if
+-the whole tree is ready to be processed, the
+-routine
+-.I order
+-is called, with a tree and cookie.
+-.I Order
+-generates code for trees that
+-do not require temporary locations.
+-.I Order
+-may make recursive calls on itself, and,
+-in some cases, on
+-.I codgen ;
+-for example, when processing the operators &&, \(or\(or, and comma (`,'), that have
+-a left to right evaluation, it is
+-incorrect for
+-.I store
+-examine the right operand for subtrees to be stored.
+-In these cases,
+-.I order
+-will call
+-.I codgen
+-recursively when it is permissible to work on the right operand.
+-A similar issue arises with the ? : operator.
+-.PP
+-The
+-.I order
+-routine works by matching the current tree with
+-a set of code templates.
+-If a template is discovered that will
+-match the current tree and cookie, the associated assembly language
+-statement or statements are generated.
+-The tree is then rewritten,
+-as specified by the template, to represent the effect of the output instruction(s).
+-If no template match is found, first an attempt is made to find a match with a
+-different cookie; for example, in order to compute
+-an expression with cookie INTEMP (store into a temporary storage location),
+-it is usually necessary to compute the expression into a scratch register
+-first.
+-If all attempts to match the tree fail, the heuristic part of
+-the algorithm becomes dominant.
+-Control is typically given to one of a number of machine-dependent routines
+-that may in turn recursively call
+-.I order
+-to achieve a subgoal of the computation (for example, one of the
+-arguments may be computed into a temporary register).
+-After this subgoal has been achieved, the process begins again with the
+-modified tree.
+-If the machine-dependent heuristics are unable to reduce the tree further,
+-a number of default rewriting rules may be considered appropriate.
+-For example, if the left operand of a + is a scratch
+-register, the + can be replaced by a += operator;
+-the tree may then match a template.
+-.PP
+-To close this introduction, we will discuss the steps in compiling
+-code for the expression
+-.DS
+-\fIa\fR += \fIb\fR
+-.DE
+-where
+-.I a
+-and
+-.I b
+-are static variables.
+-.PP
+-To begin with, the whole expression tree is examined with cookie FOREFF, and
+-no match is found.  Search with other cookies is equally fruitless, so an
+-attempt at rewriting is made.
+-Suppose we are dealing with the Interdata 8/32 for the moment.
+-It is recognized that the left hand and right hand sides of the += operator
+-are addressable, and in particular the left hand side has no
+-side effects, so it is permissible to rewrite this as
+-.DS
+-\fIa\fR = \fIa\fR + \fIb\fR
+-.DE
+-and this is done.
+-No match is found on this tree either, so a machine dependent rewrite is done; it is recognized
+-that the left hand side of the assignment is addressable, but the right hand side is not
+-in a register, so
+-.I order
+-is called recursively, being asked to put the right
+-hand side of the assignment into a register.
+-This invocation of
+-.I order
+-searches the tree for a match, and fails.
+-The machine dependent rule for +
+-notices that the right hand operand is addressable;
+-it decides to put the left operand into a scratch register.
+-Another recursive call to
+-.I order
+-is made, with the tree
+-consisting solely of the leaf
+-.I a ,
+-and the cookie asking that the value be placed into a scratch register.
+-This now matches a template, and a load instruction is emitted.
+-The node consisting of
+-.I a
+-is rewritten in place to represent the register into which
+-.I a
+-is loaded,
+-and this third call to
+-.I order
+-returns.
+-The second call to
+-.I order
+-now finds that it has the tree
+-.DS
+-\fBreg\fR + \fIb\fR
+-.DE
+-to consider.
+-Once again, there is no match, but the default rewriting rule rewrites
+-the + as a += operator, since the left operand is a scratch register.
+-When this is done, there is a match: in fact,
+-.DS
+-\fBreg\fR += \fIb\fR
+-.DE
+-simply describes the effect of the add instruction
+-on a typical machine.
+-After the add is emitted, the tree is rewritten
+-to consist merely of the register node, since the result of the add
+-is now in the register.
+-This agrees with the cookie passed to the second invocation of
+-.I order ,
+-so this invocation
+-terminates, returning to the first level.
+-The original tree has now
+-become
+-.DS
+-\fIa\fR = \fBreg\fR
+-.DE
+-which matches a template for the store instruction.
+-The store is output, and the tree rewritten to become
+-just a single register node.
+-At this point, since the top level call to
+-.I order
+-was
+-interested only in side effects, the call to
+-.I order
+-returns, and the code generation is completed;
+-we have generated a load, add, and store, as might have been expected.
+-.PP
+-The effect of machine architecture on this is considerable.
+-For example, on the Honeywell 6000, the machine dependent heuristics recognize that there is an ``add to storage''
+-instruction, so the strategy is quite different;
+-.I b
+-is loaded in to
+-a register, and then an add to storage instruction generated
+-to add this register in to
+-.I a .
+-The transformations, involving as they do the semantics of C,
+-are largely machine independent.
+-The decisions as to when to use them, however, are
+-almost totally machine dependent.
+-.PP
+-Having given a broad outline of
+-the code generation process, we shall next consider the
+-heart of it: the templates.
+-This leads naturally into discussions of template matching and register allocation,
+-and finally a discussion of the machine dependent interfaces and strategies.
+-.SH
+-The Templates
+-.PP
+-The templates describe the effect of the target machine instructions
+-on the model of computation around which the compiler is organized.
+-In effect, each template has five logical sections, and represents an assertion
+-of the form:
+-.IP
+-.B If
+-we have a subtree of a given shape (1), and we have a goal (cookie) or goals to
+-achieve (2), and we have sufficient free resources (3),
+-.B then
+-we may emit an instruction or instructions (4), and
+-rewrite the subtree in a particular manner (5),
+-and the rewritten tree will achieve the desired goals.
+-.PP
+-These five sections will be discussed in more
+-detail later.  First, we give an example of a
+-template:
+-.DS
+-.ta 1i 2i 3i 4i 5i
+-ASG PLUS,     INAREG,
+-      SAREG,  TINT,
+-      SNAME,  TINT,
+-              0,      RLEFT,
+-              "       add     AL,AR\en",
+-.DE
+-The top line specifies the operator (+=) and the cookie (compute the
+-value of the subtree into an AREG).
+-The second and third lines specify the left and right descendants,
+-respectively,
+-of the += operator.
+-The left descendant must be a REG node, representing an
+-A register, and have integer type, while the right side must be a NAME node,
+-and also have integer type.
+-The fourth line contains the resource requirements (no scratch registers
+-or temporaries needed), and the rewriting rule (replace the subtree by the left descendant).
+-Finally, the quoted string on the last line represents the output to the assembler:
+-lower case letters, tabs, spaces, etc. are copied
+-.I verbatim .
+-to the output; upper case letters trigger various macro-like expansions.
+-Thus,
+-.B AL
+-would expand into the \fBA\fRddress form of the \fBL\fReft operand \(em
+-presumably the register number.
+-Similarly,
+-.B AR
+-would expand into the name of the right operand.
+-The
+-.I add
+-instruction of the last section might well be
+-emitted by this template.
+-.PP
+-In principle, it would be possible to make separate templates
+-for all legal combinations of operators, cookies, types, and shapes.
+-In practice, the number of combinations is very large.
+-Thus, a considerable amount of mechanism is present to
+-permit a large number of subtrees to be matched
+-by a single template.
+-Most of the shape and type specifiers are individual bits, and can
+-be logically
+-or'ed
+-together.
+-There are a number of special descriptors for matching classes of
+-operators.
+-The cookies can also be combined.
+-As an example of the kind of template
+-that really arises in practice, the
+-actual template for the Interdata 8/32
+-that subsumes the above example is:
+-.DS
+-.ta 1i 2i 3i 4i 5i
+-ASG OPSIMP,   INAREG\(orFORCC,
+-      SAREG,  TINT\(orTUNSIGNED\(orTPOINT,
+-      SAREG\(orSNAME\(orSOREG\(orSCON,        TINT\(orTUNSIGNED\(orTPOINT,
+-              0,      RLEFT\(orRESCC,
+-              "       OI      AL,AR\en",
+-.DE
+-Here, OPSIMP represents the operators
+-+, \-, \(or, &, and ^.
+-The
+-.B OI
+-macro in the output string expands into the
+-appropriate \fBI\fRnteger \fBO\fRpcode for the operator.
+-The left and right sides can be integers, unsigned, or pointer types.
+-The right side can be, in addition to a name, a register,
+-a memory location whose address is given by a register and displacement (OREG),
+-or a constant.
+-Finally, these instructions set the condition codes,
+-and so can be used in condition contexts:
+-the cookie and rewriting rules reflect this.
+-.SH
+-The Template Matching Algorithm.
+-.PP
+-The heart of the second pass is the template matching
+-algorithm, in the routine
+-.I match .
+-.I Match
+-is called with a tree and a cookie; it attempts to match
+-the given tree against some template that will transform it
+-according to one of the goals given in the cookie.
+-If a match is successful, the transformation is
+-applied;
+-.I expand
+-is called to generate the assembly code, and then
+-.I reclaim
+-rewrites the tree, and reclaims the resources, such
+-as registers, that might have become free as a result
+-of the generated code.
+-.PP
+-This part of the compiler is among the most time critical.
+-There is a spectrum of implementation techniques available
+-for doing this matching.
+-The most naive algorithm simply looks at the templates one by one.
+-This can be considerably improved upon by restricting the search
+-for an acceptable template.
+-It would be possible to do better than this if the templates were given
+-to a separate program that ate them and generated a template
+-matching subroutine.
+-This would make maintenance of the compiler much more
+-complicated, however, so this has not been done.
+-.PP
+-The matching algorithm is actually carried out by restricting
+-the range in the table that must be searched for each opcode.
+-This introduces a number of complications, however, and needs a
+-bit of sympathetic help by the person constructing the
+-compiler in order to obtain best results.
+-The exact tuning of this algorithm continues; it
+-is best to consult the code and comments in
+-.I match
+-for the latest version.
+-.PP
+-In order to match a template to a tree,
+-it is necessary to match not only the cookie and the
+-op of the root, but also the types and shapes of the
+-left and right descendants (if any) of the tree.
+-A convention is established here that is carried out throughout
+-the second pass of the compiler.
+-If a node represents a unary operator, the single descendant
+-is always the ``left'' descendant.
+-If a node represents a unary operator or a leaf node (no descendants)
+-the ``right'' descendant is taken by convention to be the node itself.
+-This enables templates to easily match leaves and conversion operators, for example,
+-without any additional mechanism in the matching program.
+-.PP
+-The type matching is straightforward; it is possible to specify any combination
+-of basic types, general pointers, and pointers to one or more of
+-the basic types.
+-The shape matching is somewhat more complicated, but still pretty simple.
+-Templates have a collection of possible operand shapes
+-on which the opcode might match.
+-In the simplest case, an
+-.I add
+-operation might be able to add to either a register variable
+-or a scratch register, and might be able (with appropriate
+-help from the assembler) to add an integer constant (ICON), a static
+-memory cell (NAME), or a stack location (OREG).
+-.PP
+-It is usually attractive to specify a number of such shapes,
+-and distinguish between them when the assembler output is produced.
+-It is possible to describe the union of many elementary
+-shapes such as ICON, NAME, OREG,
+-AREG or BREG
+-(both scratch and register forms), etc.
+-To handle at least the simple forms of indirection, one can also
+-match some more complicated forms of trees; STARNM and STARREG
+-can match more complicated trees headed by an indirection operator,
+-and SFLD can match certain trees headed by a FLD operator: these
+-patterns call machine dependent routines that match the
+-patterns of interest on a given machine.
+-The shape SWADD may be used to recognize NAME or OREG
+-nodes that lie on word boundaries: this may be of some importance
+-on word\-addressed machines.
+-Finally, there are some special shapes: these may not
+-be used in conjunction with the other shapes, but may be
+-defined and extended in machine dependent ways.
+-The special shapes SZERO, SONE, and SMONE are predefined and match
+-constants 0, 1, and \-1, respectively; others are easy to add
+-and match by using the machine dependent routine
+-.I special .
+-.PP
+-When a template has been found that matches the root of the tree,
+-the cookie, and the shapes and types of the descendants,
+-there is still one bar to a total match: the template may
+-call for some resources (for example, a scratch register).
+-The routine
+-.I allo
+-is called, and it attempts to allocate the resources.
+-If it cannot, the match fails; no resources are
+-allocated.
+-If successful, the allocated resources are given numbers
+-1, 2, etc. for later reference when the assembly code is
+-generated.
+-The routines
+-.I expand
+-and
+-.I reclaim
+-are then called.
+-The
+-.I match
+-routine then returns a special value, MDONE.
+-If no match was found, the value MNOPE is returned;
+-this is a signal to the caller to try more cookie
+-values, or attempt a rewriting rule.
+-.I Match
+-is also used to select rewriting rules, although
+-the way of doing this is pretty straightforward.
+-A special cookie, FORREW, is used to ask
+-.I match
+-to search for a rewriting rule.
+-The rewriting rules are keyed to various opcodes; most
+-are carried out in
+-.I order .
+-Since the question of when to rewrite is one of the key issues in
+-code generation, it will be taken up again later.
+-.SH
+-Register Allocation.
+-.PP
+-The register allocation routines, and the allocation strategy,
+-play a central role in the correctness of the code generation algorithm.
+-If there are bugs in the Sethi-Ullman computation that cause the
+-number of needed registers to be underestimated,
+-the compiler may run out of scratch registers;
+-it is essential that the allocator keep track of those registers that
+-are free and busy, in order to detect such conditions.
+-.PP
+-Allocation of registers takes place as the result of a template
+-match; the routine
+-.I allo
+-is called with a word describing the number of A registers,
+-B registers, and temporary locations needed.
+-The allocation of temporary locations on the stack is relatively
+-straightforward, and will not be further covered; the
+-bookkeeping is a bit tricky, but conceptually trivial, and requests
+-for temporary space on the stack will never fail.
+-.PP
+-Register allocation is less straightforward.
+-The two major complications are
+-.I pairing
+-and
+-.I sharing .
+-In many machines, some operations (such as multiplication
+-and division), and/or some types (such as longs or double precision)
+-require even/odd pairs of registers.
+-Operations of the first type are exceptionally difficult to
+-deal with in the compiler; in fact, their theoretical
+-properties are rather bad as well.
+-.[
+-Aho Johnson Ullman Multiregister
+-.]
+-The second issue is dealt with rather more successfully;
+-a machine dependent function called
+-.I szty(t)
+-is called that returns 1 or 2, depending on the
+-number of A registers required to hold an object of type
+-.I t .
+-If
+-.I szty
+-returns 2, an even/odd pair of A registers is allocated
+-for each request.
+-.PP
+-The other issue, sharing, is more subtle, but
+-important for good code quality.
+-When registers are allocated, it
+-is possible to reuse registers that hold address
+-information, and use them to contain the values
+-computed or accessed.
+-For example, on the IBM 360, if register 2 has
+-a pointer to an integer in it, we may load the
+-integer into register 2 itself by saying:
+-.DS
+-L     2,0(2)
+-.DE
+-If register 2 had a byte pointer, however, the sequence for
+-loading a character involves clearing the target
+-register first, and then inserting the desired character:
+-.DS
+-SR    3,3
+-IC    3,0(2)
+-.DE
+-In the first case, if register 3 were used as the target,
+-it would lead to a larger number of registers
+-used for the expression than were required; the compiler would
+-generate inefficient code.
+-On the other hand, if register 2 were used as the target in the second
+-case, the code would simply be wrong.
+-In the first case, register 2 can be 
+-.I shared
+-while in the second, it cannot.
+-.PP
+-In the specification of the register needs in the templates,
+-it is possible to indicate whether required scratch registers
+-may be shared with possible registers on the left or the right of the input tree.
+-In order that a register be shared, it must be scratch, and it must
+-be used only once, on the appropriate side of the tree being compiled.
+-.PP
+-The
+-.I allo
+-routine thus has a bit more to do than meets the eye;
+-it calls
+-.I freereg
+-to obtain a free register for each A and B register request.
+-.I Freereg
+-makes multiple calls on the routine
+-.I usable
+-to decide if a given register can be used to satisfy
+-a given need.
+-.I Usable
+-calls
+-.I shareit
+-if the register is busy, but might be shared.
+-Finally,
+-.I shareit
+-calls
+-.I ushare
+-to decide if the desired register is actually in the appropriate
+-subtree, and can be shared.
+-.PP
+-Just to add additional complexity, on some machines (such as the IBM 370) it
+-is possible to have ``double indexing'' forms of
+-addressing; these are represented by OREGS's
+-with the base and index registers encoded into the register field.
+-While the register allocation and deallocation
+-.I "per se"
+-is not made more difficult by this phenomenon, the code itself
+-is somewhat more complex.
+-.PP
+-Having allocated the registers and expanded the assembly language,
+-it is time to reclaim the resources; the routine
+-.I reclaim
+-does this.
+-Many operations produce more than one result.
+-For example, many arithmetic operations may produce
+-a value in a register, and also set the condition
+-codes.
+-Assignment operations may leave results both in a register and in memory.
+-.I Reclaim
+-is passed three parameters; the tree and cookie
+-that were matched, and the rewriting field of the template.
+-The rewriting field allows the specification of possible results;
+-the tree is rewritten to reflect the results of the operation.
+-If the tree was computed for side effects only (FOREFF),
+-the tree is freed, and all resources in it reclaimed.
+-If the tree was computed for condition codes, the resources
+-are also freed, and the tree replaced by a special
+-node type, FORCC.
+-Otherwise, the value may be found in the left
+-argument of the root, the right argument of the root,
+-or one of the temporary resources allocated.
+-In these cases, first the resources of the tree,
+-and the newly allocated resources,
+-are
+-freed; then the resources needed by the result
+-are made busy again.
+-The final result must always match the shape of the input cookie;
+-otherwise, the compiler error
+-``cannot reclaim''
+-is generated.
+-There are some machine dependent ways of
+-preferring results in registers or memory when
+-there are multiple results matching multiple goals in the cookie.
+-.SH
+-The Machine Dependent Interface
+-.PP
+-The files
+-.I order.c ,
+-.I local2.c ,
+-and
+-.I table.c ,
+-as well as the header file
+-.I mac2defs ,
+-represent the machine dependent portion of the second pass.
+-The machine dependent portion can be roughly divided into
+-two: the easy portion and the hard portion.
+-The easy portion
+-tells the compiler the names of the registers, and arranges that
+-the compiler generate the proper assembler formats, opcode names, location counters, etc.
+-The hard portion involves the Sethi\-Ullman computation, the
+-rewriting rules, and, to some extent, the templates.
+-It is hard because there are no real algorithms that apply;
+-most of this portion is based on heuristics.
+-This section discusses the easy portion; the next several
+-sections will discuss the hard portion.
+-.PP
+-If the compiler is adapted from a compiler for a machine
+-of similar architecture, the easy part is indeed easy.
+-In
+-.I mac2defs ,
+-the register numbers are defined, as well as various parameters for
+-the stack frame, and various macros that describe the machine architecture.
+-If double indexing is to be permitted, for example, the symbol
+-R2REGS is defined.
+-Also, a number of macros that are involved in function call processing,
+-especially for unusual function call mechanisms, are defined here.
+-.PP
+-In
+-.I local2.c ,
+-a large number of simple functions are defined.
+-These do things such as write out opcodes, register names,
+-and address forms for the assembler.
+-Part of the function call code is defined here; that is nontrivial
+-to design, but typically rather straightforward to implement.
+-Among the easy routines in
+-.I order.c
+-are routines for generating a created label,
+-defining a label, and generating the arguments
+-of a function call.
+-.PP
+-These routines tend to have a local effect, and depend on a fairly straightforward way
+-on the target assembler and the design decisions already made about
+-the compiler.
+-Thus they will not be further treated here.
+-.SH
+-The Rewriting Rules
+-.PP
+-When a tree fails to match any template, it becomes
+-a candidate for rewriting.
+-Before the tree is rewritten,
+-the machine dependent routine
+-.I nextcook
+-is called with the tree and the cookie; it suggests
+-another cookie that might be a better candidate for the
+-matching of the tree.
+-If all else fails, the templates are searched with the cookie
+-FORREW, to look for a rewriting rule.
+-The rewriting rules are of two kinds;
+-for most of the common operators, there are
+-machine dependent rewriting rules that may be applied;
+-these are handled by machine dependent functions
+-that are called and given the tree to be computed.
+-These routines may recursively call
+-.I order
+-or
+-.I codgen
+-to cause certain subgoals to be achieved;
+-if they actually call for some alteration of the tree,
+-they return 1, and the
+-code generation algorithm recanonicalizes and tries again.
+-If these routines choose not to deal with the tree, the
+-default rewriting rules are applied.
+-.PP
+-The assignment ops, when rewritten, call the routine
+-.I setasg .
+-This is assumed to rewrite the tree at least to the point where there are
+-no side effects in the left hand side.
+-If there is still no template match,
+-a default rewriting is done that causes
+-an expression such as
+-.DS
+-.I "a += b"
+-.DE
+-to be rewritten as
+-.DS
+-.I "a = a + b"
+-.DE
+-This is a useful default for certain mixtures of strange types
+-(for example, when
+-.I a
+-is a bit field and
+-.I b
+-an character) that
+-otherwise might need separate table entries.
+-.PP
+-Simple assignment, structure assignment, and all forms of calls
+-are handled completely by the machine dependent routines.
+-For historical reasons, the routines generating the calls return
+-1 on failure, 0 on success, unlike the other routines.
+-.PP
+-The machine dependent routine
+-.I setbin
+-handles binary operators; it too must do most of the job.
+-In particular, when it returns 0, it must do so with
+-the left hand side in a temporary register.
+-The default rewriting rule in this case is to convert the
+-binary operator into the associated assignment operator;
+-since the left hand side is assumed to be a temporary register,
+-this preserves the semantics and often allows a considerable
+-saving in the template table.
+-.PP
+-The increment and decrement operators may be dealt with with
+-the machine dependent routine
+-.I setincr .
+-If this routine chooses not to deal with the tree, the rewriting rule replaces
+-.DS
+-.I "x ++"
+-.DE
+-by
+-.DS
+-.I "( (x += 1) \- 1)"
+-.DE
+-which preserves the semantics.
+-Once again, this is not too attractive for the most common
+-cases, but can generate close to optimal code when the
+-type of x is unusual.
+-.PP
+-Finally, the indirection (UNARY MUL) operator is also handled
+-in a special way.
+-The machine dependent routine
+-.I offstar
+-is extremely important for the efficient generation of code.
+-.I Offstar
+-is called with a tree that is the direct descendant of a UNARY MUL node;
+-its job is to transform this tree so that the combination of
+-UNARY MUL with the transformed tree becomes addressable.
+-On most machines,
+-.I offstar
+-can simply compute the tree into an A or B register,
+-depending on the architecture, and then
+-.I canon
+-will make the resulting tree into an OREG.
+-On many machines,
+-.I offstar
+-can profitably choose to do less work than computing
+-its entire argument into a register.
+-For example, if the target machine supports OREGS
+-with a constant offset from a register, and
+-.I offstar
+-is called
+-with a tree of the form
+-.DS
+-.I "expr + const"
+-.DE
+-where
+-.I const
+-is a constant, then
+-.I offstar
+-need only compute
+-.I expr
+-into the appropriate form of register.
+-On machines that support double indexing,
+-.I offstar
+-may have even more choice as to how to proceed.
+-The proper tuning of
+-.I offstar ,
+-which is not typically too difficult, should be one of the
+-first tries at optimization attempted by the
+-compiler writer.
+-.SH
+-The Sethi-Ullman Computation
+-.PP
+-The heart of the heuristics is the computation of the Sethi-Ullman numbers.
+-This computation is closely linked with the rewriting rules and the
+-templates.
+-As mentioned before, the Sethi-Ullman numbers are expected to
+-estimate the number of scratch registers needed to compute
+-the subtrees without using any stores.
+-However, the original theory does not apply to real machines.
+-For one thing, the theory assumes that all registers
+-are interchangeable.
+-Real machines have general purpose, floating point, and index registers,
+-register pairs, etc.
+-The theory also does not account for side effects;
+-this rules out various forms of pathology that arise
+-from assignment and assignment ops.
+-Condition codes are also undreamed of.
+-Finally, the influence of types, conversions, and the
+-various addressability restrictions and extensions of real
+-machines are also ignored.
+-.PP
+-Nevertheless, for a ``useless'' theory,
+-the basic insight of Sethi and Ullman is amazingly
+-useful in a real compiler.
+-The notion that one should attempt to estimate the
+-resource needs of trees before starting the
+-code generation provides a natural means of splitting the
+-code generation problem, and provides a bit of redundancy
+-and self checking in the compiler.
+-Moreover, if writing the
+-Sethi-Ullman routines is hard, describing, writing, and debugging the
+-alternative (routines that attempt to free up registers by stores into
+-temporaries ``on the fly'') is even worse.
+-Nevertheless, it should be clearly understood that these routines exist in a realm
+-where there is no ``right'' way to write them;
+-it is an art, the realm of heuristics, and, consequently, a major
+-source of bugs in the compiler.
+-Often, the early, crude versions of these routines give little trouble;
+-only after
+-the compiler is actually working
+-and the
+-code quality is being improved do serious problem have to be faced.
+-Having a simple, regular machine architecture is worth quite
+-a lot at this time.
+-.PP
+-The major problems arise from asymmetries in the registers: register pairs,
+-having different kinds of registers, and the related problem of
+-needing more than one register (frequently a pair) to store certain
+-data
+-types (such as longs or doubles).
+-There appears to be no general way of treating this problem;
+-solutions have to be fudged for each machine where the problem arises.
+-On the Honeywell 66, for example, there are only two general purpose registers,
+-so a need for a pair is the same as the need for two registers.
+-On the IBM 370, the register pair (0,1) is used to do multiplications and divisions;
+-registers 0 and 1 are not generally considered part of the scratch registers, and so
+-do not require allocation explicitly.
+-On the Interdata 8/32, after much consideration, the
+-decision was made not to try to deal with the register pair issue;
+-operations such as multiplication and division that required pairs
+-were simply assumed to take all of the scratch registers.
+-Several weeks of effort had failed to produce
+-an algorithm that seemed to have much chance of running successfully
+-without inordinate debugging effort.
+-The difficulty of this issue should not be minimized; it represents one of the
+-main intellectual efforts in porting the compiler.
+-Nevertheless, this problem has been fudged with a degree of
+-success on nearly a dozen machines, so the compiler writer should
+-not abandon hope.
+-.PP
+-The Sethi-Ullman computations interact with the
+-rest of the compiler in a number of rather subtle ways.
+-As already discussed, the
+-.I store
+-routine uses the Sethi-Ullman numbers to decide which subtrees are too difficult
+-to compute in registers, and must be stored.
+-There are also subtle interactions between the
+-rewriting routines and the Sethi-Ullman numbers.
+-Suppose we have a tree such as
+-.DS
+-.I "A \- B"
+-.DE
+-where
+-.I A
+-and
+-.I B
+-are expressions; suppose further that
+-.I B
+-takes two registers, and
+-.I A
+-one.
+-It is possible to compute the full expression in two registers by
+-first computing
+-.I B ,
+-and then, using the scratch register
+-used by
+-.I B ,
+-but not containing the answer, compute
+-.I A .
+-The subtraction can then be done, computing the expression.
+-(Note that this assumes a number of things, not the least of which
+-are register-to-register subtraction operators and symmetric
+-registers.)
+-If the machine dependent routine
+-.I setbin ,
+-however, is not prepared to recognize this case
+-and compute the more difficult side of the expression
+-first, the
+-Sethi-Ullman number must be set to three.
+-Thus, the
+-Sethi-Ullman number for a tree should represent the code that
+-the machine dependent routines are actually willing to generate.
+-.PP
+-The interaction can go the other way.
+-If we take an expression such as
+-.DS
+-.I "* ( p + i )"
+-.DE
+-where
+-.I p
+-is a pointer and
+-.I i
+-an integer,
+-this can probably be done in one register on most machines.
+-Thus, its Sethi-Ullman number would probably be set to one.
+-If double indexing is possible in the machine, a possible way
+-of computing the expression is to load both
+-.I p
+-and
+-.I i
+-into registers, and then use double indexing.
+-This would use two scratch registers; in such a case,
+-it is possible that the scratch registers might be unobtainable,
+-or might make some other part of the computation run out of
+-registers.
+-The usual solution is to cause
+-.I offstar
+-to ignore opportunities for double indexing that would tie up more scratch
+-registers than the Sethi-Ullman number had reserved.
+-.PP
+-In summary, the Sethi-Ullman computation represents much of the craftsmanship and artistry in any application
+-of the portable compiler.
+-It is also a frequent source of bugs.
+-Algorithms are available that will produce nearly optimal code
+-for specialized machines, but unfortunately most existing machines
+-are far removed from these ideals.
+-The best way of proceeding in practice is to start with a compiler
+-for a similar machine to the target, and proceed very
+-carefully.
+-.SH
+-Register Allocation
+-.PP
+-After the Sethi-Ullman numbers are computed,
+-.I order
+-calls a routine,
+-.I rallo ,
+-that does register allocation, if appropriate.
+-This routine does relatively little, in general;
+-this is especially true if the target machine
+-is fairly regular.
+-There are a few cases where it is assumed that
+-the result of a computation takes place in a particular register;
+-switch and function return are the two major places.
+-The expression tree has a field,
+-.I rall ,
+-that may be filled with a register number; this is taken
+-to be a preferred register, and the first temporary
+-register allocated by a template match will be this preferred one, if
+-it is free.
+-If not, no particular action is taken; this is just a heuristic.
+-If no register preference is present, the field contains NOPREF.
+-In some cases, the result must be placed in
+-a given register, no matter what.
+-The register number is placed in
+-.I rall ,
+-and the mask MUSTDO is logically or'ed in with it.
+-In this case, if the subtree is requested in a register, and comes
+-back in a register other than the demanded one, it is moved
+-by calling the routine
+-.I rmove .
+-If the target register for this move is busy, it is a compiler
+-error.
+-.PP
+-Note that this mechanism is the only one that will ever cause a register-to-register
+-move between scratch registers (unless such a move is buried in the depths of
+-some template).
+-This simplifies debugging.
+-In some cases, there is a rather strange interaction between
+-the register allocation and the Sethi-Ullman number;
+-if there is an operator or situation requiring a
+-particular register, the allocator and the Sethi-Ullman
+-computation must conspire to ensure that the target
+-register is not being used by some intermediate result of some far-removed computation.
+-This is most easily done by making the special operation take
+-all of the free registers, preventing any other partially-computed
+-results from cluttering up the works.
+-.SH
+-Compiler Bugs
+-.PP
+-The portable compiler has an excellent record of generating correct code.
+-The requirement for reasonable cooperation between the register allocation,
+-Sethi-Ullman computation, rewriting rules, and templates builds quite a bit
+-of redundancy into the compiling process.
+-The effect of this is that, in a surprisingly short time, the compiler will
+-start generating correct code for those
+-programs that it can compile.
+-The hard part of the job then becomes finding and
+-eliminating those situations where the compiler refuses to
+-compile a program because it knows it cannot do it right.
+-For example, a template may simply be missing; this may either
+-give a compiler error of the form ``no match for op ...'' , or cause
+-the compiler to go into an infinite loop applying various rewriting rules.
+-The compiler has a variable,
+-.I nrecur ,
+-that is set to 0 at the beginning of an expressions, and
+-incremented at key spots in the
+-compilation process; if this parameter gets too large, the
+-compiler decides that it is in a loop, and aborts.
+-Loops are also characteristic of botches in the machine-dependent rewriting rules.
+-Bad Sethi-Ullman computations usually cause the scratch registers
+-to run out; this often means
+-that the Sethi-Ullman number was underestimated, so
+-.I store
+-did not store something it should have; alternatively,
+-it can mean that the rewriting rules were not smart enough to
+-find the sequence that
+-.I sucomp
+-assumed would be used.
+-.PP
+-The best approach when a compiler error is detected involves several stages.
+-First, try to get a small example program that steps on the bug.
+-Second, turn on various debugging flags in the code generator, and follow the
+-tree through the process of being matched and rewritten.
+-Some flags of interest are
+-\-e, which prints the expression tree,
+-\-r, which gives information about the allocation of registers,
+-\-a, which gives information about the performance of
+-.I rallo ,
+-and \-o, which gives information about the behavior of
+-.I order .
+-This technique should allow most bugs to be found relatively quickly.
+-.PP
+-Unfortunately, finding the bug is usually not enough; it must also
+-be fixed!
+-The difficulty arises because a fix to the particular bug of interest tends
+-to break other code that already works.
+-Regression tests, tests that compare the performance of
+-a new compiler against the performance of an older one, are very
+-valuable in preventing major catastrophes.
+-.SH
+-Summary and Conclusion
+-.PP
+-The portable compiler has been a useful tool for providing C
+-capability on a large number of diverse machines,
+-and for testing a number of theoretical
+-constructs in a practical setting.
+-It has many blemishes, both in style and functionality.
+-It has been applied to many more machines than first
+-anticipated, of a much wider range than originally dreamed of.
+-Its use has also spread much faster than expected, leaving parts of
+-the compiler still somewhat raw in shape.
+-.PP
+-On the theoretical side, there is some hope that the
+-skeleton of the
+-.I sucomp
+-routine could be generated for many machines directly from the
+-templates; this would give a considerable boost
+-to the portability and correctness of the compiler,
+-but might affect tunability and code quality.
+-There is also room for more optimization, both within
+-.I optim
+-and in the form of a portable ``peephole'' optimizer.
+-.PP
+-On the practical, development side,
+-the compiler could probably be sped up and made smaller
+-without doing too much violence to its basic structure.
+-Parts of the compiler deserve to be rewritten;
+-the initialization code, register allocation, and
+-parser are prime candidates.
+-It might be that doing some or all of the parsing
+-with a recursive descent parser might
+-save enough space and time to be worthwhile;
+-it would certainly ease the problem of moving the
+-compiler to an environment where
+-.I Yacc
+-is not already present.
+-.PP
+-Finally, I would like to thank the many people who have
+-sympathetically, and even enthusiastically, helped me grapple
+-with what has been a frustrating program to write, test, and install.
+-D. M. Ritchie and E. N. Pinson provided needed early
+-encouragement and philosophical guidance;
+-M. E. Lesk,
+-R. Muha, T. G. Peterson,
+-G. Riddle, L. Rosler,
+-R. W. Mitze,
+-B. R. Rowland,
+-S. I. Feldman,
+-and
+-T. B. London
+-have all contributed ideas, gripes, and all, at one time or another,
+-climbed ``into the pits'' with me to help debug.
+-Without their help this effort would have not been possible;
+-with it, it was often kind of fun.
+-.sp 100
+-.LP
+-.[
+-$LIST$
+-.]
+-.LP
+-.sp 100
+-.LP
+//GO.SYSIN DD porttour2
diff --git a/doc/7thEdMan/vol2/ratfor.bun b/doc/7thEdMan/vol2/ratfor.bun
new file mode 100644 (file)
index 0000000..e806975
--- /dev/null
@@ -0,0 +1,2205 @@
+# To unbundle, run this file
+echo m.mac
+sed 's/.//' >m.mac <<'//GO.SYSIN DD m.mac'
+-.tr ~
+-.tr _\(em
+-.ND
+-.if n .ls 2
+-.de UL
+-.if t \&\\$3\f3\\$1\fP\\$2\&
+-.if n \&\\$3\f2\\$1\fP\\$2\&
+-..
+-.de IT
+-.if n .ul
+-\\$3\f2\\$1\fP\\$2
+-..
+-.de UI
+-\f3\\$1\fI\\$2\fR\\$3
+-..
+-.de P1
+-.if \\n(.$ .DS I \\$1
+-.if !\\n(.$ .DS I 5
+-.if n .ls 1
+-.nf
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ta .4i .8i 1.2i 1.6i 2i 2.4i 2.8i 3.2i 3.6i 4i
+-.if t .tr -\(mi|\(bv'\(fm^\(no
+-.if t .tr _\(ru
+-.lg 0
+-.             use first argument as indent if present
+-..
+-.de P2
+-.ft R
+-.if n .ls 2
+-.tr --||''^^!!_\(em
+-.lg
+-.DE
+-..
+-.hw semi-colon
+-.if t .ds m \(mi
+-.if n .ds m -
+-.if t .ds n \(no
+-.if n .ds n -
+-.if t .ds S \(sl
+-.if n .ds S /
+-.if t .ds d \s+4\&.\&\s-4
+-.if n .ds d \&.\&
+-.if t .ds a \z@@
+-.if n .ds a @
+-.hy 14
+-.     2=not last lines; 4= no -xx; 8=no xx-
+-.ds m \(mi
+-.tr *\(**
+-.de WS
+-.sp
+-..
+-.de UC
+-\&\\$3\s-2\\$1\s0\\$2\&
+-..
+//GO.SYSIN DD m.mac
+echo m0
+sed 's/.//' >m0 <<'//GO.SYSIN DD m0'
+-.....ND "January 1, 1977"
+-.RP
+-....TR 55
+-.....TM 76-1273-10 39199 39199-11
+-.TL
+-RATFOR \(em A Preprocessor for a Rational Fortran
+-.AU "MH 2C-518" 6021
+-Brian W. Kernighan
+-.AI
+-.MH
+-.OK
+-structured programming, control flow, programming
+-.AB
+-.ps 9
+-.nr PS 9
+-.vs 11
+-.nr VS 11
+-.in 0
+-.ll
+-.PP
+-Although Fortran is not a pleasant
+-language to use,
+-it does have the advantages of universality
+-and (usually) relative efficiency.
+-The
+-Ratfor 
+-language attempts to conceal
+-the main deficiencies of Fortran
+-while retaining its desirable qualities,
+-by providing
+-decent control flow statements:
+-.IP "\ \ \ \(bu"
+-statement grouping
+-.IP "\ \ \ \(bu"
+-.UL if-else
+-and
+-.UL switch
+-for decision-making
+-.IP "\ \ \ \(bu"
+-.UL while ,
+-.UL for ,
+-.UL do ,
+-and
+-.UL repeat-until
+-for looping
+-.IP "\ \ \ \(bu"
+-.UL break
+-and
+-.UL next
+-for controlling loop exits
+-.LP
+-and some ``syntactic sugar'':
+-.IP "\ \ \ \(bu"
+-free form input (multiple statements/line, automatic continuation)
+-.IP "\ \ \ \(bu"
+-unobtrusive comment convention
+-.IP "\ \ \ \(bu"
+-translation of >, >=, etc., into .GT., .GE., etc.
+-.IP "\ \ \ \(bu"
+-.UL return (expression)
+-statement for functions
+-.IP "\ \ \ \(bu"
+-.UL define
+-statement for symbolic parameters
+-.IP "\ \ \ \(bu"
+-.UL include
+-statement for including source files
+-.LP
+-Ratfor
+-is implemented as a
+-preprocessor which translates this language
+-into Fortran.
+-.PP
+-Once the control flow and cosmetic deficiencies of Fortran
+-are hidden,
+-the resulting language is remarkably pleasant to use.
+-Ratfor 
+-programs are
+-markedly easier to write, and to read,
+-and thus easier to debug, maintain and modify
+-than their Fortran equivalents.
+-.PP
+-It is readily possible to write 
+-Ratfor 
+-programs which are portable to other env ironments.
+-Ratfor
+-is written in itself
+-in this way,
+-so it is also portable;
+-versions of 
+-Ratfor 
+-are now running on at least two dozen different types of computers
+-at over five hundred locations.
+-.PP
+-This paper discusses design criteria
+-for a Fortran preprocessor,
+-the 
+-Ratfor
+-language
+-and its implementation,
+-and user experience.
+-.AE
+-.FS
+-This paper is a revised and expanded version of oe published in
+-.ul
+-Software\(emPractice and Experience,
+-October 1975.
+-The Ratfor described here is the one in use on
+-.UC UNIX
+-and
+-.UC GCOS
+-at Bell Laboratories, Murray Hill, N. J.
+-.FE
+-.CS 12 1 13 0 0 10
+//GO.SYSIN DD m0
+echo m1
+sed 's/.//' >m1 <<'//GO.SYSIN DD m1'
+-.nr PS 9
+-.nr VS 11
+-.if t .2C
+-.if n .ls 2
+-.NH
+-INTRODUCTION
+-.PP
+-Most programmers will agree that Fortran is
+-an unpleasant language to program in,
+-yet there are many occasions when they are forced to use it.
+-For example, Fortran is often the only language
+-thoroughly supported on the local computer.
+-Indeed, it is the closest thing to a universal programming language
+-currently available:
+-with care it is possible to write large, truly portable
+-Fortran programs[1].
+-Finally, Fortran is often the most ``efficient'' language
+-available, particularly for programs requiring much computation.
+-.PP
+-But Fortran 
+-.ul
+-is
+-unpleasant.
+-Perhaps the worst deficiency is in
+-the control flow
+-statements
+-_ conditional branches and loops _
+-which express the logic of the program.
+-The conditional statements in Fortran are primitive.
+-The Arithmetic 
+-.UC IF
+-forces the user into at least two statement numbers and
+-two (implied) 
+-.UC GOTO 's;
+-it leads to unintelligible code, and is eschewed by good programmers.
+-The Logical
+-.UC IF
+-is better, in that the test part can be stated clearly,
+-but hopelessly restrictive because the statement
+-that follows the
+-.UC IF
+-can only be one Fortran statement
+-(with some
+-.ul
+-further
+-restrictions!).
+-And of course there can be no
+-.UC ELSE
+-part to a Fortran
+-.UC IF :
+-there is no way to specify an alternative action if the
+-.UC IF
+-is not satisfied.
+-.PP
+-The Fortran
+-.UC DO
+-restricts the user to going forward in an arithmetic progression.
+-It is fine for ``1 to N in steps of 1 (or 2 or ...)'',
+-but there is no direct way to go backwards,
+-or even (in ANSI Fortran[2]) to go from 1 to
+-.if n N-1.
+-.if t N\(mi1.
+-And of course the
+-.UC DO
+-is useless if one's problem doesn't map into an arithmetic progression.
+-.PP
+-The result of these failings is that Fortran programs
+-must be written with numerous labels and branches.
+-The resulting code is
+-particularly difficult to read and understand,
+-and thus hard to debug and modify.
+-.PP
+-When one is faced with an unpleasant language,
+-a useful technique is to define
+-a new language that overcomes the deficiencies,
+-and to translate it into the unpleasant one
+-with a preprocessor.
+-This is the approach taken with 
+-Ratfor.
+-(The preprocessor idea is of course not new,
+-and preprocessors for Fortran are especially popular
+-today.
+-A recent listing [3] of preprocessors 
+-shows more than 50, of which at least half a dozen are widely available.)
+//GO.SYSIN DD m1
+echo m2
+sed 's/.//' >m2 <<'//GO.SYSIN DD m2'
+-.NH
+-LANGUAGE DESCRIPTION
+-.SH
+-Design
+-.PP
+-Ratfor
+-attempts to retain the merits of Fortran
+-(universality, portability, efficiency)
+-while hiding the worst Fortran inadequacies.
+-The language
+-.ul
+-is
+-Fortran except for two aspects.
+-First,
+-since control flow is central to any program,
+-regardless of the specific application,
+-the primary task of
+-Ratfor
+-is to conceal this part of Fortran from the user,
+-by providing decent control flow structures.
+-These structures are sufficient and comfortable
+-for structured programming in the narrow sense of programming without
+-.UC GOTO 's.
+-Second, since the preprocessor must examine an entire program
+-to translate the control structure,
+-it is possible at the same time to clean up many of the
+-``cosmetic'' deficiencies of Fortran,
+-and thus provide a language which is easier
+-and more pleasant to read and write.
+-.PP
+-Beyond these two aspects _ control flow and cosmetics _
+-Ratfor
+-does nothing about the host of other weaknesses of Fortran.
+-Although it would be straightforward to extend 
+-it
+-to provide
+-character strings,
+-for example,
+-they are not needed by everyone,
+-and of course
+-the preprocessor would be harder to implement.
+-Throughout, the design principle which has determined
+-what should be in
+-Ratfor
+-and what should not has
+-been
+-.ul
+-Ratfor
+-.ul
+-doesn't know any Fortran.
+-Any language feature which would require that
+-Ratfor
+-really understand Fortran has been omitted.
+-We will return to this point in the section
+-on implementation.
+-.PP
+-Even within the confines of control flow and cosmetics,
+-we have attempted to be selective
+-in what features to provide.
+-The intent has been to provide a small set of the most useful
+-constructs,
+-rather than to throw in everything that has ever been thought useful
+-by someone.
+-.PP
+-The rest of this section contains an informal description
+-of the
+-Ratfor
+-language.
+-The control flow aspects will be
+-quite familiar to readers used to languages like
+-Algol, PL/I, Pascal, etc.,
+-and the cosmetic changes are equally straightforward.
+-We shall concentrate on 
+-showing what the language looks like.
+-.SH
+-Statement Grouping
+-.PP
+-Fortran provides no way to group statements together,
+-short of making them into a subroutine.
+-The standard construction
+-``if a condition is true,
+-do this group of things,''
+-for example,
+-.P1
+-if (x > 100)
+-      { call error("x>100"); err = 1; return }
+-.P2
+-cannot be written directly in Fortran.
+-Instead
+-a programmer is forced to translate this relatively
+-clear thought into murky Fortran,
+-by stating the negative condition
+-and branching around the group of statements:
+-.P1
+-      if (x .le. 100) goto 10
+-              call error(5hx>100)
+-              err = 1
+-              return
+-10    ...
+-.P2
+-When the program doesn't work,
+-or when it must be modified,
+-this must be translated back into
+-a clearer form before one can be sure what it does.
+-.PP
+-Ratfor
+-eliminates this error-prone and confusing back-and-forth translation;
+-the first form 
+-.ul
+-is
+-the way the computation is written in 
+-Ratfor.
+-A group of statements can be treated as a unit
+-by enclosing them in the braces { and }.
+-This is true throughout the language:
+-wherever a single 
+-Ratfor
+-statement can be used,
+-there can be several enclosed in braces.
+-(Braces seem clearer and less obtrusive than
+-.UL begin
+-and
+-.UL end 
+-or
+-.UL do
+-and
+-.UL end ,
+-and of course 
+-.UL do
+-and
+-.UL end
+-already have Fortran meanings.)
+-.PP
+-Cosmetics
+-contribute to the readability of code,
+-and thus to its understandability.
+-The character ``>'' is clearer than
+-.UC ``.GT.'' ,
+-so
+-Ratfor
+-translates it appropriately,
+-along with several other similar shorthands.
+-Although many Fortran compilers permit character strings in quotes
+-(like
+-.UL """x>100""" ),
+-quotes are
+-not allowed in 
+-.UC ANSI
+-Fortran,
+-so 
+-Ratfor
+-converts it into the right number of
+-.UL H 's:
+-computers count better than people do.
+-.PP
+-Ratfor
+-is a free-form language:
+-statements may appear anywhere on a line,
+-and several may appear on one line
+-if they are separated by semicolons.
+-The example above could also be written as
+-.P1
+-if (x > 100) {
+-      call error("x>100")
+-      err = 1
+-      return
+-}
+-.P2
+-In this case, no semicolon is needed at the end of each line because
+-Ratfor
+-assumes there is one statement per line
+-unless told otherwise.
+-.PP
+-Of course,
+-if the statement that follows the
+-.UL if
+-is a single statement
+-(Ratfor
+-or otherwise),
+-no braces are needed:
+-.P1
+-if (y <= 0.0 & z <= 0.0)
+-      write(6, 20) y, z
+-.P2
+-No continuation need be indicated 
+-because the statement is clearly not finished on the first line.
+-In general
+-Ratfor
+-continues lines when it seems obvious that they are not yet done.
+-(The continuation convention is discussed in detail later.)
+-.PP
+-Although a free-form language permits wide latitude in formatting styles,
+-it is wise to pick one that is readable, then stick to it.
+-In particular, proper indentation is vital,
+-to make the logical structure of the program obvious to the reader.
+-.sp
+-.SH
+-The ``else'' Clause
+-.PP
+-Ratfor
+-provides an
+-.UL "else"
+-statement to handle the construction
+-``if a condition is true,
+-do 
+-this
+-thing,
+-.ul
+-otherwise
+-do that thing.''
+-.P1
+-if (a <= b)
+-      { sw = 0; write(6, 1) a, b }
+-else
+-      { sw = 1; write(6, 1) b, a }
+-.P2
+-This writes out the smaller of
+-.UL a
+-and
+-.UL b ,
+-then the larger, and sets
+-.UL sw
+-appropriately.
+-.PP
+-The Fortran equivalent of this code is circuitous indeed:
+-.P1
+-      if (a .gt. b) goto 10
+-              sw = 0
+-              write(6, 1) a, b
+-              goto 20
+-10    sw = 1
+-      write(6, 1) b, a
+-20    ...
+-.P2
+-This is a mechanical translation;
+-shorter forms exist, 
+-as they do for many similar situations.
+-But all translations suffer from the same problem:
+-since they are translations,
+-they are less clear and understandable than code
+-that is not a translation.
+-To understand the Fortran version,
+-one must scan the entire program to make
+-sure that no other statement branches
+-to statements 10 or 20
+-before one knows that indeed this is an 
+-.UL if-else
+-construction.
+-With the
+-Ratfor
+-version,
+-there is no question about how one gets to the parts of the statement.
+-The
+-.UL if-else
+-is a single unit,
+-which can be read, understood, and ignored if not relevant.
+-The program says what it means.
+-.PP
+-As before, if the statement following an
+-.UL if
+-or an
+-.UL else
+-is a single statement, no braces are needed:
+-.P1
+-if (a <= b)
+-      sw = 0
+-else
+-      sw = 1
+-.P2
+-.PP
+-The syntax of the
+-.UL if
+-statement is
+-.P1
+-if (\fIlegal Fortran condition\fP)
+-      \fIRatfor statement\fP
+-else
+-      \fIRatfor statement\fP
+-.P2
+-where the 
+-.UL else
+-part is optional.
+-The
+-.ul
+-legal Fortran condition
+-is
+-anything that can legally go into a Fortran Logical
+-.UC IF .
+-Ratfor
+-does not check this clause,
+-since it does not know enough Fortran
+-to know what is permitted.
+-The
+-.ul
+-Ratfor
+-.ul
+-statement
+-is any Ratfor or Fortran statement, or any collection of them
+-in braces.
+-.SH
+-Nested if's
+-.PP
+-Since the statement that follows an
+-.UL if
+-or 
+-an
+-.UL else
+-can be any Ratfor statement, this leads immediately
+-to the possibility of another
+-.UL if
+-or
+-.UL else .
+-As a useful example, consider this problem:
+-the variable
+-.UL f
+-is to be set to
+-\-1 if
+-.UL x
+-is less than zero,
+-to
+-+1
+-if
+-.UL x
+-is greater than 100,
+-and to 0 otherwise.
+-Then in Ratfor, we write
+-.P1
+-if (x < 0)
+-      f = -1
+-else if (x > 100)
+-      f = +1
+-else
+-      f = 0
+-.P2
+-Here the statement after the first
+-.UL else
+-is another
+-.UL if-else .
+-Logically it is just a single statement,
+-although it is rather complicated.
+-.PP
+-This code says what it means.
+-Any version written in straight Fortran
+-will necessarily be indirect
+-because Fortran does not let you say what you mean.
+-And as always, clever shortcuts may turn out
+-to be too clever to understand a year from now.
+-.PP
+-Following an
+-.UL else
+-with an
+-.UL if
+-is one way to write a multi-way branch in Ratfor.
+-In general the structure
+-.P1
+-if (...)
+-      - - -
+-else if (...)
+-      - - -
+-else if (...)
+-      - - -
+- ...
+-else
+-      - - -
+-.P2
+-provides a way to specify the choice of exactly one of several alternatives.
+-(Ratfor also provides a
+-.UL switch
+-statement which does the same job
+-in certain special cases;
+-in more general situations, we have to make do
+-with spare parts.)
+-The tests are laid out in sequence, and each one
+-is followed by the code associated with it.
+-Read down the list
+-of decisions until one is found that is satisfied.
+-The code associated with this condition is executed,
+-and then the entire structure is finished.
+-The trailing
+-.UL else
+-part handles the ``default'' case,
+-where none of the other conditions apply.
+-If there is no default action, this final
+-.UL else
+-part
+-is omitted:
+-.P1
+-if (x < 0)
+-      x = 0
+-else if (x > 100)
+-      x = 100
+-.P2
+-.SH
+-if-else ambiguity
+-.PP
+-There is one thing to notice about complicated structures
+-involving nested
+-.UL if 's
+-and
+-.UL else 's.
+-Consider
+-.P1
+-if (x > 0)
+-      if (y > 0)
+-              write(6, 1) x, y
+-      else
+-              write(6, 2) y
+-.P2
+-There are two
+-.UL if 's
+-and
+-only one
+-.UL else .
+-Which
+-.UL if
+-does the
+-.UL else
+-go with?
+-.PP
+-This is a genuine ambiguity in Ratfor, as it is in many other programming
+-languages.
+-The ambiguity is resolved in Ratfor
+-(as elsewhere) by saying that in such cases the
+-.UL else
+-goes with the closest previous
+-.UL else 'ed un-
+-.UL if .
+-Thus in this case, the
+-.UL else
+-goes with the inner
+-.UL if ,
+-as we have indicated by the indentation.
+-.PP
+-It is a wise practice to resolve such cases by explicit braces,
+-just to make your intent clear.
+-In the case above, we would write
+-.P1
+-if (x > 0) {
+-      if (y > 0)
+-              write(6, 1) x, y
+-      else
+-              write(6, 2) y
+-}
+-.P2
+-which does not change the meaning, but leaves
+-no doubt in the reader's mind.
+-If we want the other association, we
+-.ul
+-must
+-write
+-.P1
+-if (x > 0) {
+-      if (y > 0)
+-              write(6, 1) x, y
+-}
+-else
+-      write(6, 2) y
+-.P2
+-.SH
+-The ``switch'' Statement
+-.PP
+-The
+-.UL switch
+-statement
+-provides a clean way to express multi-way branches
+-which branch on the value of some integer-valued expression.
+-The syntax is
+-.P1
+-\f3switch (\fIexpression\|\f3) {
+-
+-      case \fIexpr1\f3 :
+-              \f2statements\f3
+-      case \fIexpr2, expr3\f3 :
+-              \f2statements\f3
+-      ...
+-      default:
+-              \f2statements\f3
+-}
+-.P2
+-.PP
+-Each
+-.UL case
+-is followed by a
+-list of comma-separated integer expressions.
+-The
+-.ul
+-expression
+-inside
+-.UL switch
+-is compared against the case expressions
+-.ul
+-expr1,
+-.ul
+-expr2, 
+-and so on in turn
+-until one matches,
+-at which time the statements following that
+-.UL case
+-are executed.
+-If no cases match
+-.ul
+-expression,
+-and there is a
+-.UL default 
+-section,
+-the statements with it are done;
+-if there is no
+-.UL default,
+-nothing is done.
+-In all situations,
+-as soon as some block of statements is executed,
+-the entire
+-.UL switch
+-is exited immediately.
+-(Readers familiar with C[4] should beware that this
+-behavior is not the same as the C
+-.UL switch .)
+-.SH
+-The ``do'' Statement
+-.PP
+-The
+-.UL do
+-statement in
+-Ratfor
+-is quite similar to the
+-.UC DO
+-statement in Fortran,
+-except that it uses no statement number.
+-The statement number, after all, serves only to mark the end
+-of the
+-.UC DO ,
+-and this can be done just as easily with braces.
+-Thus
+-.P1
+-      do i = 1, n {
+-              x(i) = 0.0
+-              y(i) = 0.0
+-              z(i) = 0.0
+-      }
+-.P2
+-is the same as
+-.P1
+-      do 10 i = 1, n
+-              x(i) = 0.0
+-              y(i) = 0.0
+-              z(i) = 0.0
+-10    continue
+-.P2
+-The syntax is:
+-.P1
+-do \fIlegal\(hyFortran\(hyDO\(hytext\fP
+-      \fIRatfor statement\fP
+-.P2
+-The part that follows 
+-the keyword
+-.UL do
+-has to be something that can legally go into a Fortran
+-.UC DO
+-statement.
+-Thus if a local version of Fortran allows
+-.UC DO
+-limits to be expressions
+-(which is not currently permitted in
+-.UC ANSI
+-Fortran),
+-they can be used in a
+-Ratfor
+-.UL do.
+-.PP
+-The
+-.ul
+-Ratfor statement
+-part will often be enclosed in braces, but
+-as with the
+-.UL if ,
+-a single statement need not have braces around it.
+-This code sets an array to zero:
+-.P1
+-do i = 1, n
+-      x(i) = 0.0
+-.P2
+-Slightly more complicated,
+-.P1
+-do i = 1, n
+-      do j = 1, n
+-              m(i, j) = 0
+-.P2
+-sets the entire array
+-.UL m
+-to zero, and
+-.P1
+-do i = 1, n
+-      do j = 1, n
+-              if (i < j)
+-                      m(i, j) = -1
+-              else if (i == j)
+-                      m(i, j) = 0
+-              else
+-                      m(i, j) = +1
+-.P2
+-sets the upper triangle of
+-.UL m
+-to \-1, the diagonal to zero, and the lower triangle to +1.
+-(The operator == is ``equals'', that is, ``.EQ.''.)
+-In each case, the statement that follows the
+-.UL do
+-is logically a
+-.ul
+-single
+-statement, even though complicated,
+-and thus needs no braces.
+-.sp
+-.SH
+-``break'' and ``next''
+-.PP
+-Ratfor
+-provides a statement for leaving a loop early,
+-and one for beginning the next iteration.
+-.UL "break"
+-causes an immediate exit from the
+-.UL do ;
+-in effect it is a branch to the statement
+-.ul
+-after
+-the
+-.UL do .
+-.UL next
+-is a branch to the bottom of the loop,
+-so it causes the next iteration to be done.
+-For example, this code skips over negative values in an array:
+-.P1
+-do i = 1, n {
+-      if (x(i) < 0.0)
+-              next
+-      \fIprocess positive element\fP
+-}
+-.P2
+-.UL break
+-and
+-.UL next
+-also work in the other Ratfor looping constructions
+-that we will talk about in the next few sections.
+-.PP
+-.UL break
+-and
+-.UL next
+-can be followed by an integer to indicate breaking or iterating
+-that level of enclosing loop; thus
+-.P1
+-break 2
+-.P2
+-exits from two levels of enclosing loops,
+-and
+-.UL break\ 1
+-is equivalent to
+-.UL break .
+-.UL next\ 2
+-iterates the second enclosing loop.
+-(Realistically, 
+-multi-level
+-.UL break 's
+-and
+-.UL next 's
+-are
+-not likely to be much used
+-because they lead to code that is hard to understand
+-and somewhat risky to change.)
+-.sp
+-.SH
+-The ``while'' Statement
+-.PP
+-One of the problems with the Fortran
+-.UC DO
+-statement
+-is that it generally insists upon being done once,
+-regardless of its limits.
+-If a loop begins
+-.P1
+-DO I = 2, 1
+-.P2
+-this will typically be done once with
+-.UL I
+-set to 2,
+-even though common sense would suggest that perhaps it shouldn't be.
+-Of course a
+-Ratfor
+-.UL do
+-can easily be preceded by a test
+-.P1
+-if (j <= k)
+-      do i = j, k  {
+-              _ _ _
+-      }
+-.P2
+-but this has to be a conscious act,
+-and is often overlooked by programmers.
+-.PP
+-A more serious problem with the
+-.UC DO
+-statement
+-is that it encourages that a program be written
+-in terms of an arithmetic progression
+-with small positive steps,
+-even though that may not be the best way to write it.
+-If code has to be contorted to fit the requirements
+-imposed by the Fortran
+-.UC DO ,
+-it is that much harder to write and understand.
+-.PP
+-To overcome these difficulties,
+-Ratfor
+-provides a
+-.UL while
+-statement,
+-which is simply a loop:
+-``while some condition is true,
+-repeat this group of statements''.
+-It has
+-no preconceptions about why one is looping.
+-For example, this routine to compute sin(x)
+-by the Maclaurin series
+-combines two termination criteria.
+-.P1 1
+-.ta .3i .6i .9i 1.2i 1.5i 1.8i
+-real function sin(x, e)
+-      # returns sin(x) to accuracy e, by
+-      # sin(x) = x - x**3/3! + x**5/5! - ...
+-
+-      sin = x
+-      term = x
+-
+-      i = 3
+-      while (abs(term)>e & i<100) {
+-              term = -term * x**2 / float(i*(i-1))
+-              sin = sin + term
+-              i = i + 2
+-      }
+-
+-      return
+-      end
+-.P2
+-.PP
+-Notice that
+-if the routine is entered with
+-.UL term
+-already smaller than
+-.UL e ,
+-the 
+-loop will be done
+-.ul
+-zero times,
+-that is, no attempt will be made to compute
+-.UL x**3
+-and thus a potential underflow is avoided.
+-Since the test is made at the top of a
+-.UL while
+-loop
+-instead of the bottom,
+-a special case disappears _
+-the code works at one of its boundaries.
+-(The test
+-.UL i<100
+-is the other boundary _
+-making sure the routine stops after
+-some maximum number of iterations.)
+-.PP
+-As an aside, a sharp character ``#'' in a line
+-marks the beginning of a comment;
+-the rest of the line is comment.
+-Comments and code can co-exist on the same line _
+-one can make marginal remarks,
+-which is not possible with Fortran's ``C in column 1'' convention.
+-Blank lines are also permitted anywhere
+-(they are not in Fortran);
+-they should be used to emphasize the natural divisions
+-of a program.
+-.PP
+-The syntax of the 
+-.UL while
+-statement is
+-.P1
+-while (\fIlegal Fortran condition\fP)
+-      \fIRatfor statement\fP
+-.P2
+-As with the
+-.UL if ,
+-.ul
+-legal Fortran condition
+-is something that can go into
+-a Fortran Logical
+-.UC IF ,
+-and
+-.ul
+-Ratfor statement
+-is a single statement,
+-which may be multiple statements in braces.
+-.PP
+-The
+-.UL while
+-encourages a style of coding not normally
+-practiced by Fortran programmers.
+-For example, suppose
+-.UL nextch
+-is a function which returns the next input character
+-both as a function value and in its argument.
+-Then a loop to find the first non-blank character is just
+-.P1
+-while (nextch(ich) == iblank)
+-      ;
+-.P2
+-A semicolon by itself is a null statement,
+-which is necessary here to mark the end of the
+-.UL while ;
+-if it were not present, the
+-.UL while
+-would control the next statement.
+-When the loop is broken, 
+-.UL ich
+-contains the first non-blank.
+-Of course the same code can be written in Fortran as
+-.P1 1
+-100   if (nextch(ich) .eq. iblank) goto 100
+-.P2
+-but many Fortran programmers (and a few compilers) believe this line is illegal.
+-The language at one's disposal
+-strongly influences how one thinks about a problem.
+-.sp
+-.SH
+-The ``for'' Statement
+-.PP
+-The
+-.UL for
+-statement
+-is another Ratfor loop, which
+-attempts to carry the separation of
+-loop-body from reason-for-looping
+-a step further
+-than the
+-.UL while.
+-A
+-.UL for
+-statement allows explicit initialization
+-and increment steps as part of the statement.
+-For example, 
+-a
+-.UC DO
+-loop is just
+-.P1
+-for (i = 1; i <= n; i = i + 1) ...
+-.P2
+-This is equivalent to
+-.P1
+-i = 1
+-while (i <= n) {
+-      ...
+-      i = i + 1
+-}
+-.P2
+-The initialization and increment of
+-.UL i
+-have been moved into the
+-.UL for
+-statement,
+-making it easier to see at a glance
+-what controls the loop.
+-.PP
+-The
+-.UL for
+-and
+-.UL while
+-versions have the advantage that they will be done zero times
+-if
+-.UL n
+-is less than 1; this is not true of the
+-.UL do .
+-.PP
+-The loop of the sine routine in the previous section
+-can be re-written
+-with a
+-.UL for
+-as
+-.P1 3
+-for (i=3; abs(term) > e & i < 100; i=i+2) {
+-      term = -term * x**2 / float(i*(i-1))
+-      sin = sin + term
+-}
+-.P2
+-.PP
+-The syntax of the
+-.UL for
+-statement is
+-.P1
+-for ( \fIinit\fP ; \fIcondition\fP ; \fIincrement\fP )
+-      \fIRatfor statement\fP
+-.P2
+-.ul
+-init
+-is any single Fortran statement, which gets done once
+-before the loop begins.
+-.ul
+-increment
+-is any single Fortran statement,
+-which gets done at the end of each pass through the loop,
+-before the test.
+-.ul
+-condition
+-is again anything that is legal in a logical 
+-.UC IF.
+-Any of 
+-.ul
+-init,
+-.ul
+-condition,
+-and
+-.ul
+-increment
+-may be omitted,
+-although the semicolons
+-.ul
+-must
+-always be present.
+-A non-existent
+-.ul
+-condition
+-is treated as always true,
+-so
+-.UL "for(;;)"
+-is an indefinite repeat.
+-(But see the
+-.UL repeat-until
+-in the next section.)
+-.PP
+-The
+-.UL for
+-statement is particularly
+-useful for
+-backward loops, chaining along lists,
+-loops that might be done zero times,
+-and similar things which are hard to express with a 
+-.UC DO
+-statement,
+-and obscure to write out 
+-with
+-.UC IF 's
+-and
+-.UC GOTO 's.
+-For example,
+-here is a
+-backwards
+-.UC DO
+-loop
+-to find the last non-blank character on a card:
+-.P1
+-for (i = 80; i > 0; i = i - 1)
+-      if (card(i) != blank)
+-              break
+-.P2
+-(``!='' is the same as 
+-.UC ``.NE.'' ).
+-The code scans the columns from 80 through to 1.
+-If a non-blank is found, the loop
+-is immediately broken.
+-.UL break \& (
+-and
+-.UL next
+-work in
+-.UL for 's
+-and
+-.UL while  's
+-just as in 
+-.UL do 's).
+-If 
+-.UL i
+-reaches zero,
+-the card is all blank.
+-.PP
+-This code is rather nasty to write with a regular Fortran
+-.UC DO ,
+-since the loop must go forward,
+-and we must explicitly set up proper conditions
+-when we fall out of the loop.
+-(Forgetting this is a common error.)
+-Thus:
+-.P1 1
+-.ta .3i .6i .9i 1.2i 1.5i 1.8i
+-      DO 10 J = 1, 80
+-              I = 81 - J
+-              IF (CARD(I) .NE. BLANK) GO TO 11
+-10    CONTINUE
+-      I = 0
+-11    ...
+-.P2
+-The version that uses the
+-.UL for
+-handles the termination condition properly for free;
+-.UL i
+-.ul
+-is
+-zero when we fall out of the
+-.UL for
+-loop.
+-.PP
+-The increment
+-in a
+-.UL for
+-need not be an arithmetic progression;
+-the following program walks along a list
+-(stored in an integer array
+-.UL ptr )
+-until a zero pointer is found,
+-adding up elements from a parallel array of values:
+-.P1
+-sum = 0.0
+-for (i = first; i > 0; i = ptr(i))
+-      sum = sum + value(i)
+-.P2
+-Notice that the code works correctly if the list is empty.
+-Again, placing the test at the top of a loop
+-instead of the bottom eliminates a potential boundary error.
+-.SH
+-The ``repeat-until'' statement
+-.PP
+-In spite of the dire warnings,
+-there are times when one really needs a loop that tests at the bottom
+-after one pass through.
+-This service is provided by the
+-.UL repeat-until :
+-.P1
+-repeat
+-      \fIRatfor statement\fP
+-until (\fIlegal Fortran condition\fP)
+-.P2
+-The
+-.ul
+-Ratfor statement
+-part is done once,
+-then the condition is evaluated.
+-If it is true, the loop is exited;
+-if it is false, another pass is made.
+-.PP
+-The
+-.UL until
+-part is optional, so a bare
+-.UL repeat
+-is the cleanest way to specify an infinite loop.
+-Of course such a loop must ultimately be broken by some
+-transfer of control such as
+-.UL stop ,
+-.UL return ,
+-or
+-.UL break ,
+-or an implicit stop such as running out of input with
+-a
+-.UC READ
+-statement.
+-.PP
+-As a matter of observed fact[8], the
+-.UL repeat-until
+-statement is
+-.ul
+-much
+-less used than the other looping constructions;
+-in particular, it is typically outnumbered ten to one by
+-.UL for
+-and
+-.UL while .
+-Be cautious about using it, for loops that test only at the
+-bottom often don't handle null cases well.
+-.SH
+-More on break and next
+-.PP
+-.UL break
+-exits immediately from 
+-.UL do ,
+-.UL while ,
+-.UL for ,
+-and
+-.UL repeat-until .
+-.UL next
+-goes to the test part of
+-.UL do ,
+-.UL while
+-and
+-.UL repeat-until ,
+-and to the increment step of a
+-.UL for .
+-.SH
+-``return'' Statement
+-.PP
+-The standard Fortran mechanism for returning a value from a function uses the name of the function as a variable which can be assigned to;
+-the last value stored in it 
+-is the function value upon return.
+-For example, here is a routine
+-.UL equal
+-which returns 1 if two arrays are identical,
+-and zero if they differ.
+-The array ends are marked by the special value \-1.
+-.P1 1
+-.ta .3i .6i .9i 1.2i 1.5i 1.8i
+-# equal _ compare str1 to str2;
+-#     return 1 if equal, 0 if not
+-      integer function equal(str1, str2)
+-      integer str1(100), str2(100)
+-      integer i
+-
+-      for (i = 1; str1(i) == str2(i); i = i + 1)
+-              if (str1(i) == -1) {
+-                      equal = 1
+-                      return
+-              }
+-      equal = 0
+-      return
+-      end
+-.P2
+-.PP
+-In many languages (e.g., PL/I)
+-one instead says
+-.P1
+-return (\fIexpression\fP)
+-.P2
+-to return a value from a function.
+-Since this is often clearer, Ratfor provides such a
+-.UL return
+-statement _
+-in a function
+-.UL F ,
+-.UL return (expression)
+-is equivalent to
+-.P1
+-{ F = expression; return }
+-.P2
+-For example, here is
+-.UL equal
+-again:
+-.P1 1
+-.ta .3i .6i .9i 1.2i 1.5i 1.8i
+-# equal _ compare str1 to str2;
+-#     return 1 if equal, 0 if not
+-      integer function equal(str1, str2)
+-      integer str1(100), str2(100)
+-      integer i
+-
+-      for (i = 1; str1(i) == str2(i); i = i + 1)
+-              if (str1(i) == -1)
+-                      return(1)
+-      return(0)
+-      end
+-.P2
+-If there is no parenthesized expression after
+-.UL return ,
+-a normal
+-.UC RETURN 
+-is made.
+-(Another version of
+-.UL equal
+-is presented shortly.)
+-.sp
+-.SH
+-Cosmetics
+-.PP
+-As we said above,
+-the visual appearance of a language
+-has a substantial effect
+-on how easy it is to read and understand
+-programs.
+-Accordingly, Ratfor provides a number of cosmetic facilities
+-which may be used to make programs more readable.
+-.SH
+-Free-form Input
+-.PP
+-Statements can be placed anywhere on a line;
+-long statements are continued automatically,
+-as are long conditions in
+-.UL if ,
+-.UL while ,
+-.UL for ,
+-and
+-.UL until .
+-Blank lines are ignored.
+-Multiple statements may appear on one line,
+-if they are separated by semicolons.
+-No semicolon is needed at the end of a line,
+-if
+-Ratfor
+-can make some reasonable guess about whether the statement
+-ends there.
+-Lines ending with any of the characters
+-.P1
+-=    +    -    *    ,    |    &    (    \(ru
+-.P2
+-are assumed to be continued on the next line.
+-Underscores are discarded wherever they occur;
+-all others remain as part of the statement.
+-.PP
+-Any statement that begins with an all-numeric field is
+-assumed to be a Fortran label,
+-and placed in columns 1-5 upon output.
+-Thus
+-.P1
+-write(6, 100); 100 format("hello")
+-.P2
+-is converted into
+-.P1
+-      write(6, 100)
+-100   format(5hhello)
+-.P2
+-.SH
+-Translation Services
+-.PP
+-Text enclosed in matching single or double quotes
+-is converted to
+-.UL nH...
+-but is otherwise unaltered
+-(except for formatting _ it may get split across card boundaries
+-during the reformatting process).
+-Within quoted strings, the backslash `\e' serves as an escape character:
+-the next character is taken literally.
+-This provides a way to get quotes (and of course the backslash itself) into
+-quoted strings:
+-.P1
+-"\e\e\e\(fm"
+-.P2
+-is a string containing a backslash and an apostrophe.
+-(This is
+-.ul
+-not
+-the standard convention of doubled quotes,
+-but it is easier to use and more general.)
+-.PP
+-Any line that begins with the character `%'
+-is left absolutely unaltered  
+-except for stripping off the `%'
+-and moving the line one position to the left.
+-This is useful for inserting control cards,
+-and other things that should not be transmogrified
+-(like an existing Fortran program).
+-Use `%' only for ordinary statements,
+-not for the condition parts of
+-.UL if ,
+-.UL while ,
+-etc., or the output may come out in an unexpected place.
+-.PP
+-The following character translations are made, 
+-except within single or double quotes
+-or on a line beginning with a `%'.
+-.P1
+-.ta .5i 1.5i 2i
+-==    .eq.    !=      .ne.
+->     .gt.    >=      .ge.
+-<     .lt.    <=      .le.
+-&     .and.   |       .or.
+-!     .not.   ^       .not.
+-.P2
+-In addition, the following translations are provided
+-for input devices with restricted character sets.
+-.P1
+-.ta .5i 1.5i 2i
+-[     {       ]       }
+-$(    {       $)      }
+-.P2
+-.SH
+-``define'' Statement
+-.PP
+-Any string of alphanumeric characters can be defined as a name;
+-thereafter, whenever that name occurs in the input
+-(delimited by non-alphanumerics)
+-it is replaced by the rest of the definition line.
+-(Comments and trailing white spaces are stripped off).
+-A defined name can be arbitrarily long,
+-and must begin with a letter.
+-.PP
+-.UL define
+-is typically used to create symbolic parameters:
+-.P1
+-define        ROWS    100
+-define        COLS    50
+-.if t .sp 5p
+-dimension a(ROWS), b(ROWS, COLS)
+-.if t .sp 5p
+-      if (i > ROWS  \(or  j > COLS) ...
+-.P2
+-Alternately, definitions may be written as
+-.P1
+-define(ROWS, 100)
+-.P2
+-In this case, the defining text is everything after the comma up to the balancing
+-right parenthesis;
+-this allows multi-line definitions.
+-.PP
+-It is generally a wise practice to use symbolic parameters
+-for most constants, to help make clear the function of what
+-would otherwise be mysterious numbers.
+-As an example, here is the routine
+-.UL equal 
+-again, this time with symbolic constants.
+-.P1 3
+-.ta .3i .6i .9i 1.2i 1.5i 1.8i
+-define        YES             1
+-define        NO              0
+-define        EOS             -1
+-define        ARB             100
+-
+-# equal _ compare str1 to str2;
+-#     return YES if equal, NO if not
+-      integer function equal(str1, str2)
+-      integer str1(ARB), str2(ARB)
+-      integer i
+-
+-      for (i = 1; str1(i) == str2(i); i = i + 1)
+-              if (str1(i) == EOS)
+-                      return(YES)
+-      return(NO)
+-      end
+-.P2
+-.SH
+-``include'' Statement
+-.PP
+-The statement
+-.P1
+-      include file
+-.P2
+-inserts the file
+-found on input stream
+-.ul
+-file
+-into the
+-Ratfor
+-input in place of the
+-.UL include
+-statement.
+-The standard usage is to place 
+-.UC COMMON
+-blocks on a file,
+-and
+-.UL include
+-that file whenever a copy is needed:
+-.P1
+-subroutine x
+-      include commonblocks
+-      ...
+-      end
+-
+-suroutine y
+-      include commonblocks
+-      ...
+-      end
+-.P2
+-This ensures that all copies of the 
+-.UC COMMON
+-blocks are identical
+-.SH
+-Pitfalls, Botches, Blemishes and other Failings
+-.PP
+-Ratfor catches certain syntax errors, such as missing braces,
+-.UL else
+-clauses without an
+-.UL if ,
+-and most errors involving missing parentheses in statements.
+-Beyond that, since Ratfor knows no Fortran, 
+-any errors you make will be reported by the Fortran compiler,
+-so you will from time to time have to relate a Fortran diagnostic back
+-to the Ratfor source.
+-.PP
+-Keywords are reserved _
+-using
+-.UL if ,
+-.UL else ,
+-etc., as variable names will typically wreak havoc.
+-Don't leave spaces in keywords.
+-Don't use the Arithmetic
+-.UC IF .
+-.PP
+-The Fortran
+-.UL nH
+-convention is not recognized anywhere by Ratfor;
+-use quotes instead.
+//GO.SYSIN DD m2
+echo m3
+sed 's/.//' >m3 <<'//GO.SYSIN DD m3'
+-.NH
+-IMPLEMENTATION
+-.PP
+-Ratfor
+-was originally written in
+-C[4]
+-on the
+-.UC UNIX
+-operating system[5].
+-The language is specified by a context free grammar
+-and the compiler constructed using
+-the
+-.UC YACC
+-compiler-compiler[6].
+-.PP
+-The
+-Ratfor
+-grammar is simple and straightforward, being essentially
+-.P1
+-prog  : stat 
+-      | prog   stat
+-stat  : \f3if\fP (...) stat 
+-      | \f3if\fP (...) stat \f3else\fP stat
+-      | \f3while\fP (...) stat
+-      | \f3for\fP (...; ...; ...) stat
+-      | \f3do\fP ... stat
+-      | \f3repeat\fP stat
+-      | \f3repeat\fP stat \f3until\fP (...)
+-      | \f3switch\fP (...) { \f3case\fP ...: prog ...
+-                      \f3default\fP: prog }
+-      | \f3return\fP
+-      | \f3break\fP
+-      | \f3next\fP
+-      | digits   stat
+-      | { prog }
+-      | anything unrecognizable
+-.P2
+-The observation
+-that
+-Ratfor
+-knows no Fortran
+-follows directly from the rule that says a statement is
+-``anything unrecognizable''.
+-In fact most of Fortran falls into this category,
+-since any statement that does not begin with one of the keywords
+-is by definition ``unrecognizable.''
+-.PP
+-Code generation is also simple.
+-If the first thing on a source line is
+-not a keyword
+-(like
+-.UL if ,
+-.UL else ,
+-etc.)
+-the entire statement is simply copied to the output
+-with appropriate character translation and formatting.
+-(Leading digits are treated as a label.)
+-Keywords cause only slightly more complicated actions.
+-For example, when
+-.UL if
+-is recognized, two consecutive labels L and L+1
+-are generated and the value of L is stacked.
+-The condition is then isolated, and the code
+-.P1
+-if (.not. (condition)) goto L
+-.P2
+-is output.
+-The 
+-.ul
+-statement
+-part of the
+-.UL if
+-is then translated.
+-When the end of the 
+-statement is encountered
+-(which may be some distance away and include nested \f3if\fP's, of course),
+-the code
+-.P1
+-L     continue
+-.P2
+-is generated, unless there is an
+-.UL else
+-clause, in which case
+-the code is
+-.P1
+-      goto L+1
+-L     continue
+-.P2
+-In this latter case,
+-the code
+-.P1
+-L+1   continue
+-.P2
+-is produced after the
+-.ul
+-statement
+-part of the
+-.UL else.
+-Code generation for the various loops is equally simple.
+-.PP
+-One might argue that more care should be taken
+-in code generation.
+-For example,
+-if there is no trailing
+-.UL else ,
+-.P1
+-      if (i > 0) x = a
+-.P2
+-should be left alone, not converted into
+-.P1
+-      if (.not. (i .gt. 0)) goto 100
+-      x = a
+-100   continue
+-.P2
+-But what are optimizing compilers for, if not to improve code?
+-It is a rare program indeed where this kind of ``inefficiency''
+-will make even a measurable difference.
+-In the few cases where it is important,
+-the offending lines can be protected by `%'.
+-.PP
+-The use of a compiler-compiler is definitely the preferred method
+-of software development.
+-The language is well-defined,
+-with few syntactic irregularities.
+-Implementation is quite simple;
+-the original construction took under a week.
+-The language
+-is sufficiently simple, however, that an
+-.ul
+-ad hoc
+-recognizer can be readily constructed to do the same job
+-if no compiler-compiler is available.
+-.PP
+-The C version of 
+-Ratfor
+-is used on
+-.UC UNIX
+-and on the Honeywell
+-.UC GCOS
+-systems.
+-C compilers are not as widely available as Fortran, however,
+-so there is also a
+-Ratfor
+-written in itself
+-and originally bootstrapped with the C version.
+-The
+-Ratfor
+-version
+-was written so as to translate into the portable subset
+-of Fortran described in [1],
+-so it is portable,
+-having been run essentially without change
+-on at least twelve distinct machines.
+-(The main restrictions of the portable subset are:
+-only one character per machine word;
+-subscripts in the 
+-form
+-.ul
+-c*v\(+-c;
+-avoiding expressions in places like
+-.UC DO
+-loops;
+-consistency in subroutine argument usage,
+-and in 
+-.UC COMMON
+-declarations.
+-Ratfor
+-itself will not gratuitously generate non-standard Fortran.)
+-.PP
+-The
+-Ratfor
+-version is about 1500 lines of
+-Ratfor
+-(compared to about 1000 lines of C);
+-this compiles into 2500 lines of Fortran.
+-This expansion ratio is somewhat higher than average,
+-since the compiled code contains unnecessary occurrences
+-of
+-.UC COMMON
+-declarations.
+-The execution time of the
+-Ratfor
+-version is dominated by
+-two routines that read and write cards.
+-Clearly these routines could be replaced
+-by machine coded local versions;
+-unless this is done, the efficiency of other parts of the translation process
+-is largely irrelevant.
+//GO.SYSIN DD m3
+echo m4
+sed 's/.//' >m4 <<'//GO.SYSIN DD m4'
+-.NH
+-EXPERIENCE
+-.SH
+-Good Things
+-.PP
+-``It's
+-so much better than Fortran''
+-is the most common response of users
+-when asked how well
+-Ratfor
+-meets their needs.
+-Although cynics might consider this to be vacuous,
+-it does seem to be true that 
+-decent control flow and cosmetics converts Fortran
+-from a bad language into quite a reasonable one,
+-assuming that Fortran data structures are adequate
+-for the task at hand.
+-.PP
+-Although there are no quantitative results,
+-users feel that coding in
+-Ratfor
+-is at least twice as fast as in Fortran.
+-More important, debugging and subsequent revision
+-are much faster than in Fortran.
+-Partly this is simply because the code can be
+-.ul
+-read.
+-The looping statements
+-which test at the top instead of the bottom
+-seem to eliminate or at least
+-reduce the occurrence of a wide class of
+-boundary errors.
+-And of course it is easy to do structured programming in 
+-Ratfor;
+-this self-discipline also contributes
+-markedly to reliability.
+-.PP
+-One interesting and encouraging fact is that
+-programs written in
+-Ratfor
+-tend to be as readable as programs
+-written in more modern languages
+-like Pascal.
+-Once one is freed from the shackles of Fortran's
+-clerical detail and rigid input format,
+-it is easy to write code that is readable, even esthetically pleasing.
+-For example,
+-here is a
+-Ratfor
+-implementation of the linear table search discussed by
+-Knuth [7]:
+-.P1
+-A(m+1) = x
+-for (i = 1; A(i) != x; i = i + 1)
+-      ;
+-if (i > m) {
+-      m = i
+-      B(i) = 1
+-}
+-else
+-      B(i) = B(i) + 1
+-.P2
+-A large corpus (5400 lines) of Ratfor, including a subset of
+-the Ratfor preprocessor itself,
+-can be found in
+-[8].
+-.SH
+-Bad Things
+-.PP
+-The biggest single problem is that many Fortran syntax errors
+-are not detected by
+-Ratfor
+-but by the local Fortran compiler.
+-The compiler then prints a message
+-in terms of the generated Fortran,
+-and in a few cases this may be difficult
+-to relate back to the offending
+-Ratfor
+-line,
+-especially if the implementation conceals the generated Fortran.
+-This problem could be dealt with
+-by tagging each generated line with some indication
+-of the source line that created it,
+-but this is inherently implementation-dependent,
+-so no action has yet been taken.
+-Error message interpretation
+-is actually not so arduous as might be thought.
+-Since Ratfor generates no variables,
+-only a simple pattern of
+-.UC IF 's
+-and
+-.UC GOTO 's,
+-data-related errors like missing
+-.UC DIMENSION
+-statements
+-are easy to find in the Fortran.
+-Furthermore, there has been a steady improvement
+-in Ratfor's ability to catch trivial syntactic
+-errors like unbalanced parentheses and quotes.
+-.PP
+-There are a number of implementation weaknesses
+-that are a nuisance, especially to new users.
+-For example,
+-keywords are reserved.
+-This rarely makes any difference, except for those hardy souls
+-who want to use an Arithmetic 
+-.UC IF .
+-A few standard Fortran
+-constructions are not accepted by 
+-Ratfor,
+-and this is perceived as a problem by users with a large corpus
+-of existing Fortran programs.
+-Protecting every line with a `%' is not really a
+-complete solution, although it serves as a stop-gap.
+-The best long-term solution is provided by the program
+-Struct [9],
+-which converts arbitrary Fortran programs into Ratfor.
+-.PP
+-Users who export programs often complain that the generated Fortran is
+-``unreadable'' because it is not 
+-tastefully formatted and contains extraneous
+-.UC CONTINUE
+-statements.
+-To some extent this can be ameliorated
+-(Ratfor now has an option to copy Ratfor comments into
+-the generated Fortran),
+-but it has always seemed that effort is better spent
+-on the input language than on the output esthetics.
+-.PP
+-One final problem is partly attributable to success _
+-since Ratfor is relatively easy to modify,
+-there are now several dialects of Ratfor.
+-Fortunately, so far most of the differences are in character set,
+-or in invisible aspects like code generation.
+//GO.SYSIN DD m4
+echo m5
+sed 's/.//' >m5 <<'//GO.SYSIN DD m5'
+-.NH
+-CONCLUSIONS
+-.PP
+-Ratfor
+-demonstrates that with modest effort
+-it is possible to convert Fortran
+-from a bad language into quite a good one.
+-A preprocessor 
+-is clearly a useful way to extend or ameliorate
+-the facilities of a base language.
+-.PP
+-When designing a language,
+-it is important to concentrate on
+-the essential requirement of providing
+-the user with the best language possible
+-for a given effort.
+-One must avoid throwing in
+-``features'' _
+-things which the user may trivially construct within the existing
+-framework.
+-.PP
+-One must also avoid getting sidetracked on irrelevancies.
+-For instance it seems pointless for
+-Ratfor
+-to prepare a neatly formatted
+-listing of either its input or its output.
+-The user is presumably capable of the self-discipline required
+-to prepare neat input
+-that reflects his thoughts.
+-It is much more important that the language provide free-form input
+-so he
+-.ul
+-can
+-format it neatly.
+-No one should read the output anyway
+-except in the most dire circumstances.
+-.SH
+-Acknowledgements
+-.PP
+-C. A. R. Hoare
+-once said that
+-``One thing [the language designer] should not do
+-is to include untried ideas of his own.''
+-Ratfor
+-follows this precept very closely _
+-everything in it has been stolen from someone else.
+-Most of the control flow structures
+-are taken directly from the language C[4]
+-developed by Dennis Ritchie;
+-the comment and continuation
+-conventions are adapted from Altran[10].
+-.PP
+-I am grateful to Stuart Feldman,
+-whose patient simulation of an innocent user
+-during the early days of Ratfor
+-led to several design improvements
+-and the eradication of bugs.
+-He also translated the C parse-tables
+-and
+-.UC YACC 
+-parser
+-into Fortran for the
+-first
+-Ratfor
+-version of
+-Ratfor.
+//GO.SYSIN DD m5
+echo m9
+sed 's/.//' >m9 <<'//GO.SYSIN DD m9'
+-.SH
+-References
+-.IP [1]
+-B. G. Ryder,
+-``The PFORT Verifier,''
+-.ul
+-Software_Practice & Experience,
+-October 1974.
+-.IP [2]
+-American National Standard Fortran.
+-American National Standards Institute,
+-New York, 1966.
+-.IP [3]
+-.ul
+-For-word: Fortran Development Newsletter,
+-August 1975.
+-.IP [4]
+-B. W. Kernighan and D. M. Ritchie,
+-.ul
+-The C Programming Language,
+-Prentice-Hall, Inc., 1978.
+-.IP [5]
+-D. M. Ritchie and K. L. Thompson,
+-``The UNIX Time-sharing System.''
+-\fICACM\fP, July 1974.
+-.IP [6]
+-S. C. Johnson,
+-``YACC _ Yet Another Compiler-Compiler.''
+-Bell Laboratories Computing Science Technical Report #32,
+-1978.
+-.IP [7]
+-D. E. Knuth,
+-``Structured Programming with goto Statements.''
+-\fIComputing Surveys\fP, December 1974.
+-.IP [8]
+-B. W. Kernighan and P. J. Plauger,
+-.ul
+-Software Tools,
+-Addison-Wesley, 1976.
+-.IP [9]
+-B. S. Baker,
+-``Struct _ A Program which Structures Fortran'',
+-Bell Laboratories internal memorandum, December 1975.
+-.IP [10]
+-A. D. Hall,
+-``The Altran System for Rational Function Manipulation _
+-A Survey.''
+-\fICACM\fP, August 1971.
+//GO.SYSIN DD m9
+echo m99
+sed 's/.//' >m99 <<'//GO.SYSIN DD m99'
+-.bp
+-.if t .1C
+-.SH
+-Appendix: Usage on
+-.UC UNIX 
+-and
+-.UC GCOS .
+-.PP
+-Beware _
+-local customs vary.
+-Check with a native before going into the jungle.
+-.SH
+-UNIX
+-.PP
+-The program
+-.UL ratfor
+-is the basic translator; it takes either a list
+-of file names or the standard input and writes
+-Fortran on the standard output.
+-Options include
+-.UL \-6x ,
+-which uses
+-.UL x
+-as a continuation character in column 6
+-.UC UNIX "" (
+-uses 
+-.UL & 
+-in column 1),
+-and
+-.UL \-C ,
+-which causes Ratfor comments to be copied into
+-the generated Fortran.
+-.PP
+-The program
+-.UL rc
+-provides an interface to the
+-.UL ratfor
+-command which is much the same as
+-.UL cc .
+-Thus
+-.P1
+-rc [options] files
+-.P2
+-compiles the files specified by
+-.UL files .
+-Files with names ending in
+-.UL \&.r
+-are Ratfor source; other files are assumed to
+-be for the loader.
+-The flags
+-.UL \-C 
+-and
+-.UL \-6x
+-described above are recognized, as are
+-.P1
+--c    compile only; don't load
+--f    save intermediate Fortran .f files
+--r    Ratfor only; implies -c and -f
+--2    use big Fortran compiler (for large programs)
+--U    flag undeclared variables (not universally available)
+-.P2
+-Other flags are passed on to the loader.
+-.SH
+-GCOS
+-.PP
+-The program
+-.UL \&./ratfor
+-is the bare translator, and is identical to the
+-.UC UNIX
+-version, except that the continuation convention
+-is 
+-.UL &
+-in column 6.
+-Thus
+-.P1
+-\&./ratfor  files  >output
+-.P2
+-translates the Ratfor source on
+-.UL files 
+-and
+-collects the generated Fortran on file
+-`output'
+-for subsequent processing.
+-.PP
+-.UL \&./rc
+-provides much the same services as
+-.UL rc 
+-(within the limitations of
+-.UC GCOS ),
+-regrettably with a somewhat different syntax.
+-Options recognized by
+-.UL ./rc
+-include
+-.P1
+-.ta 1.2i
+-name  Ratfor source or library, depending on type
+-h=/name       make TSS H* file (runnable version); run as /name
+-r=/name       update and use random library
+-a=    compile as ascii (default is bcd)
+-C=    copy comments into Fortran
+-f=name        Fortran source file
+-g=name        gmap source file
+-.P2
+-Other options are as specified for the
+-.UL \&./cc
+-command described in [4].
+-.SH
+-TSO, TSS, and other systems
+-.PP
+-Ratfor exists on
+-various other systems;
+-check with the author for specifics.
+//GO.SYSIN DD m99
diff --git a/doc/7thEdMan/vol2/refer.bun b/doc/7thEdMan/vol2/refer.bun
new file mode 100644 (file)
index 0000000..d281293
--- /dev/null
@@ -0,0 +1,2291 @@
+# To unbundle, run this file
+echo pubuse
+sed 's/.//' >pubuse <<'//GO.SYSIN DD pubuse'
+-..... use tbl and troff \-ms
+-.if \nP=0 .IM
+-.TL
+-Updating Publication Lists
+-.AU
+-M. E. Lesk
+-.NH
+-Introduction.
+-.PP
+-.\".if \nP>0 .pn 14
+-This note describes several commands to update the
+-publication lists.
+-The data base consisting of these lists is kept in
+-a set of files in
+-the directory
+-.I /usr/dict/papers
+-on the Version 7
+-.UX
+-system.
+-The reason for having special commands to update these files is
+-that they are indexed, and the only reasonable way to find the
+-items to be updated is to use the index.
+-However, altering the files
+-destroys the usefulness of the index,
+-and makes further editing difficult.
+-So the recommended procedure is to
+-.IP (1)
+-Prepare additions, deletions, and changes in separate files.
+-.IP (2)
+-Update the data base and reindex.
+-.LP
+-Whenever you make changes, etc. it is necessary to run
+-the ``add & index'' step before logging off; otherwise the
+-changes do not take effect.
+-The next section shows the format of the files
+-in the data base.
+-After that, the procedures for
+-preparing additions, preparing changes, preparing deletions,
+-and updating the public data base are given.
+-.NH
+-Publication Format.
+-.PP
+-The format of a data base entry is given completely in ``Some Applications
+-of Inverted Indexes on UNIX'' by M. E. Lesk,
+-the first part of this report,
+-.if \nP=0 (also TM 77-1274-17)
+-and is summarized here via a few examples.
+-In each example, first the output format for an item is shown,
+-and then the corresponding data base entry.
+-.LP
+-.DS
+-.ti 0
+-Journal article:
+-.fi
+-.ll 5i
+-A. V. Aho, D. J. Hirschberg, and J. D. Ullman, ``Bounds
+-on the Complexity of the Maximal Common Subsequence Problem,''
+-.I
+-J. Assoc. Comp. Mach.,
+-.R
+-vol. 23, no. 1, pp. 1-12 (Jan. 1976).
+-.nf
+-.ll
+-.sp
+-%T Bounds on the Complexity of the Maximal Common
+-Subsequence Problem
+-%A A. V. Aho
+-%A D. S. Hirschberg
+-%A J. D. Ullman
+-%J J. Assoc. Comp. Mach.
+-%V 23
+-%N 1
+-%P 1-12
+-%D Jan. 1976
+-.if \nP=0 %M TM 75-1271-7
+-.if \nP>0 %M Memo abcd...
+-.DE
+-.DS
+-.ti 0
+-Conference proceedings:
+-.fi
+-.ll 5i
+-B. Prabhala and R. Sethi, ``Efficient Computation of Expressions with Common
+-Subexpressions,''
+-.I
+-Proc. 5th ACM Symp. on Principles of Programming Languages,
+-.R
+-pp. 222-230, Tucson, Ariz. (January 1978).
+-.nf
+-.ll
+-.sp
+-%A B. Prabhala
+-%A R. Sethi
+-%T Efficient Computation of Expressions with
+-Common Subexpressions
+-%J Proc. 5th ACM Symp. on Principles
+-of Programming Languages
+-%C Tucson, Ariz.
+-%D January 1978
+-%P 222-230
+-.DE
+-.DS
+-.ti 0
+-Book:
+-.fi
+-.ll 5i
+-B. W. Kernighan and P. J. Plauger,
+-.I
+-Software Tools,
+-.R
+-Addison-Wesley, Reading, Mass. (1976).
+-.nf
+-.ll
+-.sp
+-%T Software Tools
+-%A B. W. Kernighan
+-%A P. J. Plauger
+-%I Addison-Wesley
+-%C Reading, Mass.
+-%D 1976
+-.DE
+-.DS
+-.ti 0
+-Article within book:
+-.fi
+-.ll 5i
+-J. W. de Bakker, ``Semantics of Programming Languages,''
+-pp. 173-227 in
+-.I
+-Advances in Information Systems Science, Vol. 2,
+-.R
+-ed. J. T. Tou, Plenum Press, New York, N. Y. (1969).
+-.nf
+-.ll
+-.sp
+-%A J. W. de Bakker
+-%T Semantics of programming languages
+-%E J. T. Tou
+-%B Advances in Information Systems Science, Vol. 2
+-%I Plenum Press
+-%C New York, N. Y.
+-%D 1969
+-%P 173-227
+-.DE
+-.DS
+-.ti 0
+-Technical Report:
+-.fi
+-.ll 5i
+-F. E. Allen, ``Bibliography on Program Optimization,''
+-Report RC-5767, IBM T. J. Watson Research Center,
+-Yorktown Heights, N. Y. (1975).
+-.nf
+-.ll
+-.sp
+-%A F. E. Allen
+-%D 1975
+-%T Bibliography on Program Optimization
+-%R Report RC-5767
+-%I IBM T. J. Watson Research Center
+-%C Yorktown Heights, N. Y.
+-.DE
+-.DS
+-.di xx
+-.ti 0
+-Technical Memorandum:
+-.fi
+-.ll 5i
+-A. V. Aho, B. W. Kernighan and P. J. Weinberg,
+-``AWK \- Pattern Scanning and Processing Language'',
+-TM 77-1271-5, TM 77-1273-12, TM 77-3444-1 (1977).
+-.nf
+-.ll
+-.sp
+-%T AWK \- Pattern Scanning and Processing Language
+-%A A. V. Aho
+-%A B. W. Kernighan
+-%A P. J. Weinberger
+-%M TM 77-1271-5, TM 77-1273-12, TM 77-3444-1
+-%D 1977
+-.di
+-.if \nP=0 .xx
+-.rm xx
+-.DE
+-.LP
+-Other forms of publication can be entered similarly.
+-Note that conference
+-proceedings are entered as if journals,
+-with the conference name on a
+-.I %J
+-line.
+-This is also sometimes appropriate for obscure publications
+-such as series of lecture notes.
+-When something is both a report and an article, or
+-both a memorandum and an article, enter all necessary information
+-for both; see the first article above, for example.
+-Extra information (such as ``In preparation'' or ``Japanese translation'')
+-should be placed on a line beginning
+-.I %O .
+-The most common use of %O lines now is for ``Also in ...'' to give
+-an additional reference to a secondary appearance of the same paper.
+-.PP
+-Some of the possible fields of a citation are:
+-.TS
+-c c 5 c c
+-a l   a l .
+-Letter        Meaning Letter  Meaning
+-A     Author  K       Extra keys
+-B     Book including item     N       Issue number
+-C     City of publication     O       Other
+-D     Date    P       Page numbers
+-E     Editor of book  R       Report number
+-I     Publisher (issuer)      T       Title of item
+-J     Journal name    V       Volume number
+-.TE
+-Note that
+-.I %B
+-is used to indicate the title
+-of a book containing the article being entered;
+-when an item is an entire book, the title should
+-be entered with a
+-.I %T
+-as usual.
+-.PP
+-Normally, the order of items does not matter.  The only exception is
+-that if there are multiple authors (%A lines) the order of authors
+-should be that on the paper.
+-If a line is too long, it may be continued on to the next line;
+-any line not beginning with % or . (dot) is assumed to be
+-a continuation of the previous line.
+-Again, see the first article above for an example of a long title.
+-Except for authors, do not repeat any items; if two %J lines are
+-given, for example, the first is ignored.
+-Multiple items on the same file should be separated by blank lines.
+-.PP
+-Note that in formatted printouts of the file, the
+-exact appearance of the items is determined by
+-a set of macros and the formatting programs.
+-Do not try to adjust fonts, punctuation, etc. by editing
+-the data base; it is wasted effort.  In case someone has
+-a real need for a differently-formatted output, a new set
+-of macros can easily be generated to provide alternative
+-appearances of the citations.
+-.NH
+-Updating and Re-indexing.
+-.PP
+-This section describes the commands that are used to manipulate
+-and change the data base.
+-It explains the procedures for (a) finding references in the data base,
+-(b) adding new references, (c) changing existing references, and (d)
+-deleting references.
+-Remember that all changes, additions, and deletions are done by preparing
+-separate files and then running an `update and reindex' step.
+-.PP
+-.I
+-Checking what's there now.
+-.R
+-Often you will want to know what is currently in the data base.
+-There is a special command
+-.I lookbib
+-to look for things and print them
+-out.
+-It searches for articles based on words in the title, or the author's name,
+-or the date.
+-For example, you could find the first paper above with
+-.DS
+-lookbib aho ullman maximal subsequence 1976
+-.DE
+-or
+-.DS
+-lookbib aho ullman hirschberg
+-.DE
+-.LP
+-If you don't give enough words, several items will be found;
+-if you spell some wrong, nothing will be found.
+-There are around 4300 papers in the public file; you should
+-always use this command to check when you are not sure
+-whether a certain paper is there or not.
+-.PP
+-.I
+-Additions.
+-.R
+-To add new papers, just type in, on one or more files, the citations
+-for the new papers.
+-Remember to check first if the papers are already in the data base.
+-For example, if a paper has a previous memo version, this should
+-be treated as a change to an existing entry, rather than
+-a new entry.
+-If several new papers are being typed on the same file, be
+-sure that there is a blank line between each two papers.
+-.PP
+-.I
+-Changes.
+-.R
+-To change an item, it should be extracted onto a file.
+-This is done with the command
+-.DS
+-pub.chg key1 key2 key3 ...
+-.DE
+-where the items key1, key2, key3, etc. are
+-a set of keys that will find the paper,
+-as in the
+-.I lookbib
+-command.
+-That is, if
+-.DS
+-lookbib johnson yacc cstr
+-.DE
+-will find a item (to, in this case, Computing Science Technical Report
+-No. 32, ``YACC: Yet Another Compiler-Compiler,''
+-by S. C. Johnson)
+-then
+-.DS
+-pub.chg johnson yacc cstr
+-.DE
+-will permit you to edit the item.
+-The
+-.I pub.chg
+-command
+-extracts the item onto a file named ``bibxxx'' where ``xxx''
+-is a 3-digit number, e.g. ``bib234''.
+-The command will print the file name it has chosen.
+-If the set of keys finds more than one paper (or no papers) an
+-error message is printed and no file is written.
+-Each reference to be changed must be extracted with a separate
+-.I pub.chg
+-command, and each will be placed on a separate file.
+-You should then edit the ``bibxxx'' file as desired to change the item,
+-using the UNIX editor.
+-Do not delete or change the first line of the file, however, which begins
+-.I %#
+-and is a special code line to tell the update program
+-which item is being altered.
+-You may delete or change other lines, or add lines, as you wish.
+-The changes are not actually made in the public data
+-base until you run the update command
+-.I pub.run
+-(see below).
+-Thus, if after extracting an item and modifying it, you decide
+-that you'd rather leave things as they were, delete the
+-``bibxxx'' file, and your change request will disappear.
+-.PP
+-.I
+-Deletions.
+-.R
+-To delete an entry from the data base,
+-type the command
+-.DS
+-pub.del key1 key2 key3 ...
+-.DE
+-where the items key1, key2, etc. are a set
+-of keys that will find the paper, as with the
+-.I lookbib
+-command.
+-That is, if
+-.DS
+-lookbib aho hirschberg ullman
+-.DE
+-will find a paper,
+-.DS
+-pub.del aho hirschberg ullman
+-.DE
+-deletes it.
+-Upper and lower case are equivalent in keys;
+-the command
+-.DS
+-pub.del Aho Hirschberg Ullman
+-.DE
+-is an equivalent
+-.I pub.del
+-command.
+-The
+-.I pub.del
+-command will print the entry being deleted.
+-It also gives the name of a ``bibxxx'' file on which the deletion
+-command is stored.
+-The actual deletion is not done until the changes, additions, etc.
+-are processed, as with the
+-.I pub.chg
+-command.
+-If, after seeing the item to be deleted, you change your
+-mind about throwing it away, delete the ``bibxxx'' file
+-and the delete request disappears.
+-Again, if the list of keys does not uniquely identify one paper,
+-an error message is given.
+-.PP
+-Remember that the default versions of the commands described here
+-edit a public data base.
+-Do not delete
+-items unless you are sure deletion is proper; usually this
+-means that there are duplicate entries for the same paper.
+-Otherwise, view requests for deletion with skepticism; even
+-if one person has no need for a particular item in the data base,
+-someone else may want it there.
+-.PP
+-If an item is correct, but should not appear in the ``List of Publications''
+-as normally produced, add the line
+-.DS
+-%K DNL
+-.DE
+-to the item.
+-This preserves the item intact, but implies ``Do Not List'' to the
+-to the commands that print publication lists.
+-The DNL line is normally used for some technical reports,
+-minor memoranda, or other
+-low-grade publications.
+-.PP
+-.I
+-Update and reindex.
+-.R
+-When you have completed a session of changes, you should
+-type the command
+-.DS
+-pub.run file1 file2 ...
+-.DE
+-where the names ``file1'', ... are the new files of additions you
+-have prepared.
+-You need not list the ``bibxxx'' files representing changes and
+-deletions; they are processed automatically.
+-All of the new items are edited into the standard
+-public data base, and then a new index is made.  This process
+-takes about one minute of processor time.
+-The index is not made by re-analyzing and re-sorting the
+-entire data base; the new or changed items are indexed
+-in the usual way and then merged with the previous data files.
+-A complete re-index would be much slower for small changes.
+-.PP
+-Normally, you should execute
+-.I pub.run
+-just before you logoff after performing
+-some edit requests.
+-However, if you don't, the various change request files remain
+-in your directory
+-until you finally do execute
+-.I pub.run.
+-When the changes are processed, the ``bibxxx'' files are deleted.
+-It is not desirable to wait too long before processing changes,
+-however, to avoid conflicts with someone else who wishes to change
+-the same file.
+-If executing
+-.I pub.run
+-produces the message ``File bibxxx too old''
+-it means that someone else has been editing the same file
+-between the time you prepared your changes, and the time you typed
+-.I pub.run.
+-You must delete such old change files and
+-re-enter them.
+-.PP
+-Note that although
+-.I pub.run
+-discards the ``bibxxx'' files after
+-processing them, your files of additions are left around
+-even after
+-.I pub.run
+-is finished.
+-If they were typed in only for purposes of
+-updating the data base, you may delete them
+-after they have been processed by
+-.I pub.run.
+-.PP
+-.I
+-Example.
+-.R
+-Suppose, for example, that you wish to
+-.IP (1)
+-Add to the data base the memos ``The Dilogarithm Function of a Real Argument''
+-by R. Morris, and
+-``UNIX Software Distribution by Communication Link,''
+-by M. E. Lesk and A. S. Cohen;
+-.IP (2)
+-Delete from the data base the item
+-``Cheap Typesetters'', by M. E. Lesk,
+-SIGLASH Newsletter, 1973;
+-and
+-.IP (3)
+-Change ``J. Assoc. Comp. Mach.'' to ``Jour. ACM'' in the citation
+-for Aho, Hirschberg, and Ullman shown above.
+-.LP
+-The procedure would be as follows.
+-First, you would make a file
+-containing the additions,
+-here called ``new.1'', in the normal way using the UNIX editor.
+-In the script shown below, the computer prompts are
+-.if n underlined.
+-.if t in italics.
+-.DS
+-.if n _\b$ ed new.1
+-.if t \f2$\f1 ed new.1
+-.if n _\b?
+-.if t \f2?\f1
+-a
+-%T The Dilogarithm Function of a Real Argument
+-%A Robert Morris
+-.if \nP=0 %M TM 78-1271-1
+-.if \nP>0 %M abcd
+-%D 1978
+-
+-%T UNIX Software Distribution by Communication Link
+-%A M. E. Lesk
+-%A A. S. Cohen
+-.if \nP=0 %M TM 78-1274-1, 78-8234-1
+-.if \nP>0 %M abcd
+-%D 1978
+-.
+-w new.1
+-.if n _\b1_\b9_\b9
+-.if t \f2199\f1
+-q
+-.DE
+-Next you would specify the deletion, which would be done with the
+-.I pub.del
+-command:
+-.DS
+-.if n _\b$ pub.del lesk cheap typesetters siglash
+-.if t \f2$\f1 pub.del lesk cheap typesetters siglash
+-.ti 0
+-to which the computer responds:
+-
+-.if n W\b_i\b_l\b_l\b_ d\b_e\b_l\b_e\b_t\b_e\b_:\b_  (\b_f\b_i\b_l\b_e\b_ b\b_i\b_b\b_1\b_7\b_6\b_)\b_
+-.if t \f2Will delete:  (file bib176)\f1
+-
+-.if n %\b_T\b_ C\b_h\b_e\b_a\b_p\b_ T\b_y\b_p\b_e\b_s\b_e\b_t\b_t\b_e\b_r\b_s\b_
+-.if t \f2%T Cheap Typesetters\f1
+-.if n %\b_A\b_ M\b_.\b_ E\b_.\b_ L\b_e\b_s\b_k\b_
+-.if t \f2%A M. E. Lesk\f1
+-.if n %\b_J\b_ A\b_C\b_M\b_ S\b_I\b_G\b_L\b_A\b_S\b_H\b_ N\b_e\b_w\b_s\b_l\b_e\b_t\b_t\b_e\b_r\b_
+-.if t \f2%J ACM SIGLASH Newsletter\f1
+-.if n %\b_V\b_ 6\b_
+-.if t \f2%V 6\f1
+-.if n %\b_N\b_ 4\b_
+-.if t \f2%N 4\f1
+-.if n %\b_P\b_ 1\b_4\b_-\b_1\b_6\b_
+-.if t \f2%P 14-16\f1
+-.if n %\b_D\b_ O\b_c\b_t\b_o\b_b\b_e\b_r\b_ 1\b_9\b_7\b_3\b_
+-.if t \f2%D October 1973\f1
+-.DE
+-And then you would extract the Aho, Hirschberg and Ullman paper.
+-The dialogue involved is shown below.
+-First run
+-.I pub.chg
+-to extract the paper; it responds by printing
+-the citation and informing you that it was placed on file \f2bib123\f1.
+-That file is then edited.
+-.DS
+-.if n _\b$ pub.chg aho hirschberg ullman
+-.if t \f2$\f1 pub.chg aho hirschberg ullman
+-.if n _\bE_\bx_\bt_\br_\ba_\bc_\bt_\bi_\bn_\bg _\ba_\bs _\bf_\bi_\bl_\be _\bb_\bi_\bb_\b1_\b2_\b3
+-.if t \f2Extracting as file bib123\f1
+-.if n _\b%_\bT _\bB_\bo_\bu_\bn_\bd_\bs _\bo_\bn _\bt_\bh_\be _\bC_\bo_\bm_\bp_\bl_\be_\bx_\bi_\bt_\by _\bo_\bf _\bt_\bh_\be _\bM_\ba_\bx_\bi_\bm_\ba_\bl
+-.if t \f2%T Bounds on the Complexity of the Maximal\f1
+-.if n _\bC_\bo_\bm_\bm_\bo_\bn _\bS_\bu_\bb_\bs_\be_\bq_\bu_\be_\bn_\bc_\be _\bP_\br_\bo_\bb_\bl_\be_\bm
+-.if t \f2Common Subsequence Problem\f1
+-.if n _\b%_\bA _\bA_\b. _\bV_\b. _\bA_\bh_\bo
+-.if t \f2%A A. V. Aho\f1
+-.if n _\b%_\bA _\bD_\b. _\bS_\b. _\bH_\bi_\br_\bs_\bc_\bh_\bb_\be_\br_\bg
+-.if t \f2%A D. S. Hirschberg\f1
+-.if n _\b%_\bA _\bJ_\b. _\bD_\b. _\bU_\bl_\bl_\bm_\ba_\bn
+-.if t \f2%A J. D. Ullman\f1
+-.if n _\b%_\bJ _\bJ_\b. _\bA_\bs_\bs_\bo_\bc_\b. _\bC_\bo_\bm_\bp_\b. _\bM_\ba_\bc_\bh_\b.
+-.if t \f2%J J. Assoc. Comp. Mach.\f1
+-.if n _\b%_\bV _\b2_\b3
+-.if t \f2%V 23\f1
+-.if n _\b%_\bN _\b1
+-.if t \f2%N 1\f1
+-.if n _\b%_\bP _\b1_\b-_\b1_\b2
+-.if t \f2%P 1-12\f1
+-.if \nP=0 .if n _\b%_\bM _\bT_\bM _\b7_\b5_\b-_\b1_\b2_\b7_\b1_\b-_\b7
+-.if \nP>0 .if n %\b_M\b_ M\b_e\b_m\b_o\b_ n\b_u\b_m\b_b\b_e\b_r\b_
+-.if \nP=0 .if t \f2%M TM 75-1271-7\f1
+-.if \nP>0 .if t \f2%M abcd\f1
+-.if n _\b%_\bD _\bJ_\ba_\bn_\b. _\b1_\b9_\b7_\b6
+-.if t \f2%D Jan. 1976\f1
+-
+-.if n _\b$ ed bib123
+-.if t \f2$\f1 ed bib123
+-.if n _\b3_\b1_\b2
+-.if t \f2312\f1
+-/Assoc/s/ J/ Jour/p
+-.if n _\b%_\bJ _\bJ_\bo_\bu_\br_\b. _\bA_\bs_\bs_\bo_\bc_\b. _\bC_\bo_\bm_\bp_\b. _\bM_\ba_\bc_\bh_\b.
+-.if t \f2%J Jour. Assoc. Comp. Mach.\f1
+-s/Assoc.*/ACM/p
+-.if n _\b%_\bJ _\bJ_\bo_\bu_\br_\b. _\bA_\bC_\bM
+-.if t \f2%J Jour. ACM\f1
+-1,$p
+-.if n _\b%_\b# _\b/_\bu_\bs_\br_\b/_\bd_\bi_\bc_\bt_\b/_\bp_\ba_\bp_\be_\br_\bs_\b/_\bp_\b7_\b6 _\b2_\b3_\b3 _\b2_\b4_\b5 _\bc_\bh_\ba_\bn_\bg_\be
+-.if t \f2%# /usr/dict/papers/p76 233 245 change\f1
+-.if n _\b%_\bT _\bB_\bo_\bu_\bn_\bd_\bs _\bo_\bn _\bt_\bh_\be _\bC_\bo_\bm_\bp_\bl_\be_\bx_\bi_\bt_\by _\bo_\bf _\bt_\bh_\be _\bM_\ba_\bx_\bi_\bm_\ba_\bl
+-.if t \f2%T Bounds on the Complexity of the Maximal\f1
+-.if n _\bC_\bo_\bm_\bm_\bo_\bn _\bS_\bu_\bb_\bs_\be_\bq_\bu_\be_\bn_\bc_\be _\bP_\br_\bo_\bb_\bl_\be_\bm
+-.if t \f2Common Subsequence Problem\f1
+-.if n _\b%_\bA _\bA_\b. _\bV_\b. _\bA_\bh_\bo
+-.if t \f2%A A. V. Aho\f1
+-.if n _\b%_\bA _\bD_\b. _\bS_\b. _\bH_\bi_\br_\bs_\bc_\bh_\bb_\be_\br_\bg
+-.if t \f2%A D. S. Hirschberg\f1
+-.if n _\b%_\bA _\bJ_\b. _\bD_\b. _\bU_\bl_\bl_\bm_\ba_\bn
+-.if t \f2%A J. D. Ullman\f1
+-.if n _\b%_\bJ _\bJ_\bo_\bu_\br_\b. _\bA_\bC_\bM
+-.if t \f2%J Jour. ACM\f1
+-.if n _\b%_\bV _\b2_\b3
+-.if t \f2%V 23\f1
+-.if n _\b%_\bN _\b1
+-.if t \f2%N 1\f1
+-.if n _\b%_\bP _\b1_\b-_\b1_\b2
+-.if t \f2%P 1-12\f1
+-.if \nP=0 .if n _\b%_\bM _\bT_\bM _\b7_\b5_\b-_\b1_\b2_\b7_\b1_\b-_\b7
+-.if \nP>0 .if n _\b%_\bM _\bM_\be_\bm_\bo _\bn_\bu_\bm_\bb_\be_\br
+-.if \nP=0 .if t \f2%M TM 75-1271-7\f1
+-.if \nP>0 .if t \f2%M abcd\f1
+-.if n _\b%_\bD _\bJ_\ba_\bn_\b. _\b1_\b9_\b7_\b6
+-.if t \f2%D Jan. 1976\f1
+-
+-w
+-.if n _\b2_\b9_\b2
+-.if t \f2292\f1
+-q
+-.if n _\b$
+-.if t \f2$\f1
+-.DE
+-Finally, execute
+-.I pub.run ,
+-making sure to remember that you
+-have prepared a new file ``new.1'':
+-.DS
+-\f2$\f1 pub.run new.1
+-.DE
+-Currently, this takes about 1 minute of 11/70 processor time.
+-.NH
+-Printing a Publication List
+-.PP
+-There are two commands for printing a publication list,
+-depending on whether you want to print one person's list,
+-or the list of many people.
+-To print a list for one person, use the
+-.I pub.indiv
+-command:
+-.DS
+-pub.indiv M Lesk
+-.DE
+-This runs off the list for M. Lesk and puts it in file ``output''.
+-Note that no `.' is given after the initial.
+-In case of ambiguity two initials can be used.
+-Similarly, to get the list for group of people, say
+-.DS
+-pub.org xxx
+-.DE
+-which prints all the publications of the members of organization
+-.I xxx ,
+-taking the names for the list in the file
+-.I /usr/dict/papers/centlist/xxx .
+-This command should normally be run in the background; it takes
+-perhaps 15 minutes.
+-Two options are available with these commands:
+-.DS
+-pub.indiv \-p M Lesk
+-.DE
+-prints only the papers, leaving out unpublished notes, patents, etc.
+-Also
+-.DS
+-pub.indiv \-t M Lesk | gcat
+-.DE
+-prints a typeset copy, instead of a computer printer copy.
+-In this case it has been directed to an alternate typesetter with the
+-`gcat' command.
+-These options may be used together, and may be used with the
+-.I pub.org
+-command as well.
+-For example, to print
+-only the papers for all of organization zzz and typeset them,
+-you could type
+-.DS
+-pub.center \-t \-p zzz | gcat &
+-.DE
+-These publication lists are printed double column with a citation style
+-taken from a set of publication list macros; the macros, of course, can be
+-changed easily to adjust the format of the lists.
+//GO.SYSIN DD pubuse
+echo refer
+sed 's/.//' >refer <<'//GO.SYSIN DD refer'
+-.... refer | tbl | nroff -ms
+-.de UC
+-\\s-2\\$1\\s0\\$2
+-..
+-.ds . \&\s+2.\s0
+-.if t .ds -- \(em
+-.if n .ds -- --
+-.TR 69
+-.TM 77-1274-17 39199 39199-11
+-.ND October 27, 1977
+-.ND June 21, 1978
+-.TL
+-Some Applications of Inverted Indexes on the UNIX System
+-.AU "MH 2C-572" 6377
+-M. E. Lesk
+-.AI
+-.MH
+-.AB
+-.LP
+-.ft B
+-I. Some Applications of Inverted Indexes \- Overview
+-.ft R
+-.PP
+-This memorandum describes a set of programs which
+-make inverted indexes to
+-UNIX*
+-text files, and their
+-application to
+-retrieving and formatting citations for documents prepared using
+-.I troff.
+-.PP
+-These indexing and searching programs make keyword
+-indexes to volumes of material too large for linear searching.
+-Searches for combinations of single words can be performed quickly.
+-The programs are divided into
+-two phases.  The first makes an index from the original
+-data; the second searches the index and retrieves
+-items.
+-Both of these phases are further divided into two parts
+-to separate the data-dependent and algorithm dependent
+-code.
+-.PP
+-The major current application of these programs is
+-the
+-.I troff
+-preprocessor
+-.I refer.
+-A list of 4300 references is maintained on line,
+-containing primarily papers written and cited by
+-local authors.
+-Whenever one of these references is required
+-in a paper, a few words from the title or author list
+-will retrieve it, and the user need not bother to re-enter
+-the exact citation.
+-Alternatively, authors can use their own lists of papers.
+-.PP
+-This memorandum is of interest to
+-those who are interested in facilities for searching large
+-but relatively unchanging text files on
+-the
+-UNIX
+-system,
+-and those who are interested in handling bibliographic
+-citations with
+-UNIX
+-.I troff.
+-.LP
+-.ft B
+-II. Updating Publication Lists
+-.PP
+-This section is a brief note describing the
+-auxiliary programs for managing the updating
+-processing.
+-It is written to aid clerical users in
+-maintaining lists of references.
+-Primarily, the programs described permit a large
+-amount of individual control over the content
+-of publication lists while retaining the
+-usefulness of the files to other users.
+-.LP
+-.ft B
+-III. Manual Pages
+-.PP
+-This section contains the pages from the
+-UNIX programmer's manual
+-for the
+-.I lookall,
+-.I pubindex,
+-and
+-.I refer
+-commands.
+-It is useful for reference.
+-.sp
+-\l'3i'
+-.br
+-* UNIX is a Trademark of Bell Laboratories.
+-.AE
+-.CS 10 4 14 0 0 4
+-.NH
+-Introduction.
+-.PP
+-The
+-.UX
+-system
+-has many utilities
+-(e.g. \fIgrep, awk, lex, egrep, fgrep, ...\fR)
+-to search through files of text,
+-but most of them are based on a linear scan through the
+-entire file, using some deterministic automaton.
+-.ev 1
+-.ps 8
+-.vs 10p
+-.ev
+-This memorandum discusses a program which uses inverted
+-indexes
+-.[
+-%A D. Knuth
+-%T The Art of Computer Programming: Vol. 3, Sorting and Searching
+-%I Addison-Wesley
+-%C Reading, Mass.
+-%D 1977
+-%O See section 6.5.
+-.]
+-and can thus be used on much larger data bases.
+-.PP
+-As with any indexing system, of course, there are some disadvantages;
+-once an index is made, the files that have been indexed can not be changed
+-without remaking the index.
+-Thus applications are restricted
+-to those making many searches
+-of relatively stable data.
+-Furthermore, these programs depend on hashing, and can only
+-search for exact matches of whole keywords.
+-It is not possible to look for
+-arithmetic or logical expressions (e.g. ``date greater than 1970'') or
+-for regular expression searching such as that in
+-.I lex.
+-.[
+-lex lesk cstr
+-.]
+-.PP
+-Currently there are two uses of this software,
+-the
+-.I refer
+-preprocessor to format references,
+-and the
+-.I lookall
+-command to search through all text files on
+-the
+-.UX
+-system.
+-.PP
+-The remaining sections of this memorandum discuss
+-the searching programs and their uses.
+-Section 2 explains the operation of the searching algorithm and describes
+-the data collected for use with the
+-.I lookall
+-command.
+-The more important application,
+-.I refer
+-has a user's description in section 3.
+-Section 4 goes into more detail on
+-reference files
+-for the benefit of those who
+-wish to add references to data bases or
+-write new
+-.I troff
+-macros for use with
+-.I refer.
+-The options to make
+-.I refer
+-collect identical citations, or otherwise relocate and adjust references,
+-are described in section 5.
+-The
+-.UX
+-manual sections for
+-.I "refer, lookall,"
+-and associated commands are attached as appendices.
+-.NH
+-Searching.
+-.PP
+-The indexing and searching process is divided into two phases,
+-each made of two parts.
+-These are
+-shown below.
+-.IP A.
+-Construct the index.
+-.RS
+-.IP (1)
+-Find keys \*(-- turn the input files into a sequence of tags and keys,
+-where each tag identifies a distinct item in the input
+-and the keys for each such item are the strings under which it is
+-to be indexed.
+-.IP (2)
+-Hash and sort \*(--
+-prepare a set of inverted indexes from which, given a set of keys,
+-the appropriate item tags can be found quickly.
+-.RE
+-.IP B.
+-Retrieve an item in response to a query.
+-.RS
+-.IP (3)
+-Search \*(--
+-Given some keys, look through the files prepared by the hashing
+-and sorting facility and derive the appropriate tags.
+-.IP (4)
+-Deliver \*(--
+-Given the tags, find the original items.  This completes the
+-searching process.
+-.RE
+-.LP
+-The first phase, making the index, is presumably done relatively infrequently.
+-It should, of course, be done whenever the data being
+-indexed change.
+-In contrast, the second phase, retrieving items,
+-is presumably done often, and must be rapid.
+-.PP
+-An effort is made to separate code which depends on the data
+-being handled from code which depends on the searching procedure.
+-The search algorithm is involved only in steps
+-(2) and (3), while knowledge of the actual data files is
+-needed only by steps (1) and (4).
+-Thus it is easy to adapt to different data files or different
+-search algorithms.
+-.PP
+-To start with, it is necessary to have some way of selecting
+-or generating keys from input files.
+-For dealing with files that are basically English, we have
+-a key-making program which automatically selects words
+-and passes them to the hashing and sorting program (step 2).
+-The format used has one line for each input item,
+-arranged
+-as follows:
+-.DS
+-name:start,length (tab) key1 key2 key3 ...
+-.DE
+-where
+-.I name
+-is the file name,
+-.I start
+-is the starting byte number,
+-and
+-.I length
+-is the number of bytes in the entry.
+-.PP
+-These lines are the only input used to make the
+-index.
+-The first field (the file name, byte position, and byte count)
+-is the tag of the item
+-and can be used to retrieve it quickly.
+-Normally, an item is either a whole file or a section of a file
+-delimited by blank lines.
+-After the tab, the second field contains the keys.
+-The keys, if selected by the automatic program, are
+-any alphanumeric strings which
+-are not among the 100 most frequent words in English
+-and which are not entirely numeric (except for four-digit
+-numbers beginning 19, which are accepted as dates).
+-Keys are truncated to six characters and converted to lower case.
+-Some selection is needed if the original items are very large.
+-We normally just take the first
+-.I n
+-keys, with
+-.I n
+-less than 100 or so; this replaces any attempt at intelligent selection.
+-One file in our system is
+-a complete English dictionary; it would presumably be retrieved for all queries.
+-.PP
+-To generate an inverted index to the list of record tags and keys,
+-the keys
+-are hashed
+-and sorted to produce an index.
+-What is wanted, ideally, is a series of lists showing the tags associated
+-with each key.
+-To condense this,
+-what is actually produced is a list showing the tags associated
+-with each hash code, and thus with some set of keys.
+-To speed up access and further save space,
+-a set of three or possibly four files is produced.
+-These files are:
+-.KS
+-.bd 2 2
+-.TS
+-center;
+-c c
+-lI l.
+-File  Contents
+-entry Pointers to posting file
+-      for each hash code
+-posting       Lists of tag pointers for
+-      each hash code
+-tag   Tags for each item
+-key   Keys for each item
+-      (optional)
+-.TE
+-.bd 2
+-.KE
+-The posting file comprises the real data: it contains a sequence of lists
+-of items posted under each hash code.  To speed up searching,
+-the entry file is an array of pointers into the posting file, one per potential
+-hash code.
+-Furthermore, the items in the lists in the posting file are not referred to by their
+-complete tag, but just by an address in the tag file, which
+-gives the complete tags.
+-The key file is optional and contains a copy of the keys
+-used in the indexing.
+-.PP
+-The searching process starts with a query, containing several keys.
+-The goal is to obtain all items which were indexed under these keys.
+-The query keys are hashed, and the pointers in the entry file used
+-to access the lists in the posting file.  These lists
+-are addresses in the tag file of documents posted under the
+-hash codes derived from the query.
+-The common items from all lists are determined;
+-this must include the items indexed by every key, but may also
+-contain some items which are false drops, since items referenced by
+-the correct hash codes need not actually have contained the correct keys.
+-Normally, if there are several keys in the query, there are not
+-likely to be many false drops in the final combined list even though
+-each hash code is somewhat ambiguous.
+-The actual tags are then obtained from the tag file, and to guard against
+-the possibility that an item has false-dropped on some hash code
+-in the query, the original items are normally obtained from the delivery
+-program (4) and the query keys checked against them
+-by string comparison.
+-.PP
+-Usually, therefore, the check for bad drops is made against the original file.
+-However, if the key derivation procedure is complex, it may be preferable
+-to check against the keys fed to program (2).
+-In this case the optional key file which contains the
+-keys associated with each item is generated, and the item tag is supplemented
+-by a string
+-.DS
+-;start,length
+-.DE
+-which indicates the starting byte number in the key file and the length of
+-the string of keys for each item.
+-This file is not usually necessary with the present
+-key-selection program, since the keys
+-always appear in the original document.
+-.PP
+-There is also an option
+-(\f3-C\f2n\|\f1)
+-for coordination level searching.
+-This retrieves items which match all but
+-.I n
+-of the query keys.
+-The items are retrieved in the order of the number
+-of keys that they match.
+-Of course,
+-.I n
+-must be less than the number of query keys (nothing is
+-retrieved unless it matches at least one key).
+-.PP
+-As an example, consider one set of 4377 references, comprising
+-660,000 bytes.
+-This included 51,000 keys, of which 5,900 were distinct
+-keys.
+-The hash table is kept full to save space (at the expense of time);
+-995 of 997 possible hash codes were used.
+-The total set of index files (no key file) included 171,000 bytes,
+-about 26% of the original file size.
+-It took 8 minutes of processor time to
+-hash, sort, and write the index.
+-To search for a single query with the resulting index took 1.9 seconds
+-of processor time,
+-while to find the same paper
+-with a sequential linear search
+-using
+-.I grep
+-(reading all of the tags and keys)
+-took 12.3 seconds of processor time.
+-.PP
+-We have also used this software to index all of the English stored on our
+-.UX
+-system.
+-This is the index searched by the
+-.I lookall
+-command.
+-On a typical day there were
+-29,000 files in our user file system, containing about 152,000,000
+-bytes.
+-Of these
+-5,300 files, containing 32,000,000 bytes (about 21%)
+-were English text.
+-The total number of `words' (determined mechanically)
+-was 5,100,000.
+-Of these 227,000 were selected as keys;
+-19,000 were distinct, hashing to 4,900 (of 5,000 possible) different hash codes.
+-The
+-resulting inverted file indexes used 845,000 bytes, or about
+-2.6% of the size of the original files.
+-The particularly small indexes are caused by the
+-fact that keys are taken from only the first 50 non-common words of
+-some very long input files.
+-.PP
+-Even this large \f2lookall\f1 index can be searched quickly.
+-For example, to find this document
+-by looking for the keys
+-``lesk inverted indexes''
+-required
+-1.7 seconds of processor time
+-and system time.
+-By comparison, just to search the 800,000 byte dictionary (smaller than even
+-the inverted indexes, let alone the 32,000,000 bytes of text files) with
+-.I grep
+-takes 29 seconds of processor time.
+-The
+-.I lookall
+-program is thus useful when looking for a document which you believe
+-is stored on-line, but do not know where.  For example, many memos
+-from the Computing Science Research Center are in its
+-.UX
+-file system, but
+-it is often
+-difficult to guess where a particular memo might be (it might have several
+-authors, each with many directories, and have been worked on by
+-a secretary with yet more directories).
+-Instructions for the use of the
+-.I lookall
+-command are given in the manual section, shown
+-in the appendix to this memorandum.
+-.PP
+-The only indexes maintained routinely are those of publication lists and
+-all English files.
+-To make other indexes, the programs for making keys, sorting them,
+-searching the indexes, and delivering answers must be used.
+-Since they are usually invoked as parts of higher-level commands,
+-they are not in the default command
+-directory, but are available to any user in the directory
+-.I /usr/lib/refer .
+-Three programs are of interest:
+-.I mkey ,
+-which isolates keys from input files;
+-.I inv ,
+-which makes an index from a set of keys;
+-and
+-.I hunt ,
+-which searches the index and delivers the items.
+-Note that the two parts of the retrieval phase are combined into
+-one program, to avoid the excessive system work and delay which
+-would result from running these as separate processes.
+-.PP
+-These three commands have a large number of options to adapt to different
+-kinds of input.
+-The user not interested in the detailed description that now follows may
+-skip to section 3, which describes the
+-.I refer
+-program, a packaged-up version of these tools specifically
+-oriented towards formatting references.
+-.PP
+-.B
+-Make Keys.
+-.R
+-The program
+-.I mkey
+-is the key-making program corresponding to step (1) in phase A.
+-Normally, it reads its input from the file names given as arguments,
+-and if there are no arguments it reads from the standard input.
+-It assumes that blank lines in the input delimit
+-separate items, for each of which a different line of
+-keys should be generated.
+-The lines of keys are written on the standard output.
+-Keys are any alphanumeric string in the input not
+-among the most frequent words in English and not entirely numeric
+-(except that all-numeric strings are acceptable if they
+-are between 1900 and 1999).
+-In the output, keys are translated to lower case, and truncated
+-to six characters in length; any associated punctuation is removed.
+-The following flag arguments are recognized by
+-.I mkey:
+-.TS
+-center;
+-lB lw(4i).
+-\-c \f2name   T{
+-Name of file of common words;
+-default is
+-.I /usr/lib/eign.
+-T}
+-\-f \f2name   T{
+-Read a list of files from
+-.I name
+-and take each as an input argument.
+-T}
+-\-i \f2chars  T{
+-Ignore all lines which begin with `%' followed by any character
+-in
+-.I chars .
+-T}
+-\-k\f2n       T{
+-Use at most
+-.I n
+-keys per input item.
+-T}
+-\-l\f2n       T{
+-Ignore items shorter than
+-.I n
+-letters long.
+-T}
+-\-n\f2m       T{
+-Ignore as a key any word in the first
+-.I m
+-words of the list of common English words.
+-The default is 100.
+-T}
+-\-s   T{
+-Remove the labels
+-.I (file:start,length)
+-from the output; just give the keys.
+-Used when searching rather than indexing.
+-T}
+-\-w   T{
+-Each whole file is a separate item;
+-blank lines in files are irrelevant.
+-T}
+-.TE
+-.PP
+-The normal arguments for indexing references are
+-the defaults, which are
+-.I "\-c /usr/lib/eign" ,
+-.I \-n100 ,
+-and
+-.I \-l3 .
+-For searching, the
+-.I \-s
+-option is also needed.
+-When the big
+-.I lookall
+-index of all English files is run,
+-the options are
+-.I \-w ,
+-.I \-k50 ,
+-and
+-.I "\-f (filelist)" .
+-When running on textual input,
+-the
+-.I mkey
+-program processes about 1000 English words per processor second.
+-Unless the
+-.I \-k
+-option is used (and the input files are long enough for
+-it to take effect)
+-the output of
+-.I mkey 
+-is comparable in size to its input.
+-.PP
+-.B
+-Hash and invert.
+-.R
+-The
+-.I inv
+-program computes the hash codes and writes
+-the inverted files.
+-It reads the output of
+-.I mkey
+-and writes the set of files described earlier
+-in this section.
+-It expects one argument, which is used as the base name for
+-the three (or four) files to be written.
+-Assuming an argument of
+-.I Index
+-(the default)
+-the entry file is named
+-.I Index.ia ,
+-the posting file
+-.I Index.ib ,
+-the tag file
+-.I Index.ic ,
+-and the key file (if present)
+-.I Index.id .
+-The
+-.I inv
+-program recognizes the following options:
+-.TS
+-center;
+-lB lw(4i).
+-\-a   T{
+-Append the new keys to a previous set of inverted files,
+-making new files if there is no old set using the same base name.
+-T}
+-\-d   T{
+-Write the optional key file.
+-This is needed when you can not check for false drops by looking
+-for the keys in the original inputs, i.e. when the key derivation
+-procedure is complicated and
+-the output keys are not words from the input files.
+-T}
+-\-h\f2n       T{
+-The hash table size is
+-.I n
+-(default 997);
+-.I n
+-should be prime.
+-Making \f2n\f1 bigger saves search time and spends disk space.
+-T}
+-\-i[u] \f2name        T{
+-Take input from file
+-.I name ,
+-instead of the standard input;
+-if
+-.B u
+-is present
+-.I name
+-is unlinked when the sort is started.
+-Using this option permits the sort scratch space
+-to overlap the disk space used for input keys.
+-T}
+-\-n   T{
+-Make a completely new set of inverted files, ignoring
+-previous files.
+-T}
+-\-p   T{
+-Pipe into the sort program, rather than writing a temporary
+-input file.
+-This saves disk space and spends processor time.
+-T}
+-\-v   T{
+-Verbose mode; print a summary of the number of keys which
+-finished indexing.
+-T}
+-.TE
+-.PP
+-About half the time used in
+-.I inv
+-is in the contained sort.
+-Assuming the sort is roughly linear, however,
+-a guess at the total timing for
+-.I inv
+-is 250 keys per second.
+-The space used is usually of more importance:
+-the entry file uses four bytes per possible hash (note
+-the
+-.B \-h
+-option),
+-and the tag file around 15-20 bytes per item indexed.
+-Roughly, the posting file contains one item for each key instance
+-and one item for each possible hash code; the items are two bytes
+-long if the tag file is less than 65336 bytes long, and the
+-items are four bytes wide if the tag file is greater than
+-65536 bytes long.
+-To minimize storage, the hash tables should be
+-over-full;
+-for most of the files indexed in this way, there is no
+-other real choice, since the
+-.I entry
+-file must fit in memory.
+-.PP
+-.B
+-Searching and Retrieving.
+-.R
+-The
+-.I hunt
+-program retrieves items from an index.
+-It combines, as mentioned above, the two parts of phase (B):
+-search and delivery.
+-The reason why it is efficient to combine delivery and search
+-is partly to avoid starting unnecessary processes, and partly
+-because the delivery operation must be a part of the search
+-operation in any case.
+-Because of the hashing, the search part takes place in two stages:
+-first items are retrieved which have the right hash codes associated with them,
+-and then the actual items are inspected to determine false drops, i.e.
+-to determine if anything with the right hash codes doesn't really have the right
+-keys.
+-Since the original item is retrieved to check on false drops,
+-it is efficient to present it immediately, rather than only
+-giving the tag as output and later retrieving the
+-item again.
+-If there were a separate key file, this argument would not apply,
+-but separate key files are not common.
+-.PP
+-Input to
+-.I hunt
+-is taken from the standard input,
+-one query per line.
+-Each query should be in
+-.I "mkey \-s"
+-output format;
+-all lower case, no punctuation.
+-The
+-.I hunt
+-program takes one argument which specifies the base name of the index
+-files to be searched.
+-Only one set of index files can be searched at a time,
+-although many text files may be indexed as a group, of course.
+-If one of the text files has been changed since the index, that file
+-is searched with
+-.I fgrep;
+-this may occasionally slow down the searching, and care should be taken to
+-avoid having many out of date files.
+-The following option arguments are recognized by
+-.I hunt:
+-.TS
+-center;
+-lB lw(4i).
+-\-a   T{
+-Give all output; ignore checking for false drops.
+-T}
+-\-C\f2n       T{
+-Coordination level
+-.I n;
+-retrieve items with not more than
+-.I n
+-terms of the input missing;
+-default
+-.I C0 ,
+-implying that each search term must be in the output items.
+-T}
+-\-F[yn\f2d\f3\|]      T{
+-``\-Fy'' gives the text of all the items found;
+-``\-Fn'' suppresses them.
+-``\-F\f2d\|\f1'' where \f2d\f1\| is an integer
+-gives the text of the first \f2d\f1 items.
+-The default is
+-.I \-Fy.
+-T}
+-\-g   T{
+-Do not use
+-.I fgrep
+-to search files changed since the index was made;
+-print an error comment instead.
+-T}
+-\-i \f2string T{
+-Take
+-.I string
+-as input, instead of reading the standard input.
+-T}
+-\-l \f2n      T{
+-The maximum length of internal lists of candidate
+-items is
+-.I n;
+-default 1000.
+-T}
+-\-o \f2string T{
+-Put text output (``\-Fy'') in
+-.I string;
+-of use
+-.I only
+-when
+-invoked from another program.
+-T}
+-\-p   T{
+-Print hash code frequencies; mostly
+-for use in optimizing hash table sizes.
+-T}
+-\-T[yn\f2d\|\f3]      T{
+-``\-Ty'' gives the tags of the items found;
+-``\-Tn'' suppresses them.
+-``\-T\f2d\f1\|'' where \f2d\f1\| is an integer
+-gives the first \f2d\f1 tags.
+-The default is
+-.I \-Tn .
+-T}
+-\-t \f2string T{
+-Put tag output (``\-Ty'') in
+-.I string;
+-of use
+-.I only
+-when invoked from another program.
+-T}
+-.TE
+-.PP
+-The timing of
+-.I hunt
+-is complex.
+-Normally the hash table is overfull, so that there will
+-be many false drops on any single term;
+-but a multi-term query will have few false drops on
+-all terms.
+-Thus if a query is underspecified (one search term)
+-many potential items will be examined and discarded as false
+-drops, wasting time.
+-If the query is overspecified (a dozen search terms)
+-many keys will be examined only to verify that
+-the single item under consideration has that key posted.
+-The variation of search time with number of keys is
+-shown in the table below.
+-Queries of varying length were constructed to retrieve
+-a particular document from the file of references.
+-In the sequence to the left, search terms were chosen so as
+-to select the desired paper as quickly as possible.
+-In the sequence on the right, terms were chosen inefficiently,
+-so that the query did not uniquely select the desired document
+-until four keys had been used.
+-The same document was the target in each case,
+-and the final set of eight keys are also identical; the differences
+-at five, six and seven keys are produced by measurement error, not
+-by the slightly different key lists.
+-.TS
+-center;
+-c   s   s   s5  | c   s   s   s
+-cp8 cp8 cp8 cp8 | cp8 cp8 cp8 cp8
+-cp8 cp8 cp8 cp8 | cp8 cp8 cp8 cp8
+-n   n   n   n   | n   n   n   n  .
+-Efficient Keys        Inefficient Keys
+-No. keys      Total drops     Retrieved       Search time     No. keys        Total drops     Retrieved       Search time
+-      (incl. false)   Documents       (seconds)               (incl. false)   Documents       (seconds)
+-1     15      3       1.27    1       68      55      5.96
+-2     1       1       0.11    2       29      29      2.72
+-3     1       1       0.14    3       8       8       0.95
+-4     1       1       0.17    4       1       1       0.18
+-5     1       1       0.19    5       1       1       0.21
+-6     1       1       0.23    6       1       1       0.22
+-7     1       1       0.27    7       1       1       0.26
+-8     1       1       0.29    8       1       1       0.29
+-.TE
+-As would be expected, the optimal search is achieved
+-when the query just specifies the answer; however,
+-overspecification is quite cheap.
+-Roughly, the time required by
+-.I hunt
+-can be approximated as
+-30 milliseconds per search key plus 75 milliseconds
+-per dropped document (whether it is a false drop or
+-a real answer).
+-In general, overspecification can be recommended;
+-it protects the user against additions to the data base
+-which turn previously uniquely-answered queries
+-into ambiguous queries.
+-.PP
+-The careful reader will have noted an enormous discrepancy between these times
+-and the earlier quoted time of around 1.9 seconds for a search.  The times
+-here are purely for the search and retrieval: they are measured by
+-running many searches through a single invocation of the
+-.I hunt
+-program alone.
+-Usually, the UNIX command processor (the shell) must start both
+-the
+-.I mkey
+-and
+-.I hunt
+-processes for each query, and arrange for the output of
+-.I mkey
+-to be fed to
+-the
+-.I hunt
+-program.
+-This adds a fixed overhead of about 1.7 seconds
+-of processor time
+-to any single search.
+-Furthermore, remember that all these times are processor times:
+-on a typical morning on our \s-2PDP\s0 11/70 system, with about one dozen
+-people logged on,
+-to obtain 1 second of processor time for the search program
+-took between 2 and 12 seconds of real time, with a median of
+-3.9 seconds and a mean of 4.8 seconds.
+-Thus, although the work involved in a single search may be only
+-200 milliseconds, after you add the 1.7 seconds of startup processor
+-time
+-and then assume a 4:1 elapsed/processor time
+-ratio, it will be 8 seconds before any response is printed.
+-.NH
+-Selecting and Formatting References for T\s-2ROFF\s0
+-.PP
+-The major application of the retrieval software
+-is
+-.I refer,
+-which is a
+-.I troff
+-preprocessor
+-like
+-.I eqn .
+-.[
+-kernighan cherry acm 1975
+-.]
+-It scans its input looking for items of the form
+-.DS
+-\*.[
+-imprecise citation
+-\*.\^]
+-.DE
+-where an imprecise citation is merely a string
+-of words found in the relevant bibliographic citation.
+-This is translated into a properly formatted reference.
+-If the imprecise citation does not correctly identify
+-a single paper
+-(either
+-selecting no papers or too many) a message is given.
+-The data base of citations searched may be tailored to each
+-system, and individual users may specify their own
+-citation
+-files.
+-On our system, the default data base is accumulated from
+-the publication lists of the members of our organization, plus
+-about half a dozen personal bibliographies that were collected.
+-The present total is about 4300 citations, but this increases steadily.
+-Even now,
+-the data base covers a large fraction of local citations.
+-.PP
+-For example, the reference for the
+-.I eqn
+-paper above was specified as
+-.DS
+-\&\*.\*.\*.
+-\&preprocessor like
+-\&.I eqn.
+-\&.[
+-\&kernighan cherry acm 1975
+-\&.]
+-\&It scans its input looking for items
+-\&\*.\*.\*.
+-.DE
+-This paper was itself printed using
+-.I refer.
+-The above input text was processed by
+-.I refer
+-as well as
+-.I tbl
+-and
+-.I troff
+-by the command
+-.DS
+-.ft I
+-refer memo-file | tbl | troff \-ms
+-.ft R
+-.DE
+-and the reference was automatically translated into a correct
+-citation to the ACM paper on mathematical typesetting.
+-.PP
+-The procedure to use to place a reference in a paper
+-using
+-.I refer
+-is as follows.
+-First, use the
+-.I lookbib
+-command to check that the paper is in the data base
+-and to find out what keys are necessary to retrieve it.
+-This is done by typing
+-.I lookbib
+-and then typing some potential queries until
+-a suitable query is found.
+-For example, had one started to find
+-the
+-.I eqn
+-paper shown above by presenting the query
+-.DS
+-      $ lookbib
+-      kernighan cherry
+-      (EOT)
+-.DE
+-.I lookbib
+-would have found several items; experimentation would quickly
+-have shown that the query given above is adequate.
+-Overspecifying the query is of course harmless; it is even desirable,
+-since it decreases the risk that a document added to the publication
+-data base in the future will be retrieved in addition to the
+-intended document.
+-The extra time taken by even a grossly overspecified query is
+-quite small.
+-A particularly careful reader may have noticed that ``acm'' does not
+-appear in the printed citation;
+-we have supplemented some of the data base items with
+-extra keywords, such as common abbreviations for journals
+-or other sources, to aid in searching.
+-.PP
+-If the reference is in the data base, the query
+-that retrieved it can be inserted in the text,
+-between
+-.B \*.[
+-and 
+-.B \*.\^]
+-brackets.
+-If it is not in the data base, it can be typed
+-into a private file of references, using the format
+-discussed in the next section, and then
+-the
+-.B \-p
+-option
+-used to search this private file.
+-Such a command might read
+-(if the private references are called
+-.I myfile )
+-.DS
+-.ft 2
+-refer \-p myfile document | tbl | eqn | troff \-ms \*. \*. \*.
+-.ft 1
+-.DE
+-where
+-.I tbl
+-and/or
+-.I eqn
+-could be omitted if not needed.
+-The use
+-of the
+-.I \-ms
+-macros
+-.[
+-lesk typing documents unix gcos
+-.]
+-or some other macro package, however,
+-is essential.
+-.I Refer
+-only generates the data for the references; exact formatting
+-is done by some macro package, and if none is supplied the
+-references will not be printed.
+-.PP
+-By default,
+-the references are numbered sequentially,
+-and
+-the
+-.I \-ms
+-macros format references as footnotes at the bottom of the page.
+-This memorandum is an example of that style.
+-Other possibilities are discussed in section 5 below.
+-.NH
+-Reference Files.
+-.PP
+-A reference file is a set of bibliographic references usable with
+-.I refer.
+-It can be indexed using the software described in section 2
+-for fast searching.
+-What
+-.I refer
+-does is to read the input document stream,
+-looking for imprecise citation references.
+-It then searches through reference files to find
+-the full citations, and inserts them into the
+-document.
+-The format of the full citation is arranged to make it
+-convenient for a macro package, such as the
+-.I \-ms
+-macros, to format the reference
+-for printing.
+-Since
+-the format of the final reference is determined
+-by the desired style of output,
+-which is determined by the macros used,
+-.I refer
+-avoids forcing any kind of reference appearance.
+-All it does is define a set of string registers which
+-contain the basic information about the reference;
+-and provide a macro call which is expanded by the macro
+-package to format the reference.
+-It is the responsibility of the final macro package
+-to see that the reference is actually printed; if no
+-macros are used, and the output of
+-.I refer
+-fed untranslated to
+-.I troff,
+-nothing at all will be printed.
+-.PP
+-The strings defined by
+-.I refer
+-are taken directly from the files of references, which
+-are in the following format.
+-The references should be separated
+-by blank lines.
+-Each reference is a sequence of lines beginning with
+-.B %
+-and followed
+-by a key-letter.
+-The remainder of that line, and successive lines until the next line beginning
+-with
+-.B % ,
+-contain the information specified by the key-letter.
+-In general,
+-.I refer
+-does not interpret the information, but merely presents
+-it to the macro package for final formatting.
+-A user with a separate macro package, for example,
+-can add new key-letters or use the existing ones for other purposes
+-without bothering
+-.I refer.
+-.PP
+-The meaning of the key-letters given below, in particular,
+-is that assigned by the
+-.I \-ms
+-macros.
+-Not all information, obviously, is used with each citation.
+-For example, if a document is both an internal memorandum and a journal article,
+-the macros ignore the memorandum version and cite only the journal article.
+-Some kinds of information are not used at all in printing the reference;
+-if a user does not like finding references by specifying title
+-or author keywords, and prefers to add specific keywords to the
+-citation, a field is available which is searched but not
+-printed (\f3K\f1).
+-.PP
+-The key letters currently recognized by
+-.I refer
+-and
+-.I \-ms,
+-with the kind of information implied, are:
+-.KS
+-.TS
+-center;
+-c c6 c c
+-c l c l.
+-Key   Information specified   Key     Information specified
+-A     Author's name   N       Issue number
+-B     Title of book containing item   O       Other information
+-C     City of publication     P       Page(s) of article
+-D     Date    R       Technical report reference
+-E     Editor of book containing item  T       Title
+-G     Government (NTIS) ordering number       V       Volume number
+-I     Issuer (publisher)
+-J     Journal name
+-K     Keys (for searching)    X       or
+-L     Label   Y       or
+-M     Memorandum label        Z       Information not used by \f2refer\f1
+-.TE
+-.KE
+-For example, a sample reference could be
+-typed as:
+-.DS
+-%T Bounds on the Complexity of the Maximal
+-Common Subsequence Problem
+-%Z ctr127
+-%A A. V. Aho
+-%A D. S. Hirschberg
+-%A J. D. Ullman
+-%J J. ACM
+-%V 23
+-%N 1
+-%P 1-12
+-.\"%M TM 75-1271-7
+-%M abcd-78
+-%D Jan. 1976
+-.DE
+-Order is irrelevant, except that authors are shown in the order
+-given.  The output of
+-.I refer
+-is a stream of string definitions, one
+-for each of the fields of each reference, as
+-shown below.
+-.DS
+-\*.]-
+-\*.ds [A authors' names \*.\*.\*.
+-\*.ds [T title \*.\*.\*.
+-\*.ds [J journal \*.\*.\*.
+-\*.\*.\*.
+-\*.]\|[ type-number
+-.DE
+-The
+-.I refer
+-program, in general, does not concern itself with the significance
+-of the strings.
+-The different fields are treated identically by
+-.I refer ,
+-except that the
+-X, Y and Z fields are ignored (see the
+-.B \-i
+-option of
+-.I mkey\^ )
+-in indexing and searching.
+-All
+-.I refer
+-does is select the appropriate citation, based on the keys.
+-The macro package must arrange the strings so as to produce an appropriately
+-formatted citation.
+-In this process, it uses the convention that the `T' field is the title,
+-the `J' field the journal, and so forth.
+-.PP
+-The
+-.I refer
+-program does arrange the citation to simplify the macro package's
+-job, however.
+-The special macro
+-.B \&\*.]\-
+-precedes the string definitions
+-and the special macro
+-.B \*.]\|[
+-follows.
+-These are changed from the input
+-.B \*.[
+-and 
+-.B \*.\^]
+-so that running the same file through
+-.I refer
+-again is harmless.
+-The 
+-.B \*.]\-
+-macro can be used by the macro package to
+-initialize.
+-The 
+-.B \*.]\|[
+-macro, which should be used
+-to print the reference, is given an
+-argument
+-.I type-number
+-to indicate the kind of reference, as follows:
+-.KS
+-.TS
+-center;
+-c c
+-n l.
+-Value Kind of reference
+-1     Journal article
+-2     Book
+-3     Article within book
+-4     Technical report
+-5     Bell Labs technical memorandum
+-0     Other
+-.TE
+-.KE
+-The type is determined by the presence or absence of particular fields
+-in the citation (a journal article must have a `J' field, a book must have
+-an `I' field, and so forth).
+-To a small extent, this violates
+-the above rule that
+-.I refer
+-does not concern itself with the contents of the citation;
+-however, the classification of the citation in
+-.I troff
+-macros would require a relatively expensive and obscure
+-program.
+-Any macro writer may, of course, preserve consistency by ignoring
+-the argument to the
+-.B \*.]\|[
+-macro.
+-.PP
+-The reference is flagged in the text
+-with the sequence
+-.DS
+-\e*\|([\*.number\e*\|(\*.\^]
+-.DE
+-where
+-.I number
+-is the footnote number.
+-The strings
+-.B [\*.
+-and 
+-.B \*.\^]
+-should be used by the macro package
+-to format the reference flag in the text.
+-These strings can be replaced for a particular
+-footnote, as described in section 5.
+-The footnote number (or other signal) is available
+-to the reference macro
+-.B \*.]\|[
+-as the
+-string register
+-.B [F .
+-To simplify dealing with a text reference that occurs
+-at the end of a sentence,
+-.I refer
+-treats a reference which follows a period in a special way.
+-The period is removed, and the reference is preceded by
+-a call for the string
+-.B <.
+-and followed by a call for the string
+-.B >.
+-For example, if a reference follows ``end.'' it will appear
+-as
+-.DS
+-end\e*(<\*.\e*([\*.number\e*(\*.]\e*(>\*.
+-.DE
+-where
+-.I number
+-is the footnote number.
+-The macro package should turn either the string
+-.B >.
+-or
+-.B <.
+-into a period and delete the other one.
+-This permits the output to have either the form
+-``end[31].'' or ``end.\s-3\u31\d\s0'' as the
+-macro package wishes.
+-Note that in one case the period precedes the number and in the
+-other it follows the number.
+-.PP
+-In some cases users wish to suspend the searching, and merely
+-use the reference macro formatting.
+-That is, the user doesn't want to provide a search key
+-between
+-.B \*.[
+-and 
+-.B \*.\^]
+-brackets, but merely
+-the reference lines for the appropriate document.
+-Alternatively, the user
+-can wish
+-to add a few fields to those in the reference
+-as in the standard file, or
+-override some fields.
+-Altering or replacing fields, or supplying whole references, is easily done
+-by inserting lines beginning
+-with
+-.B % ;
+-any such line is taken as
+-direct input to the reference
+-processor rather than keys to be searched.
+-Thus
+-.DS
+-\*.[
+-key1 key2 key3 \*.\*.\*.
+-%Q New format item
+-%R Override report name
+-\*.\^]
+-.DE
+-makes the indicates changes to the result of searching for
+-the keys.
+-All of the search keys must be given before the first
+-\f3%\f1 line.
+-.PP
+-If no search keys are provided, an entire citation can
+-be provided in-line in the text.
+-For example, if the
+-.I eqn
+-paper citation were to be inserted in
+-this way, rather than by searching for it in the data base,
+-the input would read
+-.DS
+-\&\*.\*.\*.
+-\&preprocessor like
+-\&.I eqn.
+-\&.[
+-\&%A B. W. Kernighan
+-\&%A L. L. Cherry
+-\&%T A System for Typesetting Mathematics
+-\&%J Comm. ACM
+-\&%V 18
+-\&%N 3
+-\&%P 151-157
+-\&%D March 1975
+-\&.]
+-\&It scans its input looking for items
+-\&\*.\*.\*.
+-.DE
+-This would produce a citation of the same appearance as that
+-resulting from the file search.
+-.PP
+-As shown, fields are normally turned into
+-.I troff
+-strings.
+-Sometimes users would rather have them defined as macros,
+-so that other
+-.I troff
+-commands can be placed into the data.
+-When this is necessary, simply double the control character
+-.B %
+-in the data.
+-Thus the input
+-.DS
+-\&.[
+-%V 23
+-%%M
+-Bell Laboratories,
+-Murray Hill, N.J. 07974
+-\&.]
+-.DE
+-is processed by
+-.I refer
+-into
+-.DS
+-\&.ds [V 23
+-\&.de [M
+-Bell Laboratories,
+-Murray Hill, N.J. 07974
+-\&..
+-.DE
+-The information after
+-.B %%M
+-is defined as a macro to be invoked by
+-.B .[M
+-while the information after
+-.B %V
+-is turned into a string to be invoked by
+-.B \e\(**([V .
+-At present
+-.I \-ms
+-expects all information as strings.
+-.NH
+-Collecting References and other Refer Options
+-.PP
+-Normally, the combination of
+-.I refer
+-and
+-.I \-ms
+-formats output as 
+-.I troff
+-footnotes which are consecutively numbered and placed
+-at the bottom of the page.  However,
+-options exist to
+-place the references at the end; to arrange references alphabetically
+-by senior author; and to indicate references by strings in the text of the form
+-[Name1975a]
+-rather than by number.
+-Whenever references are not placed at the bottom of a page
+-identical references are coalesced.
+-.PP
+-For example, the
+-.B \-e
+-option to
+-.I refer
+-specifies that references are to be collected; in this case
+-they are output whenever the sequence
+-.DS
+-\*.[
+-$LIST$
+-\*.\^]
+-.DE
+-is encountered.
+-Thus, to place references at the end of a paper, the user would run
+-.I refer
+-with the
+-.I \-e
+-option and place the above $LIST$ commands after the last
+-line of the text.
+-.I Refer
+-will then move all the references to that point.
+-To aid in formatting the collected references,
+-.I refer
+-writes the references preceded by the line
+-.DS
+-.B .]<
+-.DE
+-and
+-followed by the line
+-.DS
+-.B .]>
+-.DE
+-to invoke special macros before and after the references.
+-.PP
+-Another possible option to
+-.I refer
+-is the
+-.B \-s
+-option to specify
+-sorting of references.  The default,
+-of course, is to list references in the order presented.
+-The
+-.B \-s
+-option implies the
+-.B \-e
+-option, and thus requires
+-a
+-.DS
+-\*.[
+-$LIST$
+-\*.\^]
+-.DE
+-entry to call out the reference list.
+-The
+-.B \-s
+-option may be followed by a string of letters, numbers, and `+' signs indicating how
+-the references are to be sorted.
+-The sort is done using the fields whose key-letters are
+-in the string as sorting keys; the numbers indicate how many
+-of the fields are to be considered, with `+'
+-taken as a large number.
+-Thus the default is
+-.B \-sAD
+-meaning ``Sort on senior author, then date.''  To
+-sort on all authors and then title, specify
+-.B \-sA+T .
+-And to sort on two authors and then the journal,
+-write
+-.B \-sA2J .
+-.PP
+-Other options to
+-.I refer
+-change the signal or label inserted in the text for each reference.
+-Normally these are just sequential numbers,
+-and their exact placement (within brackets, as superscripts, etc.) is determined
+-by the macro package.
+-The
+-.B \-l
+-option replaces reference numbers by
+-strings composed of the senior author's last name, the date,
+-and a disambiguating letter.
+-If a number follows the
+-.B l
+-as in
+-.B \-l3
+-only that many letters of the last name are used
+-in the label string.
+-To abbreviate the date as well the form
+-\f3-l\f2m,n\f1
+-shortens the last name to the
+-first
+-.I m
+-letters and the date to the
+-last
+-.I n
+-digits.
+-For example, the option
+-.B \-l3,2
+-would refer to the
+-.I eqn
+-paper (reference 3) by the signal
+-.I Ker75a ,
+-since it is the first cited reference by Kernighan in 1975.
+-.PP
+-A user wishing to specify particular labels for
+-a private bibliography may use the
+-.B \-k
+-option.
+-Specifying
+-\f3\-k\f2x\f1
+-causes the field \f2x\f1 to be used as a label.
+-The default is \f3L\f1.
+-If this field ends in \f3\-\f1, that character
+-is replaced by a sequence letter; otherwise the field
+-is used exactly as given.
+-.PP
+-If none of the
+-.I refer -produced
+-signals are desired,
+-the
+-.B \-b
+-option entirely suppresses automatic text signals.
+-.PP
+-If the user wishes to override the
+-.I \-ms
+-treatment of the reference signal (which is normally to
+-enclose the number in brackets in
+-.I nroff
+-and make it a superscript in
+-.I troff\\| )
+-this can be done easily.
+-If the lines
+-.B \&.[
+-or
+-.B \&.]
+-contain anything following these characters,
+-the remainders of these lines are used to surround
+-the reference signal, instead of the default.
+-Thus, for example, to say ``See reference (2).''
+-and avoid
+-``See reference.\s-3\u2\d\s+3'' the
+-input might appear
+-.DS
+-\&See reference
+-\&\*.[ (
+-imprecise citation ...
+-\&\*.\^])\*.
+-.DE
+-Note that blanks are significant in this construction.
+-If a permanent change is desired in the style of reference
+-signals, however, it is probably easier to redefine the strings
+-.B \&[.
+-and
+-.B \&.]
+-(which are used to bracket each signal)
+-than to change each citation.
+-.PP
+-Although normally
+-.I refer
+-limits itself to retrieving the data for the reference,
+-and leaves to a macro package the job of arranging that
+-data as required by the local format, there are two
+-special options for rearrangements that can not be
+-done by macro packages.
+-The
+-.B \-c
+-option puts fields into all upper case
+-(C\s-2APS\s+2-S\s-2MALL\s+2 C\s-2APS\s+2
+-in
+-.I troff
+-output).
+-The key-letters indicated what information is to be translated
+-to upper case follow the
+-.B c ,
+-so that
+-.B \-cAJ
+-means that authors' names and journals are to be in caps.
+-The
+-.B \-a
+-option writes the names of authors last name first, that is
+-.I "A. D. Hall, Jr."
+-is written as
+-.I "Hall, A. D. Jr" .
+-The citation form of
+-the
+-.I "Journal of the ACM" ,
+-for example, would require
+-both
+-.B \-cA
+-and
+-.B \-a
+-options.
+-This produces authors' names in the style
+-.I
+-K\s-2ERNIGHAN\s0, B. W. \s-2AND\s0 C\s-2HERRY\s0, L. L.\&
+-.R
+-for the previous example.
+-The
+-.B \-a
+-option may be followed by a number to indicate how many
+-author names should be reversed;
+-.B \-a1
+-(without any
+-.B \-c
+-option)
+-would produce
+-.I
+-Kernighan, B. W. and L. L. Cherry,
+-.R
+-for example.
+-.PP
+-Finally, there is also the previously-mentioned
+-.B \-p
+-option to let the user specify
+-a private file of references to be searched before the public files.
+-Note that
+-.I refer
+-does not insist on a previously made index for these files.
+-If a file is named which contains reference
+-data but is not indexed, it will be searched
+-(more slowly)
+-by
+-.I refer
+-using
+-.I fgrep.
+-In this way
+-it is easy for users to keep small files of
+-new references, which can later be added to the
+-public data bases.
+-.SG MH-1274-MEL-\s8UNIX\s0
+//GO.SYSIN DD refer
diff --git a/doc/7thEdMan/vol2/regen b/doc/7thEdMan/vol2/regen
new file mode 100644 (file)
index 0000000..452542a
--- /dev/null
@@ -0,0 +1,547 @@
+.TL
+Regenerating System Software
+.AU
+Charles B. Haley
+.AU
+Dennis. M. Ritchie
+.MH
+.SH
+Introduction
+.PP
+This document discusses how to
+assemble or compile various parts of the
+.UX
+system software.
+This may be necessary because
+a command or library is accidentally
+deleted or otherwise
+destroyed;
+also, it may be desirable to install a modified
+version of some command or library routine.
+A few commands depend
+to some degree on the current configuration
+of the system;
+thus in any new system modifications to some commands
+are advisable.
+Most of the likely modifications
+relate to the standard disk devices contained
+in the system.
+For example, the df(1) (`disk free')
+command has built into it the names of
+the standardly present disk storage drives
+(e.g. `/dev/rf0', `/dev/rp0').
+Df(1) takes an argument to indicate which
+disk to examine, but it is convenient
+if its default argument is adjusted to
+reflect the ordinarily present devices.
+The companion document `Setting up UNIX'
+discusses which commands are likely to require
+changes.
+.SH
+Where Commands and Subroutines Live
+.PP
+The
+source files for commands and subroutines reside
+in several subdirectories
+of the directory /usr/src.
+These subdirectories, and a general
+description of their contents, are
+.IP cmd 12
+Source files for commands.
+.IP libc/stdio 12
+Source files making up the `standard i/o package'.
+.IP libc/sys 12
+Source files for the C system call interfaces.
+.IP libc/gen 12
+Source files for most of the remaining routines described
+in section 3 of the manual.
+.IP libc/crt 12
+Source files making up the C runtime support package, as
+in call save-return and long arithmetic.
+.IP libc/csu 12
+Source for the C startup routines.
+.IP games 12
+Source for (some of) the games.
+No great care has been taken to try to make it obvious how
+to compile these; treat it as a game.
+.IP libF77 12
+Source for the Fortran 77 runtime library, exclusive of IO.
+.IP libI77 12
+Source for the Fortran 77 IO runtime routines.
+.IP libdbm 12
+Source for the `data-base manager' package
+.I dbm
+(3).
+.IP libfpsim 12
+Source for the floating-point simulator routine.
+.IP libm 12
+Source for the mathematical library.
+.IP libplot 12
+Source for plotting routines.
+.SH
+Commands
+.PP
+The regeneration of most commands
+is straightforward.
+The `cmd' directory will contain either a source file
+for the command or a subdirectory containing the set
+of files that make up the command.
+If it is a single file the command
+.DS
+cd /usr/src/cmd
+cmake cmd_name
+.DE
+suffices. (Cmd_name is the name of the command you
+are playing with.)
+The result of the cmake command will be an executable version.
+If you type
+.DS
+cmake \-cp cmd_name
+.DE
+the result
+will be copied to /bin
+(or perhaps /etc or other places if appropriate).
+.PP
+If the source files are in a subdirectory there will be a `makefile'
+(see make(1)) to control the regeneration.
+After changing to the proper directory (cd(1)) you type one of the following:
+.IP "make all" 12
+The program is compiled and loaded; the executable is
+left in the current directory.
+.IP "make cp" 12
+The program is compiled and loaded, and the executable is
+installed.
+Everything is cleaned up afterwards;
+for example .o files are deleted.
+.IP "make cmp" 12
+The program is compiled and loaded, and the executable is compared
+against the one in /bin.
+.PP
+Some of the makefiles have other options. Print (cat(1)) the ones you
+are interested in to find out.
+.SH
+The Assembler
+.PP
+The assembler consists of two executable files:
+/bin/as and /lib/as2.
+The first is the 0-th pass:
+it reads the source program, converts it to
+an intermediate form in a temporary file `/tmp/atm0?',
+and estimates the final locations
+of symbols.
+It also makes two or three other temporary
+files which contain the ordinary symbol table,
+a table of temporary symbols (like 1:)
+and possibly an overflow intermediate file.
+The program /lib/as2
+acts as an ordinary multiple pass assembler
+with input taken from the files produced by /bin/as.
+.PP
+The source files for /bin/as
+are named `/usr/src/cmd/as/as1?.s'
+(there are 9 of them);
+/lib/as2 is produced
+from the source files
+`/usr/src/cmd/as/as2?.s';
+they likewise are 9 in number.
+Considerable care should be exercised
+in replacing either component of the
+assembler.
+Remember that if the assembler is lost,
+the only recourse is to replace it from some backup storage;
+a broken assembler cannot assemble itself.
+.SH
+The C Compiler
+.PP
+The C compiler consists of
+seven routines:
+`/bin/cc',
+which calls the phases of the compiler proper,
+the compiler control line expander `/lib/cpp',
+the assembler (`as'), and the loader (`ld').
+The phases of the C compiler are
+`/lib/c0', which is the first phase of the compiler;
+`/lib/c1', which is the second phase of the compiler;
+and `/lib/c2', which is the optional
+third phase optimizer.
+The loss of the C compiler is as serious
+as that of the assembler.
+.PP
+The source for /bin/cc
+resides in `/usr/src/cmd/cc.c'.
+Its loss alone (or that of c2) is not fatal.
+If needed,
+prog.c can be compiled by
+.DS
+/lib/cpp prog.c >temp0
+/lib/c0 temp0 temp1 temp2
+/lib/c1 temp1 temp2 temp3
+as \- temp3
+ld \-n /lib/crt0.o a.out \-lc
+.DE
+.PP
+The source for the compiler proper is in the
+directory /usr/src/cmd/c.
+The first phase (/lib/c0)
+is generated from the files c00.c, ..., c05.c,
+which must be compiled by the C compiler.
+There is also c0.h, a header file
+.I included
+by the C programs of the first phase.
+To make a new /lib/c0 use
+.DS
+make c0
+.DE
+Before installing the new c0, it is prudent to save the old one someplace.
+.PP
+The second phase of C (/lib/c1)
+is generated from the source files c10.c, ..., c13.c,
+the include-file c1.h, and a set
+of object-code tables combined into table.o.
+To generate a new second phase use
+.DS
+make c1
+.DE
+It is likewise prudent to save c1 before
+installing a new version.
+In fact in general it is wise to save the
+object files for the C compiler so that
+if disaster strikes C can be reconstituted
+without a working version of the compiler.
+.PP
+In a similar manner,
+the third phase of the C compiler
+(/lib/c2)
+is made up from the files
+c20.c and c21.c together with c2.h.
+Its loss is not critical since it is completely optional.
+.PP
+The set of tables mentioned above
+is generated from the file
+table.s.
+This `.s' file is not in fact assembler source;
+it must be converted by use of the 
+.I cvopt
+program, whose source and object are
+located in the C directory.
+Normally this is taken care of by make(1). You
+might want to look at the makefile to see what it does.
+.SH
+UNIX
+.PP
+The source and object programs for UNIX are kept in
+four subdirectories of
+.I /usr/sys.
+In the subdirectory 
+.I h
+there are several files ending in `.h';
+these are header files which are
+picked up (via `#include ...')
+as required by each system module.
+The subdirectory
+.I dev
+consists mostly of the device drivers
+together with a few other things.
+The subdirectory
+.I sys
+is the rest of the system.
+There are files of the form LIBx in the directories
+sys and dev. These are archives (ar(1)) which contain the
+object versions of the routines in the directory.
+.PP
+Subdirectory
+.I conf
+contains the files which control
+device configuration of the system.
+.I L.s
+specifies the
+contents of the interrupt vectors;
+.I c.c
+contains the tables which relate device numbers
+to handler routines.
+A third file,
+.I mch.s ,
+contains all the
+machine-language code in the system.
+A fourth file,
+.I mch0.s ,
+is generated by mkconf(1) and contains
+flags indicating what sort of tape drive is available
+for taking crash dumps.
+.PP
+There are two ways to recreate the system. Use
+.DS
+cd /usr/sys/conf
+make unix
+.DE
+if the libraries /usr/sys/dev/LIB2 and /usr/sys/sys/LIB1,
+and also c.o and l.o,
+are correct.
+Use
+.DS
+cd /usr/sys/conf
+make all
+.DE
+to recompile everything
+and recreate the libraries from scratch.
+This is needed, for example, when a header included
+in several source files is changed.
+See `Setting Up UNIX' for other information about configuration
+and such.
+.PP
+When the make is
+done, the new system is present in the
+current directory as `unix'.
+It should be tested before destroying the currently
+running `/unix', this is best done by doing something like
+.DS
+mv /unix /ounix
+mv unix /unix
+.DE
+If the new system doesn't work, you can still boot `ounix'
+and come up (see boot(8)).
+When you have satisfied yourself that the new system works,
+remove /ounix.
+.PP
+To install a new device driver,
+compile it and
+put it into its library.
+The best way to put it into
+the library is to use the command
+.DS
+ar uv LIB2 x.o
+.DE
+where x is the routine you just compiled.
+(All the device drivers distributed with
+the system are already in the library.)
+.PP
+Next, the device's interrupt vector must be entered in l.s.
+This is probably already done by the routine mkconf(1), but if the
+device is esoteric or nonstandard you will have to massage
+l.s by hand.
+This involves placing a pointer to a callout routine
+and the device's priority level in the vector.
+Use some other device (like the console) as a guide.
+Notice that the entries in l.s must be in order
+as the assembler does not permit moving the
+location counter `.' backwards.
+The assembler also does not permit assignation of
+an absolute number to `.', which is the
+reason for the `. = ZERO+100' subterfuge.
+If a constant smaller than 16(10) is added to the
+priority level,
+this number will be available as the first argument of the interrupt routine.
+This stratagem is used when
+several similar devices share the same interrupt routine
+(as in dl11's).
+.PP
+If you have to massage l.s, be sure to add the code
+to actually transfer to the interrupt routine. Again use
+the console as a guide. The apparent strangeness of this code
+is due to running the kernel in separate I&D space.
+The
+.I call
+routine
+saves registers as required and prepares a C-style
+call on the actual interrupt routine
+named after the `jmp' instruction.
+When the routine returns,
+.I call
+restores the registers and performs an
+rti instruction.
+As an aside, note that
+external names in C programs have an
+underscore (`_') prepended to them.
+.PP
+The second step which must be performed to add a 
+device unknown to mkconf is
+to add it to the configuration table
+/usr/sys/conf/c.c.
+This file contains two subtables,
+one for block-type devices, and one for character-type devices.
+Block devices include disks, DECtape, and magtape.
+All other devices are character devices.
+A line in each of these tables gives all the information
+the system needs to know about the device handler;
+the ordinal position of the line in the table implies
+its major device number, starting at 0.
+.PP
+There are four subentries per line in the block device table,
+which give its open routine, close routine, strategy routine, and
+device table.
+The open and close routines may be nonexistent,
+in which case the name `nulldev' is given;
+this routine merely returns.
+The strategy routine is called to do any I/O,
+and the device table contains status information for the device.
+.PP
+For character devices, each line in the table
+specifies a routine for open,
+close, read, and write, and one which sets and returns
+device-specific status (used, for example, for stty and gtty
+on typewriters).
+If there is no open or close routine, `nulldev' may
+be given; if there is no read, write, or status
+routine, `nodev' may be given.
+Nodev sets an error flag and returns.
+.PP
+The final step which must
+be taken to install a device is to make a special file for it.
+This is done by mknod(1), to which you must specify the
+device class (block or character),
+major device number (relative line in the configuration table)
+and minor device number
+(which is made available to the driver at appropriate times).
+.PP
+The documents
+`Setting up Unix' and
+`The Unix IO system'
+may aid in comprehending these steps.
+.SH
+The Library libc.a
+.PP
+The library /lib/libc.a is where most of the subroutines
+described in sections 2 and 3 of the manual are kept.
+This library
+can be remade using the following commands:
+.DS
+cd /usr/src/libc
+sh compall
+sh mklib
+mv libc.a /lib/libc.a
+.DE
+If single routines need to be recompiled and replaced, use
+.DS
+cc \-c \-O x.c
+ar vr /lib/libc.a x.o
+rm x.o
+.DE
+The above can also be used to put new items into the library.
+See ar(1), lorder(1), and tsort(1).
+.PP
+The routines in /usr/src/cmd/libc/csu (C start up) are not in
+libc.a. These are separately assembled and put into
+/lib. The commands to do this are
+.DS
+cd /usr/src/libc/csu
+as \- x.s
+mv a.out /lib/x
+.DE
+where x is the routine you want.
+.SH
+Other Libraries
+.PP
+Likewise,
+the directories containing the source for the other libraries
+have files compall (that recompiles everything)
+and mklib (that recreates the library).
+.SH
+System Tuning
+.PP
+There are several tunable parameters in the system. These set
+the size of various tables and limits. They are found in the
+file /usr/sys/h/param.h as manifests (`#define's).
+Their values are rather generous in the system as distributed.
+Our typical maximum number of users is about 20, but there are
+many daemon processes.
+.PP
+When any parameter is changed, it is prudent to recompile
+the entire system, as discussed above.
+A brief discussion of each follows:
+.IP NBUF 12
+This sets the size of the disk buffer cache. Each buffer is 512 bytes.
+This number should be around 25 plus NMOUNT,
+or as big as can be if the above number of
+buffers cause the system to not fit in memory.
+.IP NFILE 12
+This sets the maximum number of open files. An entry is made in
+this table every time a file is `opened' (see open(2), creat(2)).
+Processes share these table entries across forks (fork(2)). This number
+should be about the same size as NINODE below. (It can be a bit smaller.)
+.IP NMOUNT 12
+This indicates the maximum number of mounted file systems. Make it
+big enough that you don't run out at inconvenient times.
+.IP MAXMEM 12
+This sets an administrative limit on the amount of memory
+a process may have.
+It is set automatically if the amount of physical memory is small,
+and thus should not need to be changed.
+.IP MAXUPRC 12
+This sets the maximum number of processes that any one user can
+be running at any one time. This should be set just large enough
+that people can get work done but not so large that a user can
+hog all the processes available (usually by accident!).
+.IP NPROC 12
+This sets the maximum number of processes that can be
+active.
+It depends on the demand pattern of the typical user;
+we seem to need about 8 times the number
+of terminals.
+.DE
+.IP NINODE 12
+This sets the size of the inode table. There is one entry in the inode
+table for every open device, current working directory,
+sticky text segment,
+open file, and mounted device.
+Note that if two users have a file open there is still only one entry
+in the inode table. A reasonable rule of thumb for the size of
+this table is
+.DS
+NPROC + NMOUNT + (number of terminals)
+.DE
+.IP SSIZE 12
+The initial size of a process stack. This may be made bigger
+if commonly run processes have large data areas on the stack.
+.IP SINCR 12
+The size of the stack growth increment.
+.IP NOFILE 12
+This sets the maximum number of files that any one process can have
+open.
+20 is plenty.
+.IP CANBSIZ 12
+This is the size of the typewriter canonicalization buffer. It is
+in this buffer that erase and kill processing is done. Thus this
+is the maximum size of an input typewriter line. 256 is usually
+plenty.
+.IP CMAPSIZ 12
+The number of fragments that memory can be broken into. This should
+be big enough that it never runs out.
+The theoretical maximum is twice the number of processes,
+but this is a vast overestimate in practice.
+50 seems enough.
+.IP SMAPSIZ 12
+Same as CMAPSIZ except for secondary (swap) memory.
+.IP NCALL 12
+This is the size of the callout table. Callouts are entered in this
+table when some sort of internal system timing must be done, as in
+carriage return delays for terminals. The number must be big enough
+to handle all such requests.
+.IP NTEXT 12
+The maximum number of simultaneously executing pure programs. This
+should be big enough so as to not run out of space under heavy load.
+A reasonable rule of thumb is about
+.DS
+(number of terminals) + (number of sticky programs)
+.DE
+.IP NCLIST 12
+The number of clist segments. A clist segment is 6 characters.
+NCLIST should be big enough so that the list doesn't become exhausted
+when the machine is busy. The characters that have arrived from a terminal
+and are waiting to be given to a process live here. Thus enough space
+should be left so that every terminal can have at least one average
+line pending (about 30 or 40 characters).
+.IP TIMEZONE 12
+The number of minutes westward from Greenwich. See `Setting Up UNIX'.
+.IP DSTFLAG 12
+See `Setting Up UNIX' section on time conversion.
+.IP MSGBUFS 12
+The maximum number of characters of system error messages saved. This
+is used as a circular buffer.
+.IP NCARGS 12
+The maximum number of characters in an exec(2) arglist. This
+number controls how many arguments can be passed
+into a process.
+5120 is practically infinite.
+.IP HZ 12
+Set to the frequency of the system clock (e.g., 50 for
+a 50 Hz. clock).
diff --git a/doc/7thEdMan/vol2/run b/doc/7thEdMan/vol2/run
new file mode 100644 (file)
index 0000000..790a3db
--- /dev/null
@@ -0,0 +1,133 @@
+pkg=-ms
+name=$1
+fmtr=nroff
+shift
+
+case $name in
+
+index)
+       $fmtr $pkg $* /usr/doc/index
+       ;;
+as*)
+       tbl /usr/doc/assembler | $fmtr $pkg $*
+       ;;
+ed*)
+       $fmtr $pkg $* /usr/doc/edtut/e*
+       ;;
+adv.ed)
+       $fmtr $pkg $* /usr/doc/adv.ed/ae*
+       ;;
+trofftut)
+       $fmtr $pkg $* /usr/doc/trofftut/tt*
+       ;;
+make)
+       $fmtr $pkg $* /usr/doc/make
+       ;;
+sum*|hel*)
+       eqn /usr/doc/summary/hel* | $fmtr $pkg $*
+       ;;
+cacm)
+       refer -e /usr/doc/cacm/p* | tbl | $fmtr $pkg $*
+       ;;
+impl*)
+       refer -e /usr/doc/implement | $fmtr $pkg $*
+       ;;
+bc)
+       $fmtr $pkg $* /usr/doc/bc
+       ;;
+dc)
+       eqn /usr/doc/dc | $fmtr $pkg $*
+       ;;
+eqn)
+       eqn /usr/doc/eqn/e* | $fmtr $pkg $*
+       ;;
+eqnguide)
+       eqn /usr/doc/eqn/g* | $fmtr $pkg $*
+       ;;
+troff)
+       /usr/doc/troff/tprint $*
+       ;;
+ctour)
+       $fmtr $pkg $* /usr/doc/ctour/cdoc*
+       ;;
+shell)
+       refer -e /usr/doc/shell/t* | $fmtr -$pkg $*
+       ;;
+sed)
+       $fmtr $pkg $* /usr/doc/sed
+       ;;
+f77)
+       tbl /usr/doc/f77 | eqn | $fmtr $pkg $*
+       ;;
+begin*)
+       eqn -s9 /usr/doc/beginners/u* | $fmtr $pkg $*
+       ;;
+uprog)
+       sed -f /usr/doc/cwscript /usr/doc/p? | $fmtr $pkg $* /usr/doc/p.mac -
+       ;;
+yacc)
+       refer -e /usr/doc/yacc/ss* | $fmtr $pkg $*
+       ;;
+lint)
+       refer -e /usr/doc/lint | $fmtr $pkg $*
+       ;;
+ratfor)
+       $fmtr $pkg $* /usr/doc/ratfor/m*
+       ;;
+m4)
+       $fmtr $pkg $* /usr/doc/m4 
+       ;;
+refer)
+       refer /usr/doc/refer/refer | tbl | $fmtr $pkg $*
+       ;;
+pub*)
+       tbl /usr/doc/refer/pubuse | $fmtr -rP1 $pkg $*
+       ;;
+lex)
+       tbl /usr/doc/lex | $fmtr -mcp $*
+       ;;
+tbl)
+       tbl /usr/doc/tbl | eqn | $fmtr $pkg $*
+       ;;
+ms*)
+       tbl /usr/doc/msmacros/ms | $fmtr $pkg $*
+       tbl /usr/doc/msmacros/refcard | eqn | $fmtr $*
+       ;;
+awk)
+       refer -e /usr/doc/awk | tbl | $fmtr $pkg $*
+       ;;
+adb)
+       $fmtr $pkg $* /usr/doc/adb/tut*
+       ;;
+password)
+       tbl /usr/doc/password | eqn | $fmtr $pkg $*
+       ;;
+secur*)
+       $fmtr $pkg $* /usr/doc/security
+       ;;
+uucp)
+       $fmtr $pkg $* /usr/doc/uucp/network
+       ;;
+uucpimp*)
+       $fmtr $pkg $* /usr/doc/uucp/implement
+       ;;
+iosys)
+       $fmtr $pkg $* /usr/doc/iosys 
+       ;;
+port|p*tour)
+       refer -e /usr/doc/porttour/p* | $fmtr $pkg $*
+       ;;
+setup)
+       $fmtr $pkg $* /usr/doc/setup
+       ;;
+regen)
+       $fmtr $pkg $* /usr/doc/regen
+       ;;
+learn)
+       refer -e /usr/doc/learn/p? | tbl | $fmtr $pkg $*
+       ;;
+*)
+       echo 'what is' $name 1>&2
+       ;;
+
+esac
diff --git a/doc/7thEdMan/vol2/security b/doc/7thEdMan/vol2/security
new file mode 100644 (file)
index 0000000..c1ae396
--- /dev/null
@@ -0,0 +1,351 @@
+.ND June 10, 1977
+.TL
+On the Security of UNIX
+.AU
+Dennis M. Ritchie
+.AI
+.MH
+.PP
+Recently there has been much interest in the security
+aspects of operating systems and software.
+At issue is the ability
+to prevent undesired
+disclosure of information, destruction of information,
+and harm to the functioning of the system.
+This paper discusses the degree of security which can be provided
+under the
+.UX
+system and offers a number of hints
+on how to improve security.
+.PP
+The first fact to face is that
+.UX
+was not developed with
+security, in any realistic sense, in mind;
+this fact alone guarantees a vast number of holes.
+(Actually the same statement can be made with respect
+to most systems.)
+The area of security in which
+.UX
+is theoretically weakest is
+in protecting against crashing or at least crippling
+the operation of the system.
+The problem here is not mainly in uncritical
+acceptance of bad parameters to system calls\(em
+there may be bugs in this area, but none are known\(em
+but rather in lack of checks for excessive
+consumption of resources.
+Most notably, there is no limit on the amount of disk
+storage used, either in total space allocated or in
+the number of files or directories.
+Here is a particularly ghastly shell sequence guaranteed
+to stop the system:
+.DS
+while : ; do
+       mkdir x
+       cd x
+done
+.DE
+Either a panic will occur because all the i-nodes
+on the device are used up, or all the disk blocks will
+be consumed, thus preventing anyone from writing files
+on the device.
+.PP
+In this version of the system,
+users are prevented from creating more than
+a set number of processes simultaneously,
+so unless users are in collusion it is unlikely that any one
+can stop the system altogether.
+However, creation of 20 or so CPU or disk-bound jobs
+leaves few resources available for others.
+Also, if many large jobs are run simultaneously,
+swap space may run out, causing a panic.
+.PP
+It should be evident that excessive consumption of disk
+space, files, swap space, and processes can easily occur
+accidentally in malfunctioning programs
+as well as at command level.
+In fact
+.UX
+is essentially defenseless against this kind of
+abuse,
+nor is there any easy fix.
+The best that can be said is that it is generally
+fairly
+easy to detect what has happened when disaster
+strikes,
+to identify the user responsible,
+and take appropriate action.
+In practice,
+we have found that difficulties
+in this area are rather rare,
+but we have not been faced with malicious users,
+and enjoy a fairly generous supply of
+resources which have served to cushion us against
+accidental overconsumption.
+.PP
+The picture is considerably brighter
+in the area of protection of information
+from unauthorized perusal and destruction.
+Here the degree of security seems (almost)
+adequate theoretically, and the problems lie
+more in the necessity for care in the actual use of
+the system.
+.PP
+Each
+.UX
+file has associated with it
+eleven bits of protection information
+together with a user identification number and a user-group
+identification number
+(UID and GID).
+Nine of the protection bits
+are used to specify independently
+permission to read, to write, and to execute the file
+to the user himself, to members of the user's
+group, and to all other users.
+Each process generated
+by or for a user has associated with
+it an effective UID and a real UID, and an effective and real GID.
+When an attempt is made
+to access the file for reading, writing, or execution,
+the user process's effective UID is compared
+against the file's UID; if a match is obtained,
+access is granted provided the read, write, or execute
+bit respectively for the user himself is
+present.
+If the UID for the file and for the process fail to match,
+but the GID's do match, the group bits are used; if the GID's
+do not match, the bits for other users are tested.
+The last two bits of each file's protection information,
+called the set-UID and set-GID bits,
+are used only when the
+file is executed as a program.
+If, in this case, the set-UID bit is on for the file,
+the effective UID for the process is changed to the UID
+associated with the file; the change persists
+until the process terminates or until the UID
+changed again by another execution of a set-UID file.
+Similarly the effective group ID of a process is changed
+to the GID associated with a file
+when that file is executed and has the set-GID bit set.
+The real UID and GID of a process do not change
+when any file is executed,
+but only as the result of a privileged system
+call.
+.PP
+The basic notion of the set-UID and set-GID
+bits is that one may write a program which is executable
+by others and which maintains files accessible to others only
+by that program.
+The classical example is the game-playing program which
+maintains records of the scores of its players.
+The program itself has to read and write the score file,
+but
+no one but the game's sponsor can be allowed
+unrestricted access to the file lest they manipulate
+the game to their own advantage.
+The solution is to
+turn on the set-UID bit of the
+game
+program.
+When, and only when, it is invoked
+by players of the game, it may update the score file
+but ordinary programs executed by others cannot
+access the score.
+.PP
+There are a number of special cases involved
+in determining access permissions.
+Since executing a directory as a program is a meaningless
+operation, the execute-permission
+bit, for directories, is taken instead to mean
+permission to search the directory for a given file
+during the scanning of a path name;
+thus if a directory has execute permission but no read
+permission for a given user, he may access files
+with known names in the directory,
+but may not read (list) the entire contents of the
+directory.
+Write permission on a directory is interpreted to
+mean that the user may create and delete
+files in that directory;
+it is impossible
+for any user to write directly into any directory.
+.PP
+Another, and from the point of view of security, much
+more serious special case is that there is a ``super user''
+who is able to read any file and write any non-directory.
+The super-user is also able to change the protection
+mode and the owner UID and GID of any file
+and to invoke privileged system calls.
+It must be recognized that the mere notion of
+a super-user is a theoretical, and usually
+practical, blemish on any protection scheme.
+.PP
+The first necessity for a secure system
+is of course arranging that all files and directories
+have the proper protection modes.
+Traditionally,
+.UX
+software has been exceedingly
+permissive in this regard;
+essentially all commands create files
+readable and writable by everyone.
+In the current version,
+this policy may be easily adjusted to suit the needs of
+the installation or the individual user.
+Associated with each process and its descendants
+is a mask, which is in effect
+.I and\fR\|-ed
+with the mode of every file and directory created by
+that process.
+In this way, users can arrange that, by default,
+all their files are no more accessible than they wish.
+The standard mask, set by
+.I login,
+allows all permissions to the user himself and to his group,
+but disallows writing by others.
+.PP
+To maintain both data privacy and
+data integrity,
+it is necessary, and largely sufficient,
+to make one's files inaccessible to others.
+The lack of sufficiency could follow
+from the existence of set-UID programs
+created by the user
+and the possibility of total
+breach of system security
+in one of the ways discussed below
+(or one of the ways not discussed below).
+For greater protection,
+an encryption scheme is available.
+Since the editor is able to create encrypted
+documents, and the
+.I crypt
+command can be used to pipe such documents into
+the other text-processing programs,
+the length of time during which cleartext versions
+need be available is strictly limited.
+The encryption scheme used is not one of the strongest
+known, but it is judged adequate, in the sense that
+cryptanalysis
+is likely to require considerably more effort than more direct
+methods of reading the encrypted files.
+For example, a user who stores data that he regards as truly secret
+should be aware that he is implicitly trusting the system
+administrator not to install a version of the crypt command
+that stores every typed password in a file.
+.PP
+Needless to say, the system administrators
+must be at least as careful as their most
+demanding user to place the correct
+protection mode on the files under their
+control.
+In particular,
+it is necessary that special files be protected
+from writing, and probably reading, by ordinary
+users when
+they store sensitive files belonging to other
+users.
+It is easy to write programs that examine and change
+files by accessing the device
+on which the files live.
+.PP
+On the issue of password security,
+.UX
+is probably better than most systems.
+Passwords are stored in an encrypted form
+which, in the absence of serious attention
+from specialists in the field,
+appears reasonably secure,
+provided its limitations are understood.
+In the current version, it is based on a slightly
+defective version of the Federal DES;
+it is purposely defective so that
+easily-available hardware is useless for attempts at exhaustive
+key-search.
+Since both the encryption algorithm and the encrypted passwords
+are available,
+exhaustive enumeration of potential passwords
+is still feasible up to a point.
+We have observed that users choose passwords that are easy to guess:
+they are short, or from a limited alphabet, or
+in a dictionary.
+Passwords should be
+at least six characters long and randomly chosen from an alphabet
+which includes digits and special characters.
+.PP
+Of course there also exist
+feasible non-cryptanalytic
+ways of finding out passwords.
+For example: write a program which types out ``login:\|''
+on the typewriter and copies whatever is typed
+to a file of your own.
+Then invoke the command and go away until the victim arrives.
+.PP
+The set-UID (set-GID)
+notion must be used carefully if any security is to be maintained.
+The first thing to keep in mind is that
+a writable set-UID file can have another program copied onto it.
+For example, if the super-user
+.I (su)
+command is writable,
+anyone can copy the shell
+onto it and get a password-free version
+of
+.I su.
+A more subtle problem
+can come from
+set-UID programs which are not sufficiently
+careful of what is fed into them.
+To take an obsolete example,
+the previous version of the
+.I mail
+command was set-UID and owned by the super-user.
+This version sent mail to the recipient's own directory.
+The notion was that one should be able to send
+mail to anyone even if they want to protect
+their directories from writing.
+The trouble was that
+.I mail
+was rather dumb:
+anyone could mail someone else's private file to himself.
+Much more serious
+is the following scenario:
+make a file with a line like one in the password file
+which allows one to log in as the super-user.
+Then make a link named ``.mail'' to the password file
+in some writable
+directory on the same device as the password file (say /tmp).
+Finally mail the bogus login line to /tmp/.mail;
+You can then login as the super-user,
+clean up the incriminating evidence,
+and have your will.
+.PP
+The fact that users can mount their own disks and tapes
+as file systems
+can be another way of gaining super-user status.
+Once a disk pack is mounted, the system believes
+what is on it.
+Thus one can take a blank disk pack,
+put on it anything desired,
+and mount it.
+There are obvious and unfortunate consequences.
+For example:
+a mounted disk with garbage on it will crash the
+system;
+one of the files on the mounted disk can easily be
+a password-free version of
+.I su;
+other files can be unprotected entries for special files.
+The only easy fix for this problem is to
+forbid the use of
+.I mount
+to unprivileged users.
+A partial solution, not so restrictive,
+would be to have the
+.I mount
+command examine the special file for bad data,
+set-UID programs owned by others, and accessible
+special files,
+and balk at unprivileged invokers.
diff --git a/doc/7thEdMan/vol2/sed b/doc/7thEdMan/vol2/sed
new file mode 100644 (file)
index 0000000..e0333b3
--- /dev/null
@@ -0,0 +1,1259 @@
+.hw de-limit
+.hw de-limit-ing
+.RP
+....TM 78-1270-1 39199 39199-11
+.ND August 15, 1978
+.TL
+SED \(em A Non-interactive Text Editor
+.AU "MH 2C-555" 3302
+Lee E. McMahon
+.AI
+.MH
+.OK
+Context search
+Editing
+.AB
+.ul
+Sed
+is a non-interactive context editor
+that runs on the
+.UX
+operating system.
+.ul
+Sed
+is
+designed to be especially useful in
+three cases:
+.in +1i
+.LP
+.ti -.5i
+1)
+To edit files too large for comfortable
+interactive editing;
+.ti -.5i
+2)
+To edit any size file when the sequence
+of editing commands is too complicated to be comfortably
+typed in interactive mode.
+.ti -.5i
+3)
+To perform multiple `global' editing functions
+efficiently in one pass through the input.
+.in -1i
+.LP
+This memorandum constitutes a manual for users of
+.ul
+sed.
+.AE
+.CS 10 0 10 0 0 1
+.SH
+Introduction
+.LP
+.ul
+Sed
+is a non-interactive context editor designed to be especially useful in
+three cases:
+.in +1i
+.LP
+.ti -.5i
+1)
+To edit files too large for comfortable
+interactive editing;
+.ti -.5i
+2)
+To edit any size file when the sequence
+of editing commands is too complicated to be comfortably
+typed in interactive mode;
+.ti -.5i
+3)
+To perform multiple `global' editing functions
+efficiently in one pass through the input.
+.in -1i
+.LP
+Since only a few lines of the input reside in core
+at one time, and no temporary files are used,
+the effective size of file that can be edited is limited only
+by the requirement that the input and output fit simultaneously
+into available secondary storage.
+.LP
+Complicated editing scripts can be created separately and given
+to 
+.ul
+sed
+as a command file.
+For complex edits, this saves considerable typing, and its
+attendant errors.
+.ul
+Sed
+running from a command file is much more efficient than any interactive
+editor known to the author, even if that editor
+can be driven by a pre-written script.
+.LP
+The principal loss of functions compared to an interactive editor
+are lack of relative addressing (because of the line-at-a-time
+operation), and lack of immediate verification that a command has
+done what was intended.
+.LP
+.ul
+Sed
+is a lineal descendant of the UNIX editor,
+.ul
+ed.
+Because of the differences between interactive and non-interactive
+operation, considerable changes have been made between
+.ul
+ed
+and
+.ul
+sed;
+even confirmed users of
+.ul
+ed
+will frequently be surprised (and probably chagrined),
+if they rashly use 
+.ul
+sed
+without reading Sections 2 and 3 of this document.
+The most striking family resemblance between the two
+editors is in the class of patterns (`regular expressions') they
+recognize;
+the code for matching patterns is copied almost
+verbatim from the code for
+.ul
+ed,
+and the description of regular expressions in Section 2
+is copied almost verbatim from the UNIX Programmer's
+Manual[1]. (Both code and description were written by Dennis
+M. Ritchie.)
+.LP
+.SH
+1. Overall Operation
+.LP
+.ul
+Sed
+by default copies the standard input to the standard output,
+perhaps performing one or more editing commands on each
+line before writing it to the output.
+This behavior may be modified by flags on the command line;
+see Section 1.1 below.
+.LP
+The general format of an editing command is:
+.LP
+.in +1i
+[address1,address2][function][arguments]
+.LP
+.in -1i
+One or both addresses may be omitted; the format of addresses is
+given in Section 2.
+Any number of blanks or tabs may separate the addresses
+from the function.
+The function must be present; the available commands are discussed
+in Section 3.
+The arguments may be required or optional, according to which function
+is given; again, they are discussed in Section 3 under each individual
+function.
+.LP
+Tab characters and spaces at the beginning of lines are ignored.
+.LP
+.SH
+1.1. Command-line Flags
+.LP
+Three flags are recognized on the command line:
+.in +1i
+.ti -.5i
+.B
+-n:
+.R
+tells
+.ul
+sed
+not to copy all lines, but only those specified by
+.ul
+p
+functions or
+.ul
+p
+flags after 
+.ul
+s
+functions (see Section 3.3);
+.ti -.5i
+.B
+-e:
+.R
+tells
+.ul
+sed
+to take the next argument as an editing command;
+.ti -.5i
+.B
+-f:
+.R
+tells
+.ul
+sed
+to take the next argument as a file name;
+the file should contain editing commands, one to a line.
+.in -1i
+.SH
+1.2. Order of Application of Editing Commands
+.LP
+Before any editing is done (in fact, before any input file is
+even opened), all the editing commands are compiled into
+a form which will be moderately efficient during
+the execution phase (when the commands are actually applied to
+lines of the input file).
+The commands are compiled in the order in which they are
+encountered; this is generally the order in which they will
+be attempted at execution time.
+The commands are applied one at a time; the input to each command
+is the output of all preceding commands.
+.LP
+The default linear order of application of editing commands can
+be changed by the flow-of-control commands,
+.ul
+t
+and
+.ul
+b
+(see Section 3).
+Even when the order of application is changed
+by these commands, it is still true that the input line to any
+command is the output of any previously applied command.
+.SH
+1.3.  Pattern-space
+.LP
+The range of pattern matches is called the pattern space.
+Ordinarily, the pattern space is one line of the input text,
+but more than one line can be read into the pattern space
+by using the
+.ul
+N
+command (Section 3.6.).
+.LP
+.SH
+1.4. Examples
+.LP
+Examples are scattered throughout the text.
+Except where otherwise noted,
+the examples all assume the following input text:
+.LP
+.in +.5i
+.nf
+In Xanadu did Kubla Khan
+A stately pleasure dome decree:
+Where Alph, the sacred river, ran
+Through caverns measureless to man
+Down to a sunless sea.
+.in -.5i
+.fi
+.LP
+(In no case is the output of the 
+.ul
+sed
+commands to be considered an improvement
+on Coleridge.)
+.LP
+.SH
+Example:
+.LP
+The command
+.in +.5i
+.LP
+2q
+.in -.5i
+.LP
+will quit after copying the first two lines of the input.
+The output will be:
+.LP
+.in +.5i
+.nf
+In Xanadu did Kubla Khan
+A stately pleasure dome decree:
+.in -.5i
+.fi
+.LP
+.SH
+2. ADDRESSES: Selecting lines for editing
+.LP
+Lines in the input file(s) to which editing commands are
+to be applied can be selected by addresses.
+Addresses may be either line numbers or context addresses.
+.LP
+The application of a group of commands can be controlled by
+one address (or address-pair) by grouping
+the commands with curly braces (`{ }')(Sec. 3.6.).
+.SH
+2.1. Line-number Addresses
+.LP
+A line number is a decimal integer.
+As each line is read from the input, a line-number counter
+is incremented;
+a line-number address matches (selects) the input
+line which causes the internal counter to equal the
+address line-number.
+The counter runs cumulatively through multiple input files;
+it is not reset when a new input file is opened.
+.LP
+As a special case, the character
+$
+matches the last line of the last input file.
+.SH
+2.2. Context Addresses
+.LP
+A context address is a pattern (`regular expression') enclosed in slashes (`/').
+The regular expressions recognized by
+.ul
+sed
+are constructed as follows:
+.in +1i
+.LP
+.ti -.5i
+1)
+An ordinary character (not one of those discussed below)
+is a regular expression, and matches that character.
+.LP
+.ti -.5i
+2)
+A circumflex `^' at the beginning of a regular expression
+matches the null character at the beginning of a line.
+.ti -.5i
+3)
+A dollar-sign `$' at the end of a regular expression
+matches the null character at the end of a line.
+.ti -.5i
+4)
+The characters `\en' match an imbedded newline character,
+but not the newline at the end of the pattern space.
+.ti -.5i
+5)
+A period `.' matches any character except the terminal newline
+of the pattern space.
+.ti -.5i
+6)
+A regular expression followed by an asterisk `*' matches any
+number (including 0) of adjacent occurrences of the regular
+expression it follows.
+.ti -.5i
+7)
+A string of characters in square brackets `[ ]' matches any character
+in the string, and no others.
+If, however, the first character of the string is circumflex `^',
+the regular expression matches any character
+.ul
+except
+the characters in the string and the terminal newline of the pattern space.
+.ti -.5i
+8)
+A concatenation of regular expressions is a regular expression
+which matches the concatenation of strings matched by the
+components of the regular expression.
+.ti -.5i
+9)
+A regular expression between the sequences `\e(' and `\e)' is
+identical in effect to the unadorned regular expression, but has
+side-effects which are described under the
+.ul
+s
+command below and specification 10) immediately below.
+.ti -.5i
+10)
+The expression
+.ul
+`\|\ed'
+means the same string of characters matched
+by an expression enclosed in `\e(' and `\e)'
+earlier in the same pattern.
+Here
+.ul
+d
+is a single digit;
+the string specified is that beginning with the
+\fId\|\fRth
+occurrence of `\e(' counting from the left.
+For example, the expression
+`^\e(.*\e)\e1' matches a line beginning with
+two repeated occurrences of the same string.
+.ti -.5i
+11)
+The null regular expression standing alone (e.g., `//') is
+equivalent to the  last regular expression compiled.
+.in -1i
+.LP
+To use one of the special characters (^ $ . * [ ] \e /) as a literal
+(to match an occurrence of itself in the input), precede the
+special character by a backslash `\e'.
+.LP
+For a context address to `match' the input requires that
+the whole pattern within the address match some
+portion of the pattern space.
+.SH
+2.3. Number of Addresses
+.LP
+The commands in the next section can have 0, 1, or 2 addresses.
+Under each command the maximum number of allowed addresses is
+given.
+For a command to have more addresses than the maximum allowed
+is considered an error.
+.LP
+If a command has no addresses, it is applied to every line
+in the input.
+.LP
+If a command has one address, it is applied to all
+lines which match that address.
+.LP
+If a command has two addresses, it is applied to the first
+line which matches the first address, and to all subsequent lines
+until (and including) the first subsequent line which matches
+the second address.
+Then an attempt is made on subsequent lines to again match the first
+address, and the process is repeated.
+.LP
+Two addresses are separated by a comma.
+.SH
+Examples:
+.LP
+.nf
+.in +.5i
+.ta 1i 2i
+/an/   matches lines 1, 3, 4 in our sample text
+/an.*an/       matches line 1
+/^an/  matches no lines
+/./    matches all lines
+/\e./  matches line 5
+/r*an/ matches lines 1,3, 4 (number = zero!)
+/\e(an\e).*\e1/        matches line 1
+.fi
+.in 0
+.LP
+.SH
+3. FUNCTIONS
+.LP
+All functions are named by a single character.
+In the following summary, the maximum number of allowable addresses
+is given enclosed in parentheses, then the single character
+function name, possible arguments enclosed in angles (< >),
+an expanded English translation of the single-character name,
+and finally a description of what each function does.
+The angles around the arguments are
+.ul
+not
+part of the argument, and should not be typed
+in actual editing commands.
+.SH
+3.1. Whole-line Oriented Functions
+.LP
+.in +1i
+.ti -.5i
+(2)d -- delete lines
+.if t .sp .5
+The
+.ul
+d
+function deletes from the file (does not write to the output)
+all those lines matched by its address(es).
+.if t .sp .5
+It also has the side effect that no further commands are attempted
+on the corpse of a deleted line;
+as soon as the
+.ul
+d
+function is executed, a new line is read from the input, and
+the list of editing commands is re-started from the beginning
+on the new line.
+.ti -.5i
+.if t .sp .5
+(2)n -- next line
+.if t .sp .5
+The
+.ul
+n
+function reads the next line from the input, replacing
+the current line.
+The current line is written to the output if it should
+be.
+The list of editing commands is continued 
+following the 
+.ul
+n
+command.
+.if t .sp .5
+.nf
+.in -.5i
+(1)a\e
+<text> -- append lines
+.in +.5i
+.fi
+.if t .sp .5
+The
+.ul
+a
+function causes the argument <text> to be written to the
+output after the line matched by its address.
+The
+.ul
+a
+command is inherently multi-line;
+.ul
+a
+must appear at the end of a line, and <text> may contain
+any number of lines.
+To preserve the one-command-to-a-line fiction,
+the interior newlines must be hidden by a
+backslash character (`\e') immediately preceding the
+newline.
+The <text> argument is terminated by the first unhidden
+newline (the first one not immediately preceded
+by backslash).
+.if t .sp .5
+Once an
+.ul
+a
+function is successfully executed, <text> will be
+written to the output regardless of what later commands do to
+the line which triggered it.
+The triggering line may be 
+deleted entirely; <text> will still be written to the output.
+.if t .sp .5
+The <text> is not scanned for address matches, and no editing
+commands are attempted on it.
+It does not cause any change in the line-number counter.
+.if t .sp .5
+.nf
+.in -.5i
+(1)i\e
+<text> -- insert lines
+.in +.5i
+.fi
+.if t .sp .5
+The
+.ul
+i
+function  behaves identically to the
+.ul
+a
+function, except that <text> is written to the output
+.ul
+before
+the matched line.
+All other comments about the
+.ul
+a
+function apply to the
+.ul
+i
+function as well.
+.if t .sp .5
+.nf
+.in -.5i
+(2)c\e
+<text> -- change lines
+.in +.5i
+.fi
+.if t .sp .5
+The
+.ul
+c
+function deletes the lines selected by its address(es),
+and replaces them with the lines in <text>.
+Like
+.ul
+a
+and
+.ul
+i,
+.ul
+c
+must be followed by a newline hidden by a backslash;
+and interior new lines in <text> must be hidden by
+backslashes.
+.if t .sp .5
+The
+.ul
+c
+command may have two addresses, and therefore select a range
+of lines.
+If it does, all the lines in the range are deleted, but only
+one copy of <text> is written to the output,
+.ul
+not
+one copy per line deleted.
+As with
+.ul
+a
+and
+.ul
+i,
+<text> is not scanned for address matches, and no
+editing commands are attempted on it.
+It does not change the  line-number counter.
+.if t .sp .5
+After a line has been deleted by a
+.ul
+c
+function, no further commands are attempted on the corpse.
+.if t .sp .5
+If text is appended after a line by
+.ul
+a
+or
+.ul
+r
+functions, and the line is subsequently changed, the text
+inserted by the
+.ul
+c
+function will be placed
+.ul
+before
+the text of the
+.ul
+a
+or
+.ul
+r
+functions.
+(The
+.ul
+r
+function is described in Section 3.4.)
+.if t .sp .5
+.in -1i
+.ul
+Note:
+Within the text put in the output by these functions,
+leading blanks and tabs will disappear, as always in 
+.ul
+sed
+commands.
+To get leading blanks and tabs into the output, precede the first
+desired blank or tab by a backslash; the backslash will not
+appear in the output.
+.SH
+Example:
+.LP
+The list of editing commands:
+.LP
+.in +.5i
+.nf
+n
+a\e
+XXXX
+d
+.in -.5i
+.fi
+.LP
+applied to our standard input, produces:
+.LP
+.in +.5i
+.nf
+In Xanadu did Kubhla Khan
+XXXX
+Where Alph, the sacred river, ran
+XXXX
+Down to a sunless sea.
+.in -.5i
+.fi
+.LP
+In this particular case,
+the same effect would be produced by either
+of the two following command lists:
+.LP
+.in +.5i
+.nf
+n              n
+i\e            c\e
+XXXX   XXXX
+d
+.in -.5i
+.fi
+.LP
+.in 0
+.SH
+3.2. Substitute Function
+.LP
+One very important function changes parts of lines selected by
+a context search within the line.
+.if t .sp .5
+.in +1i
+.ti -.5i
+(2)s<pattern><replacement><flags> -- substitute
+.if t .sp .5
+The
+.ul
+s
+function replaces
+.ul
+part
+of a line (selected by <pattern>) with <replacement>.
+It can best be read:
+.if t .sp .5
+.ti +1i
+Substitute for <pattern>, <replacement>
+.if t .sp .5
+The <pattern> argument contains a pattern,
+exactly like the patterns in addresses (see 2.2 above).
+The only difference between <pattern> and a context address is
+that the context address must be delimited by slash (`/') characters;
+<pattern> may be delimited by any character other than space or
+newline.
+.if t .sp .5
+By default, only the first string matched by <pattern> is replaced,
+but see the
+.ul
+g
+flag below.
+.if t .sp .5
+The
+<replacement> argument begins immediately after the
+second delimiting character of <pattern>, and must be followed
+immediately by another instance of the delimiting character.
+(Thus there are exactly 
+.ul
+three
+instances of the delimiting character.)
+.if t .sp .5
+The <replacement> is not a pattern,
+and the characters which are special in patterns
+do not have special meaning in <replacement>.
+Instead, other characters are special:
+.if t .sp .5
+.in +1i
+.ti -.5i
+&      is replaced by the string matched by <pattern>
+.if t .sp .5
+.ti -.5i
+.ul
+\ed
+(where
+.ul
+d
+is a single digit) is replaced by the \fId\fRth substring
+matched by parts of <pattern> enclosed in `\e(' and `\e)'.
+If nested substrings occur in <pattern>, the \fId\fRth
+is determined by counting opening delimiters (`\e(').
+.if t .sp .5
+As in patterns, special characters may be made
+literal by preceding them with backslash (`\e').
+.if t .sp .5
+.in -1i
+The <flags> argument may contain the following flags:
+.if t .sp .5
+.in +1i
+.ti -.5i
+g -- substitute <replacement> for all (non-overlapping)
+instances of <pattern> in the line.
+After a successful substitution, the scan for the next
+instance of <pattern> begins just after the end of the
+inserted characters; characters put into the line from
+<replacement> are not rescanned.
+.if t .sp .5
+.ti -.5i
+p -- print the line if a successful replacement was done.
+The
+.ul
+p
+flag causes the line to be written to the output if and only
+if a substitution was actually made by the
+.ul
+s
+function.
+Notice that if several
+.ul
+s
+functions, each followed by a
+.ul
+p
+flag, successfully substitute in the same input line,
+multiple copies of the line will be written to the
+output: one for each successful substitution.
+.if t .sp .5
+.ti -.5i
+w <filename> -- write the line to a file if a successful
+replacement was done.
+The
+.ul
+w
+flag causes lines which are actually substituted by the
+.ul
+s
+function to be written to a file named by <filename>.
+If <filename> exists before
+.ul
+sed
+is run, it is overwritten;
+if not, it is created.
+.if t .sp .5
+A single space must separate
+.ul
+w
+and <filename>.
+.if t .sp .5
+The possibilities of multiple, somewhat different copies of
+one input line being written are the same as for 
+.ul
+p.
+.if t .sp .5
+A maximum of 10 different file names may be mentioned after
+.ul
+w
+flags and
+.ul
+w
+functions (see below), combined.
+.in 0
+.SH
+Examples:
+.LP
+The following command, applied to our standard input,
+.LP
+.in +.5i
+s/to/by/w changes
+.in -.5i
+.LP
+produces, on the standard output:
+.LP
+.in +.5i
+.nf
+In Xanadu did Kubhla Khan
+A stately pleasure dome decree:
+Where Alph, the sacred river, ran
+Through caverns measureless by man
+Down by a sunless sea.
+.fi
+.in -.5i
+.LP
+and, on the file `changes':
+.LP
+.in +.5i
+.nf
+Through caverns measureless by man
+Down by a sunless sea.
+.fi
+.in -.5i
+.LP
+If the nocopy option is in effect, the command:
+.LP
+.in +.5i
+.nf
+s/[.,;?:]/*P&*/gp
+.fi
+.in -.5i
+.LP
+produces:
+.LP
+.in +.5i
+.nf
+A stately pleasure dome decree*P:*
+Where Alph*P,* the sacred river*P,* ran
+Down to a sunless sea*P.*
+.LP
+.in -.5i
+.fi
+Finally, to illustrate the effect of the
+.ul
+g
+flag,
+the command:
+.LP
+.in +.5i
+.nf
+/X/s/an/AN/p
+.in -.5i
+.fi
+.LP
+produces (assuming nocopy mode):
+.in +.5i
+.LP
+.nf
+In XANadu did Kubhla Khan
+.fi
+.in -.5i
+.LP
+and the command:
+.LP
+.in +.5i
+.nf
+/X/s/an/AN/gp
+.in -.5i
+.fi
+.LP
+produces:
+.LP
+.in +.5i
+.nf
+In XANadu did Kubhla KhAN
+.in -.5i
+.fi
+.LP
+.in 0
+.SH
+3.3. Input-output Functions
+.LP
+.in +1i
+.ti -.5i
+(2)p -- print
+.if t .sp .5
+The print function writes the addressed lines to the standard output file.
+They are written at the time the
+.ul
+p
+function is encountered, regardless of what succeeding
+editing commands may do to the lines.
+.if t .sp .5
+.ti -.5i
+(2)w <filename> -- write on <filename>
+.if t .sp .5
+The write function writes the addressed lines to the file named
+by <filename>.
+If the file previously existed, it is overwritten; if not, it is created.
+The lines are written exactly as they exist when the write function
+is encountered for each line, regardless of what subsequent
+editing commands may do to them.
+.if t .sp .5
+Exactly one space must separate the
+.ul
+w
+and <filename>.
+.if t .sp .5
+A maximum of ten different files may be mentioned in write
+functions and
+.ul
+w
+flags after
+.ul
+s
+functions, combined.
+.if t .sp .5
+.ti -.5i
+(1)r <filename> -- read the contents of a file
+.if t .sp .5
+The read function reads the contents of <filename>, and appends
+them after the line matched by the address.
+The file is read and appended regardless of what subsequent
+editing commands do to the line which matched its address.
+If
+.ul
+r
+and
+.ul
+a
+functions are executed on the same line,
+the text from the 
+.ul
+a
+functions and the
+.ul
+r
+functions is written to the output in the order that
+the functions are executed.
+.if t .sp .5
+Exactly one space must separate the
+.ul
+r
+and <filename>.
+If a file mentioned by a
+.ul
+r
+function cannot be opened, it is considered a null file,
+not an error, and no diagnostic is given.
+.if t .sp .5
+.in -1i
+NOTE:
+Since there is a limit to the number of files that can be opened
+simultaneously, care should be taken that no more than ten
+files be mentioned in
+.ul
+w
+functions or flags; that number is reduced by one if any
+.ul
+r
+functions are present.
+(Only one read file is open at one time.)
+.in 0
+.SH
+Examples
+.LP
+Assume that the file `note1'
+has the following contents:
+.LP
+.in +1i
+Note:  Kubla Khan (more properly Kublai Khan; 1216-1294)
+was the grandson and most eminent successor of Genghiz
+(Chingiz) Khan, and founder of the Mongol dynasty in China.
+.LP
+.in 0
+Then the following command:
+.LP
+.nf
+.in +.5i
+/Kubla/r note1
+.in -.5i
+.fi
+.LP
+produces:
+.LP
+.nf
+.in +.5i
+In Xanadu did Kubla Khan
+.in +.5i
+.fi
+Note:  Kubla Khan (more properly Kublai Khan; 1216-1294)
+was the grandson and most eminent successor of Genghiz
+(Chingiz) Khan, and founder of the Mongol dynasty in China.
+.in -.5i
+.nf
+A stately pleasure dome decree:
+Where Alph, the sacred river, ran
+Through caverns measureless to man
+Down to a sunless sea.
+.in -.5i
+.fi
+.LP
+.in 0
+.SH
+3.4.
+Multiple Input-line Functions
+.LP
+Three functions, all spelled with capital letters, deal
+specially with pattern spaces containing imbedded newlines;
+they are intended principally to provide pattern matches across
+lines in the input.
+.if t .sp .5
+.in +1i
+.ti -.5i
+(2)N -- Next line
+.if t .sp .5
+The next input line is appended to the current line in the
+pattern space; the two input lines are separated by an imbedded
+newline.
+Pattern matches may extend across the imbedded newline(s).
+.if t .sp .5
+.ti -.5i
+(2)D -- Delete first part of the pattern space
+.if t .sp .5
+Delete up to and including the first newline character
+in the current pattern space.
+If the pattern space becomes empty (the only newline
+was the terminal newline),
+read another line from the input.
+In any case, begin the list of editing commands again
+from its beginning.
+.if t .sp .5
+.ti -.5i
+(2)P -- Print first part of the pattern space
+.if t .sp .5
+Print up to and including the first newline in the pattern space.
+.if t .sp .5
+.in 0
+The 
+.ul
+P
+and
+.ul
+D
+functions are equivalent to their lower-case counterparts
+if there are no imbedded newlines in the pattern space.
+.in 0
+.SH
+3.5.  Hold and Get Functions
+.LP
+Four functions save and retrieve part of the input for possible later
+use.
+.if t .sp .5
+.in 1i
+.ti -.5i
+(2)h -- hold pattern space
+.if t .sp .5
+The
+.ul
+h
+functions copies the contents of the pattern space
+into a hold area (destroying the previous contents of the
+hold area).
+.if t .sp .5
+.ti -.5i
+(2)H -- Hold pattern space
+.if t .sp .5
+The
+.ul
+H
+function appends the contents of the pattern space
+to the contents of the hold area; the former and new contents
+are separated by a newline.
+.if t .sp .5
+.ti -.5i
+(2)g -- get contents of hold area
+.if t .sp .5
+The
+.ul
+g
+function copies the contents of the hold area into
+the pattern space (destroying the previous contents of the
+pattern space).
+.if t .sp .5
+.ti -.5i
+(2)G -- Get contents of hold area
+.if t .sp .5
+The
+.ul
+G
+function appends the contents of the hold area to the
+contents of the pattern space; the former and new contents are separated by
+a newline.
+.if t .sp .5
+.ti -.5i
+(2)x -- exchange
+.if t .sp .5
+The exchange command interchanges the contents
+of the pattern space and the hold area.
+.in 0
+.SH
+Example
+.LP
+The commands
+.nf
+.if t .sp .5
+       1h
+       1s/ did.*//
+       1x
+       G
+       s/\en/  :/
+.if t .sp .5
+.fi
+applied to our standard example, produce:
+.nf
+.if t .sp .5
+       In Xanadu did Kubla Khan  :In Xanadu
+       A stately pleasure dome decree:  :In Xanadu
+       Where Alph, the sacred river, ran  :In Xanadu
+       Through caverns measureless to man  :In Xanadu
+       Down to a sunless sea.  :In Xanadu
+.if t .sp .5
+.fi
+.SH
+3.6.  Flow-of-Control Functions
+.LP
+These functions do no editing on the input
+lines, but control the application of functions
+to the lines selected by the address part.
+.if t .sp .5
+.in +1i
+.ti -.5i
+(2)! -- Don't
+.if t .sp .5
+The
+.ul
+Don't
+command causes the next command
+(written on the same line), to be applied to all and only those input lines
+.ul
+not
+selected by the adress part.
+.if t .sp .5
+.ti -.5i
+(2){ -- Grouping
+.if t .sp .5
+The grouping command `{' causes the
+next set of commands to be applied
+(or not applied) as a block to the
+input lines selected by the addresses
+of the grouping command.
+The first of the commands under control of the grouping
+may appear on the same line as the
+`{' or on the next line.
+.LP
+The group of commands is terminated by a
+matching `}' standing on a line by itself.
+.LP
+Groups can be nested.
+.ti -.5i
+.if t .sp .5
+(0):<label> -- place a label
+.if t .sp .5
+The label function marks a place in the list
+of editing commands which may be referred to by
+.ul
+b
+and
+.ul
+t
+functions.
+The <label> may be any sequence of eight or fewer characters;
+if two different colon functions have identical labels,
+a compile time diagnostic will be generated, and
+no execution attempted.
+.if t .sp .5
+.ti -.5i
+(2)b<label> -- branch to label
+.if t .sp .5
+The branch function causes  the sequence of editing commands being
+applied to the current input line to be restarted immediately
+after the place where a colon function with the same <label>
+was encountered.
+If no colon function with the same label can be found after
+all the editing commands have been compiled, a compile time diagnostic
+is produced, and no execution is attempted.
+.if t .sp .5
+A
+.ul
+b
+function with no <label> is taken to be a branch to the end of the
+list of editing commands;
+whatever should be done with the current input line is done, and
+another input line is read; the list of editing commands is restarted from the
+beginning on the new line.
+.if t .sp .5
+.ti -.5i
+(2)t<label> -- test substitutions
+.if t .sp .5
+The
+.ul
+t
+function tests whether 
+.ul
+any
+successful substitutions have been made on the current input
+line;
+if so, it branches to <label>;
+if not, it does nothing.
+The flag which indicates that a successful substitution has
+been executed is reset by:
+.if t .sp .5
+.in +1i
+1) reading a new input line, or
+.br
+2) executing a
+.ul
+t
+function.
+.if t .sp .5
+.in 0
+.SH
+3.7. Miscellaneous Functions
+.LP
+.in +1i
+.ti -.5i
+(1)= -- equals
+.if t .sp .5
+The = function writes to the standard output the line number of the
+line matched by its address.
+.if t .sp .5
+.ti -.5i
+(1)q -- quit
+.if t .sp .5
+The
+.ul
+q
+function causes the current line to be written to the
+output (if it should be), any appended or read text to be written, and
+execution to be terminated.
+.in 0
+.SH
+.SH
+Reference
+.IP [1]
+Ken Thompson and Dennis M. Ritchie,
+.ul
+The UNIX Programmer's Manual.
+Bell Laboratories, 1978.
diff --git a/doc/7thEdMan/vol2/setup b/doc/7thEdMan/vol2/setup
new file mode 100644 (file)
index 0000000..107b8ec
--- /dev/null
@@ -0,0 +1,787 @@
+.TL
+Setting Up
+Unix
+\- Seventh Edition
+.AU
+Charles B. Haley
+Dennis M. Ritchie
+.AI
+.MH
+.PP
+The distribution tape can be used only on a DEC PDP11/45
+or PDP11/70 with RP03, RP04, RP05, RP06 disks and with
+a TU10, TU16, or TE16 tape drive.
+It consists of some preliminary bootstrapping programs followed by
+two file system images;
+if needed, after the initial construction of the file systems
+individual files can be extracted. (See restor(1))
+.PP
+If you are set up to do it,
+it might be a good idea immediately to make a copy of the
+tape to guard against disaster.
+The tape is 9-track 800 BPI and contains some 512-byte records
+followed by many 10240-byte records.
+There are interspersed tapemarks.
+.PP
+The system as distributed contains binary images
+of the system and all the user level programs, along with source
+and manual sections for them\(emabout
+2100 files altogether.
+The binary images,
+along with other
+things needed to flesh out the file system enough so UNIX will run,
+are to be put on one file system called the `root file system'.
+The file system size required is about 5000 blocks.
+The file second system has all of the source and documentation.
+Altogether it amounts to more than 18,000 512-byte blocks.
+.SH
+Making a Disk From Tape
+.PP
+Perform the following bootstrap procedure to obtain
+a disk with a root file system on it.
+.IP 1.
+Mount the magtape on drive 0 at load point.
+.IP 2.
+Mount a formatted disk pack on drive 0.
+.IP 3.
+Key in and execute at 100000
+.RT
+.DS
+  TU10                   TU16/TE16
+012700                 Use the DEC ROM or other
+172526                 means to load block 1
+010040                 (i.e. second block) at 800 BPI
+012740                 into location 0 and transfer
+060003                 to 0.
+000777
+.DE
+.IP
+The tape should move and the CPU loop.
+(The TU10 code is
+.I
+not
+.R
+the DEC bulk ROM for tape;
+it reads block 0, not block 1.)
+.IP 4.
+If you used the above TU10 code, halt and restart the
+CPU at 0, otherwise continue to the next step.
+.IP 5.
+The console should type
+.DS
+.I
+Boot
+:
+.R
+.DE
+Copy the magtape to disk by the following procedure.
+The machine's printouts are shown in italic,
+explanatory comments are within ( ).
+Terminate each line you type by carriage return or line-feed.
+There are two classes of tape drives:
+the name `tm' is used for the TU10, and `ht' is used for
+the TU16 or TE16.
+There are also two classes of disks:
+`rp' is used for the RP03, and `hp' is used for the
+RP04/5/6.
+.PP
+If you should make a mistake while typing, the character '#'
+erases the last character typed up to the beginning of the line,
+and the character '@' erases the entire line typed.
+Some consoles cannot print lower case letters, adjust the
+instructions accordingly.
+.DS
+(bring in the program mkfs)
+\fI:\|\fRtm(0,3)               (use `ht(0,3)' for the TU16/TE16)
+\fIfile system size:\fR 5000
+\fIfile system:\fR rp(0,0)             (use `hp(0,0)' for RP04/5/6)
+.I
+isize = XX
+m/n = XX
+.R
+(after a while)
+.I
+exit called
+Boot
+:
+.R
+.DE
+This step makes an empty file system.
+.IP 6.
+The next thing to do is to restore the data
+onto the new empty file system. To do this you respond to
+the `\fI:\fR' printed in the last step with
+.DS
+(bring in the program restor)
+\fI:\|\fRtm(0,4)               (`ht(0,4)' for TU16/TE16)
+\fItape?\fR tm(0,5)    (use `ht(0,5)' for TU16/TE16)
+\fIdisk?\fR rp(0,0)            (use `hp(0,0)' for RP04/5/6)
+\fILast chance before scribbling on disk.\fR (you type return)
+(the tape moves, perhaps 5-10 minutes pass)
+\fIend of tape\fR
+.I
+Boot
+:
+.R
+.DE
+You now have a UNIX root file system.
+.SH
+Booting UNIX
+.PP
+You probably have
+the bootstrap running, left over from the last step above;
+if not,
+repeat the boot process (step 3) again.
+Then use one of the following:
+.DS
+\fI:\|\fRrp(0,0)rptmunix               (for RP03 and TU10)
+\fI:\|\fRrp(0,0)rphtunix               (for RP03 and TU16/TE16)
+\fI:\|\fRhp(0,0)hptmunix               (for RP04/5/6 and TU10)
+\fI:\|\fRhp(0,0)hphtunix               (for RP04/5/6 and TU16/TE16)
+.DE
+The machine should type the following:
+.DS
+.I
+mem = xxx
+#
+.R
+.DE
+The
+.I
+mem
+.R
+message gives the memory available to user programs
+in bytes.
+.PP
+UNIX is now running,
+and the `UNIX Programmer's manual' applies;
+references below of the form X(Y) mean the subsection named
+X in section Y of the manual.
+The `#' is the prompt from the Shell,
+and indicates you are the super-user.
+The user name of the super-user is `root'
+if you should find yourself in multi-user mode and
+need to log in;
+the password is also `root'.
+.PP
+To simplify your life later, rename the appropriate version
+of the system as specified above plain `unix.'
+For example, use mv (1) as follows if you have an RP04/5/6 and
+a TU16 tape:
+.DS
+mv hphtunix unix
+.DE
+In the future, when you reboot,
+you can type just
+.DS
+hp(0,0)unix
+.DE
+to the `:' prompt.
+(Choose appropriately among `hp', `rp', `ht', `tm'
+according to your configuration).
+.PP
+You now need to make some special file entries
+in the dev directory. These specify what sort of disk you
+are running on, what sort of tape drive you have,
+and where the file systems are. 
+For simplicity, this recipe creates fixed device names.
+These names will be used below, and some of them are built into
+various programs, so they are most convenient.
+However, the names do not always represent the actual major and
+minor device in the manner suggested in section 4 of the
+Programmer's Manual.
+For example, `rp3' will be used for the name of the file system
+on which the user file system is put, even though it might be on an RP06
+and is not logical device 3.
+Also, this sequence will put the user file system on the same
+disk drive as the root, which is not the best place
+if you have more than one drive.
+Thus the prescription below should be taken only as one example
+of where to put things.
+See also the section on `Disk layout' below.
+.PP
+In any event, change to the dev directory (cd(1)) and, if you like,
+examine and perhaps change the makefile there (make (1)).
+.DS
+cd /dev
+cat makefile
+.DE
+Then, use one of
+.DS
+make rp03
+make rp04
+make rp05
+make rp06
+.DE
+depending on which disk you have.
+Then, use one of
+.DS
+make tm
+make ht
+.DE
+depending on which tape you have.
+The file `rp0' refers to the root file system;
+`swap' to the swap-space file system; `rp3' to the
+user file system.
+The devices `rrp0' and `rrp3' are the `raw' versions
+of the disks.
+Also, `mt0' is tape drive 0, at 800 BPI;
+`rmt0' is the raw tape, on which large records can be read
+and written;
+`nrmt0' is raw tape with the quirk that it does not rewind
+on close, which is a subterfuge that permits
+multifile tapes to be handled.
+.PP
+The next thing to do is to extract the rest of the data from
+the tape.
+Comments are enclosed in ( ); don't type these.
+The number in the first command is the
+size of the file system;
+it differs between RP03, RP04/5, and RP06.
+.DS
+/etc/mkfs /dev/rp3 74000       (153406 if on RP04/5, 322278 on RP06)
+(The above command takes about 2-3 minutes on an RP03)
+dd if=/dev/nrmt0 of=/dev/null bs=20b files=6   (skip 6 files on the tape)
+restor rf /dev/rmt0 /dev/rp3   (restore the file system)
+(Reply with a `return' (CR) to the `Last chance' message)
+(The restor takes about 20-30 minutes)
+.DE
+All of the data on the tape has been extracted.
+.PP
+You may at this point mount the source
+file system (mount(1)). To do this type the following:
+.DS
+/etc/mount /dev/rp3 /usr
+.DE
+The source and manual
+pages are now available in subdirectories of /usr.
+.PP
+The above mount command is only needed if you
+intend to play around with source on a single
+user system, which you are going to do next.
+The file system is mounted automatically when multi-user
+mode is entered, by a command in the file
+/etc/rc. (See `Disk Layout' below).
+.PP
+Before anything further is done the bootstrap
+block on the disk (block 0) should be filled in.
+This is done using the command
+.DS
+dd if=/usr/mdec/rpuboot of=/dev/rp0 count=1
+.DE
+if you have the RP03, or
+.DS
+dd if=/usr/mdec/hpuboot of=/dev/rp0 count=1
+.DE
+if you have an RP04/5/6.
+Now the DEC disk bootstraps are usable.
+See Boot Procedures(8) for further information.
+.PP
+Before UNIX is turned up completely,
+a few configuration dependent exercises must be
+performed.
+At this point,
+it would be wise to read all of the manuals
+(especially `Regenerating System Software')
+and to augment this reading with hand to hand
+combat.
+.SH
+Reconfiguration
+.PP
+The UNIX system running is configured to run
+with the given disk
+and tape, a console, and no other device.
+This is certainly not the correct
+configuration.
+You will have to correct the configuration table to reflect
+the true state of your machine.
+.PP
+It is wise at this point to know how to recompile the system.
+Print (cat(1))
+the file /usr/sys/conf/makefile.
+This file is input to the program `make(1)' which
+if invoked with `make all' will recompile all of
+the system source and
+install it in the correct libraries.
+.PP
+The program mkconf(1) prepares files that
+describe a given configuration (See mkconf(1)).
+In the /usr/sys/conf directory,
+the four files
+\fIxy\fRconf
+were input to mkconf to produce the four versions of the system
+\fIxy\fRunix.
+Pick the appropriate one, and edit it to add lines describing your own configuration.
+(Remember the console typewriter is automatically included;
+don't count it in the kl specification.)
+Then run mkconf;
+it will generate the files l.s
+(trap vectors) c.c (configuration table),
+and mch0.s.
+Take a careful look at
+l.s to make sure that all the devices that you
+have are assembled in the correct interrupt vectors.
+If your configuration is non-standard, you will
+have to modify l.s to fit your configuration.
+.PP
+There are certain magic numbers and
+configuration parameters imbedded in various
+device drivers that you may want to change.
+The device addresses of each device
+are defined in each driver.
+In case you have any non-standard device
+addresses,
+just change the address and recompile.
+(The device drivers are in the directory
+/usr/sys/dev.)
+.PP
+The DC11 driver is set to run 4 lines.
+This can be changed in dc.c.
+.PP
+The DH11 driver is set to handle 3 DH11's with
+a full complement of 48 lines.
+If you have less, or more, 
+you may want to edit dh.c.
+.PP
+The DN11 driver will handle 4 DN's.
+Edit dn.c.
+.PP
+The DU11 driver can only handle a single DU.
+This cannot be easily changed.
+.PP
+The KL/DL driver is set up to run
+a single DL11-A, -B, or -C (the console)
+and no DL11-E's.
+To change this, edit
+kl.c to have NKL11 reflect the total number of
+DL11-ABC's and
+NDL11 to reflect the number of DL11-E's.
+So far as the driver is concerned,
+the difference between the devices is
+their address.
+.PP
+All of the disk and tape drivers
+(rf.c, rk.c, rp.c, tm.c, tc.c,
+hp.c, ht.c)
+are set up to run 8 drives and should not
+need to be changed.
+The big disk drivers (rp.c and hp.c)
+have partition tables in them which you
+may want to experiment with.
+.PP
+After all the corrections
+have been made,
+use `make(1)' to recompile the system (or
+recompile individually if you wish: use the makefile
+as a guide).
+If you compiled individually, say `make unix' in the
+directory /usr/sys/conf.
+The final object file (unix) should be
+moved to the root, and then booted to try it out.
+It is best to name it /nunix so as not to destroy
+the working system until you're sure it does work.
+See Boot Procedures(8) for a discussion
+of booting.
+Note:  before taking the system down,
+always (!!) perform
+a sync(1)
+to force delayed output to the disk.
+.SH
+Special Files
+.PP
+Next you must put in special files for the new devices in
+the directory /dev using mknod(1).
+Print the configuration file
+c.c created above.
+This is the major
+device switch of each device class (block and character).
+There is one line for each device configured in your system
+and a null line for place holding for those devices
+not configured.
+The essential block special files were installed above;
+for any new devices,
+the major device number is selected by counting the
+line number (from zero)
+of the device's entry in the block configuration table.
+Thus the first entry in the table bdevsw would be
+major device zero.
+This number is also printed in the table along the right margin.
+.PP
+The minor device is the drive number,
+unit number or partition as described
+under each device in section 4 of the manual.
+For tapes where the unit is dial selectable,
+a special file may be made for each possible
+selection.
+You can also add entries for other disk drives.
+.PP
+In reality, device names are arbitrary. It is usually
+convenient to have a system for deriving names, but it doesn't
+have to be the one presented above.
+.PP
+Some further notes on minor device numbers.
+The hp driver uses the 0100 bit of the minor device number to
+indicate whether or not to interleave a file system across
+more than one physical device. See hp(4) for more detail.
+The tm and ht drivers use the 0200 bit to indicate whether
+or not to rewind the tape when it is closed. The
+0100 bit indicates the density of the tape on TU16 drives.
+By convention, tape special files with the 0200 bit on have an `n'
+prepended to their name, as in /dev/nmt0 or /dev/nrmt1.
+Again, see tm(4) or ht(4).
+.PP
+The naming of character devices is similar to block devices.
+Here the names are even more arbitrary except that
+devices meant to be used
+for teletype access should (to avoid confusion, no other reason) be named
+/dev/ttyX, where X is some string (as in `00' or `library').
+The files console, mem, kmem, and null are
+already correctly configured.
+.PP
+The disk and magtape drivers provide a `raw' interface
+to the device which provides direct transmission
+between the user's core and the device and allows
+reading or writing large records.
+The raw device counts as a character device,
+and should have the name of the corresponding
+standard block special file with `r' prepended.
+(The `n' for no rewind tapes violates this rule.)
+Thus the raw magtape
+files would be called /dev/rmtX.
+These special files should be made.
+.PP
+When all the special files have been created,
+care should be taken to change
+the access modes (chmod(1))
+on these files to appropriate values (probably 600 or 644).
+.SH
+Floating Point
+.PP
+UNIX only supports (and really expects to have) the FP11-B/C
+floating point unit.
+For machines without this hardware,
+there is a user subroutine
+available that will catch illegal instruction
+traps and interpret floating point operations.
+(See fptrap(3).)
+To install this subroutine in the library, change to /usr/src/libfpsim
+and execute the shell files
+.DS
+       compall
+       mklib
+.DE
+The system as delivered does not have this code included
+in any command,
+although the operating system adapts automatically to the
+presence or absence of the FP11.
+.PP
+Next, a floating-point version of
+the C compiler in /usr/src/cmd/c
+should be compiled using the commands:
+.DS
+cd /usr/src/cmd/c
+make fc1
+mv fc1 /lib/fc1
+.DE
+This allows programs with floating point constants
+to be compiled.
+To compile floating point programs use the `\-f'
+flag to cc(1). This flag ensures that the floating
+point interpreter is loaded with the program and that
+the floating point version of `cc' is used.
+.SH
+Time Conversion
+.PP
+If your machine is not in the Eastern time zone,
+you must edit (ed(1)) the file
+/usr/sys/h/param.h
+to reflect your local time.
+The manifest `TIMEZONE' should be changed
+to reflect the time difference between local time and GMT in minutes.
+For EST, this is 5*60; for PST it would be 8*60.
+Finally, there is a `DSTFLAG'
+manifest;
+when it is 1 it causes the
+time to shift to Daylight Savings automatically
+between the last Sundays in April and October
+(or other algorithms in 1974 and 1975).
+Normally this will not have to be reset.
+When the needed changes are done, recompile and load the
+system using
+make(1)
+and install it.
+(As a general rule, when a system header file is changed,
+the entire system should be recompiled.
+As it happens, the only uses of these flags are in
+/usr/sys/sys/sys4.c, so if this is all that was changed it
+alone needs to be recompiled.)
+.PP
+You may also want to look at timezone(3)
+(/usr/src/libc/gen/timezone.c) to see
+if the name of your timezone is in its internal table.
+If needed, edit the changes in.
+After timezone.c has been edited
+it should be compiled and installed in
+its library.
+(See /usr/src/libc/(mklib and compall))
+Then you should
+(at your leisure)
+recompile and reinstall
+all programs that use it (such as date(1)).
+.SH
+Disk Layout
+.PP
+If
+there are to be more file systems mounted than just the root
+and /usr,
+use mkfs(1) to create any new file system and
+put its mounting in the file /etc/rc (see init(8) and mount(1)).
+(You might look at /etc/rc anyway to
+see what has been provided for you.)
+.PP
+There are two considerations in deciding how to adjust the arrangement
+of things on your disks:
+the most important is making sure there is adequate space
+for what is required;
+secondarily, throughput should be maximized.
+Swap space is a critical parameter.
+The system
+as distributed has 8778 (hpunix) or 2000 (rpunix) blocks 
+for swap space.
+This should be large enough so running out of swap space never
+occurs.
+You may want to change these if local wisdom indicates otherwise.
+.PP
+The system as distributed has all of the binaries in /bin.
+Most of
+them should be moved to /usr/bin, leaving only the ones required for
+system maintenance (such as icheck, dcheck, cc, ed, restor, etc.) and the most
+heavily used in /bin.
+This will speed things up a bit if you have only one disk, and also free
+up space on the root file system for temporary files. (See below).
+.PP
+Many common system programs (C, the editor, the assembler etc.)
+create intermediate files in the /tmp directory,
+so the file system where this is stored also should be made
+large enough to accommodate
+most high-water marks.
+If you leave the root file system as distributed
+(except as discussed above) there
+should be no problem.
+All the programs that create files in /tmp take
+care to delete them, but most are not immune to
+events like being hung up upon, and can leave dregs.
+The directory should be examined every so often and the old
+files deleted.
+.PP
+Exhaustion of user-file space is certain to occur
+now and then;
+the only mechanisms for controlling this phenomenon
+are occasional use of du(1), df(1), quot(1), threatening
+messages of the day, and personal letters.
+.PP
+The efficiency with which UNIX is able to use the CPU
+is largely dictated by the configuration of disk controllers.
+For general time-sharing applications,
+the best strategy is to try to split user files,
+the root directory (including the /tmp directory)
+and the swap area among three controllers.
+.PP
+Once you have decided how to make best use
+of your hardware, the question is how to initialize it.
+If you have the equipment,
+the best way to move a file system
+is to dump it (dump(1)) to magtape,
+use mkfs(1) to create the new file system,
+and restore (restor(1)) the tape.
+If for some reason you don't want to use magtape,
+dump accepts an argument telling where to put the dump;
+you might use another disk.
+Sometimes a file system has to be increased in logical size
+without copying.
+The super-block of the device has a word
+giving the highest address which can be allocated.
+For relatively small increases, this word can be patched
+using the debugger (adb(1))
+and the free list reconstructed using icheck(1).
+The size should not be increased very greatly
+by this technique, however,
+since although the allocatable space will increase
+the maximum number of files will not (that is, the i-list
+size can't be changed).
+Read and understand the description given in file system(5)
+before playing around in this way.
+You may want to
+see section rp(4) for some suggestions
+on how to lay out the information on RP disks.
+.PP
+If you have to merge a file system into another, existing one,
+the best bet is to
+use tar(1).
+If you must shrink a file system, the best bet is to dump
+the original and restor it onto the new filesystem.
+However, this might not work if the i-list on the smaller filesystem
+is smaller than the maximum allocated inode on the larger.
+If this is the case, reconstruct the filesystem from scratch
+on another filesystem (perhaps using tar(1)) and then dump it.
+If you
+are playing with the root file system and only have one drive
+the procedure is more complicated. What you do is the following:
+.IP 1.
+GET A SECOND PACK!!!!
+.IP 2.
+Dump the current root filesystem (or the reconstructed one) using dump(1).
+.IP 3.
+Bring the system down and mount the new pack.
+.IP 4.
+Retrieve the WECo distribution tape and perform steps 1 through
+5 at the beginning of this document,
+substituting the desired file system size instead of 5000
+when asked for `file system size'.
+.IP 5.
+Perform step 6 above up to the point where the `tape'
+question is asked. At this point mount the tape
+you made just a few minutes ago. Continue with step 6 above substituting
+a 0 (zero) for the 5.
+.SH
+New Users
+.PP
+Install new users by editing the password file
+/etc/passwd (passwd(5)).
+This procedure should be done once multi-user mode is entered
+(see init(8)).
+You'll have to make a current directory for each new user
+and change its owner to the
+newly installed name.
+Login as each user to make sure the password
+file is correctly edited.
+For example:
+.DS
+ed /etc/passwd
+$a
+joe::10:1::/usr/joe:
+.li
+.
+w
+q
+mkdir /usr/joe
+chown joe /usr/joe
+login joe
+ls \-la
+login root
+.DE
+This will make a new login entry for joe,
+who should be encouraged to use passwd(1)
+to give himself a password.
+His default current directory is
+/usr/joe
+which has been created.
+The delivered password file
+has the user
+.I
+bin
+.R
+in it to be used as a prototype.
+.SH
+Multiple Users
+.PP
+If UNIX is to support simultaneous
+access from more than just the console terminal,
+the file /etc/ttys (ttys(5)) has to be edited.
+To add a new terminal be sure the device is configured
+and the special file exists, then set
+the first character of the appropriate line of /etc/ttys to 1
+(or add a new line).
+Note that init.c will have to be recompiled if there are to be
+more than 100 terminals.
+Also note that if the special file is inaccessible when init tries to create a process
+for it, the system will thrash trying and retrying to open it.
+.SH
+File System Health
+.PP
+Periodically (say every day or so) and always after a crash,
+you should check all the file systems for consistency
+(icheck, dcheck(1)).
+It is quite important to execute sync (8)
+before rebooting or taking the machine down.
+This is done automatically every 30 seconds by the update
+program (8) when a multiple-user system is running,
+but you should do it anyway to make sure.
+.PP
+Dumping of the file system should be done regularly,
+since once the system is going it is very easy to
+become complacent.
+Complete and incremental dumps are easily done with
+dump(1).
+Dumping of files by name is best done by
+tar(1) but the number of files is somewhat limited.
+Finally if there are enough drives entire
+disks can be copied using cp(1), or preferably with
+dd(1) using the raw special files and an appropriate
+block size.
+.SH
+Converting Sixth Edition Filesystems
+.PP
+The best way to convert file systems from 6th
+edition (V6) to 7th edition (V7) format
+is to use tar(1). However, a special version of tar must
+be prepared
+to run on V6.
+The following steps will do this:
+.IP 1.
+change directories to /usr/src/cmd/tar
+.IP 2.
+At the shell prompt respond
+.DS
+make v6tar
+.DE
+This will leave an executable binary named `v6tar'.
+.IP 3.
+Mount a scratch tape.
+.IP 4.
+Use tp(1) to put `v6tar' on the scratch
+tape.
+.IP 5.
+Bring down V7 and bring up V6.
+.IP 6.
+Use tp (on V6) to read in `v6tar'. Put it in
+/bin or /usr/bin (or perhaps some other preferred location).
+.IP 7.
+Use v6tar to make tapes of all that you wish to convert.
+You may want to read the manual section on tar(1) to
+see whether you want to use blocking or not.
+Try to avoid using full pathnames when making the tapes. This
+will simplify moving the hierarchy to some other place on 
+V7 if desired. For example
+.DS
+chdir /usr/ken
+v6tar c .
+.DE
+is preferable to
+.DS
+v6tar c /usr/ken
+.DE
+.IP 8.
+After all of the desired tapes are made, bring
+down V6 and reboot V7. Use
+tar(1) to read in the tapes just made.
+.SH
+Odds and Ends
+.PP
+The programs
+dump,
+icheck, quot, dcheck, ncheck, and df
+(source in /usr/source/cmd)
+should be changed to
+reflect your default mounted file system devices.
+Print the first few lines of these
+programs and the changes will be obvious.
+Tar should be changed to reflect your desired
+default tape drive.
+.sp 3
+.in 4i
+Good Luck
+.sp 1
+Charles B. Haley
+.br
+Dennis M. Ritchie
diff --git a/doc/7thEdMan/vol2/shell.bun b/doc/7thEdMan/vol2/shell.bun
new file mode 100644 (file)
index 0000000..2644d10
--- /dev/null
@@ -0,0 +1,2263 @@
+# To unbundle, run this file
+echo t.mac
+sed 's/.//' >t.mac <<'//GO.SYSIN DD t.mac'
+-.ds ZZ \fB.\|.\|.\fP
+-.ds ST \v'.3m'\s+2*\s0\v'-.3m'
+-.ds DO \h'\w'do 'u'
+-.ds Ca \h'\w'case 'u'
+-.ds WH \h'\w'while 'u'
+-.ds VT \|\fB\(or\fP\|
+-.ds TH \h'\w'then 'u'
+-.ds DC \*(DO\*(CA
+-.ds AP >\h'-.2m'>
+-.ds HE <\h'-.2m'<
+-..    \" macros for algol 68c reference manual
+-.ds DA 1977 November 1
+-.ds md \v'.25m'
+-.ds mu \v'-.25m'
+-.ds U \*(mu\s-3
+-.ds V \s0\*(md
+-.ds L \*(md\s-3
+-.ds M \s0\*(mu
+-.ds S \s-1
+-.ds T \s0
+-..    \" small 1
+-.ds O \*S1\*T
+-.ds h \|
+-.ds s \|\|
+-..    \" ellipsis
+-.ds e .\|.\|.
+-..    \" subscripts
+-.ds 1 \*(md\s-41\s0\*(mu
+-.ds 2 \*(md\s-42\s0\*(mu
+//GO.SYSIN DD t.mac
+echo t1
+sed 's/.//' >t1 <<'//GO.SYSIN DD t1'
+-.RP
+-.TL 
+-An Introduction to the UNIX Shell
+-.AU
+-S. R. Bourne
+-.AI
+-.MH
+-.AB
+-.LP
+-The
+-.ul
+-shell
+-is a command programming language that provides an interface
+-to the
+-.UX
+-operating system.
+-Its features include
+-control-flow primitives, parameter passing, variables and
+-string substitution.
+-Constructs such as
+-.ul
+-while, if then else, case
+-and
+-.ul
+-for
+-are available.
+-Two-way communication is possible between the
+-.ul
+-shell
+-and commands.
+-String-valued parameters, typically file names or flags, may be
+-passed to a command.
+-A return code is set by commands that may be used to determine control-flow,
+-and the standard output from a command may be used
+-as shell input.
+-.LP
+-The
+-.ul
+-shell
+-can modify the environment
+-in which commands run.
+-Input and output can be redirected
+-to files, and processes that communicate through `pipes'
+-can be invoked.
+-Commands are found by
+-searching directories
+-in the file system in a
+-sequence that can be defined by the user.
+-Commands can be read either from the terminal or from a file,
+-which allows command procedures to be
+-stored for later use.
+-.AE
+-.ds ST \v'.3m'\s+2*\s0\v'-.3m'
+-.SH
+-1.0\ Introduction
+-.LP
+-The shell is both a command language
+-and a programming language
+-that provides an interface to the UNIX
+-operating system.
+-This memorandum describes, with
+-examples, the UNIX shell.
+-The first section covers most of the
+-everyday requirements
+-of terminal users.
+-Some familiarity with UNIX
+-is an advantage when reading this section;
+-see, for example,
+-"UNIX for beginners".
+-.[
+-unix beginn kernigh 1978
+-.]
+-Section 2 describes those features
+-of the shell primarily intended
+-for use within shell procedures.
+-These include the control-flow
+-primitives and string-valued variables
+-provided by the shell.
+-A knowledge of a programming language
+-would be a help when reading this section.
+-The last section describes the more
+-advanced features of the shell.
+-References of the form "see \fIpipe\fP (2)"
+-are to a section of the UNIX manual.
+-.[
+-seventh 1978 ritchie thompson
+-.]
+-.SH
+-1.1\ Simple\ commands
+-.LP
+-Simple commands consist of one or more words
+-separated by blanks.
+-The first word is the name of the command
+-to be executed; any remaining words
+-are passed as arguments to the command.
+-For example,
+-.DS
+-      who
+-.DE
+-is a command that prints the names
+-of users logged in.
+-The command
+-.DS
+-      ls \(mil
+-.DE
+-prints a list of files in the current
+-directory.
+-The argument \fI\(mil\fP tells \fIls\fP
+-to print status information, size and
+-the creation date for each file.
+-.SH
+-1.2\ Background\ commands
+-.LP
+-To execute a command the shell normally
+-creates a new \fIprocess\fP
+-and waits for it to finish.
+-A command may be run without waiting
+-for it to finish.
+-For example,
+-.DS
+-      cc pgm.c &
+-.DE
+-calls the C compiler to compile
+-the file \fIpgm.c\|.\fP
+-The trailing \fB&\fP is an operator that instructs the shell
+-not to wait for the command to finish.
+-To help keep track of such a process
+-the shell reports its process
+-number following its creation.
+-A list of currently active processes may be obtained
+-using the \fIps\fP command.
+-.SH
+-1.3\ Input\ output\ redirection
+-.LP
+-Most commands produce output on the standard output
+-that is initially connected to the terminal.
+-This output may be sent to a file
+-by writing, for example,
+-.DS
+-      ls \(mil >file
+-.DE
+-The notation \fI>file\fP
+-is interpreted by the shell and is not passed
+-as an argument to \fIls.\fP
+-If \fIfile\fP does not exist then the
+-shell creates it;
+-otherwise the original contents of
+-\fIfile\fP are replaced with the output
+-from \fIls.\fP
+-Output may be appended to a file
+-using the notation
+-.DS
+-      ls \(mil \*(APfile
+-.DE
+-In this case \fIfile\fP is also created if it does not already
+-exist.
+-.LP
+-The standard input of a command may be taken
+-from a file instead of the terminal by
+-writing, for example,
+-.DS
+-      wc <file
+-.DE
+-The command \fIwc\fP reads its standard input
+-(in this case redirected from \fIfile\fP)
+-and prints the number of characters, words and
+-lines found.
+-If only the number of lines is required
+-then
+-.DS
+-      wc \(mil <file
+-.DE
+-could be used.
+-.SH
+-1.4\ Pipelines\ and\ filters
+-.LP
+-The standard output of one command may be
+-connected to the standard input of another
+-by writing
+-the `pipe' operator,
+-indicated by \*(VT,
+-as in,
+-.DS
+-      ls \(mil \*(VT wc
+-.DE
+-Two commands connected in this way constitute
+-a \fIpipeline\fP and
+-the overall effect is the same as
+-.DS
+-      ls \(mil >file; wc <file
+-.DE
+-except that no \fIfile\fP is used.
+-Instead the two processes are connected
+-by a pipe (see \fIpipe\fP (2)) and are
+-run in parallel.
+-Pipes are unidirectional and
+-synchronization is achieved by
+-halting \fIwc\fP when there is
+-nothing to read and halting \fIls\fP
+-when the pipe is full.
+-.LP
+-A \fIfilter\fP is a command
+-that reads its standard input,
+-transforms it in some way,
+-and prints the result as output.
+-One such filter, \fIgrep,\fP
+-selects from its input those lines
+-that contain some specified string.
+-For example,
+-.DS
+-      ls \*(VT grep old
+-.DE
+-prints those lines, if any, of the output
+-from \fIls\fP that contain
+-the string \fIold.\fP
+-Another useful filter is \fIsort\fP.
+-For example,
+-.DS
+-      who \*(VT sort
+-.DE
+-will print an alphabetically sorted list
+-of logged in users.
+-.LP
+-A pipeline may consist of more than two commands,
+-for example,
+-.DS
+-      ls \*(VT grep old \*(VT wc \(mil
+-.DE
+-prints the number of file names
+-in the current directory containing
+-the string \fIold.\fP
+-.SH
+-1.5\ File\ name\ generation
+-.LP
+-Many commands accept arguments
+-which are file names.
+-For example,
+-.DS
+-      ls \(mil main.c
+-.DE
+-prints information relating to the file \fImain.c\fP\|.
+-.LP
+-The shell provides a mechanism
+-for generating a list of file names
+-that match a pattern.
+-For example,
+-.DS
+-      ls \(mil \*(ST.c
+-.DE
+-generates, as arguments to \fIls,\fP
+-all file names in the current directory that end in \fI.c\|.\fP
+-The character \*(ST is a pattern that will match any string
+-including the null string.
+-In general \fIpatterns\fP are specified
+-as follows.
+-.RS
+-.IP \fB\*(ST\fR 8
+-Matches any string of characters
+-including the null string.
+-.IP \fB?\fR 8
+-Matches any single character.
+-.IP \fB[\*(ZZ]\fR 8
+-Matches any one of the characters
+-enclosed.
+-A pair of characters separated by a minus will
+-match any character lexically between
+-the pair.
+-.RE
+-.LP
+-For example,
+-.DS
+-      [a\(miz]\*(ST
+-.DE
+-matches all names in the current directory
+-beginning with
+-one of the letters \fIa\fP through \fIz.\fP
+-.DS
+-      /usr/fred/test/?
+-.DE
+-matches all names in the directory
+-\fB/usr/fred/test\fP that consist of a single character.
+-If no file name is found that matches
+-the pattern then the pattern is passed,
+-unchanged, as an argument.
+-.LP
+-This mechanism is useful both to save typing
+-and to select names according to some pattern.
+-It may also be used to find files.
+-For example,
+-.DS
+-      echo /usr/fred/\*(ST/core
+-.DE
+-finds and prints the names of all \fIcore\fP files in sub-directories
+-of \fB/usr/fred\|.\fP
+-(\fIecho\fP is a standard UNIX command that prints
+-its arguments, separated by blanks.)
+-This last feature can be expensive,
+-requiring a scan of all
+-sub-directories of \fB/usr/fred\|.\fP
+-.LP
+-There is one exception to the general
+-rules given for patterns.
+-The character `\fB.\fP'
+-at the start of a file name must be explicitly
+-matched.
+-.DS
+-      echo \*(ST
+-.DE
+-will therefore echo all file names in the current
+-directory not beginning
+-with `\fB.\fP'\|.
+-.DS
+-      echo \fB.\fP\*(ST
+-.DE
+-will echo all those file names that begin with `\fB.\fP'\|.
+-This avoids inadvertent matching
+-of the names `\fB.\fP' and `\fB..\fP'
+-which mean `the current directory'
+-and `the parent directory'
+-respectively.
+-(Notice that \fIls\fP suppresses
+-information for the files `\fB.\fP' and `\fB..\fP'\|.)
+-.SH
+-1.6\ Quoting
+-.LP
+-Characters that have a special meaning
+-to the shell, such as \fB< > \*(ST ? \*(VT &\|,\fR
+-are called metacharacters.
+-A complete list of metacharacters is given
+-in appendix B.
+-Any character preceded by a \fB\\\fR is \fIquoted\fP
+-and loses its special meaning, if any.
+-The \fB\\\fP is elided so that
+-.DS
+-      echo \\\\?
+-.DE
+-will echo a single \fB?\|,\fP
+-and
+-.DS
+-      echo \\\\\\\\
+-.DE
+-will echo a single \fB\\\|.\fR
+-To allow long strings to be continued over
+-more than one line
+-the sequence \fB\\newline\fP
+-is ignored.
+-.LP
+-\fB\\\fP is convenient for quoting
+-single characters.
+-When more than one character needs
+-quoting the above mechanism is clumsy and
+-error prone.
+-A string of characters may be quoted
+-by enclosing the string between single quotes.
+-For example,
+-.DS
+-      echo xx\'\*(ST\*(ST\*(ST\*(ST\'xx
+-.DE
+-will echo
+-.DS
+-      xx\*(ST\*(ST\*(ST\*(STxx
+-.DE
+-The quoted string may not contain
+-a single quote
+-but may contain newlines, which are preserved.
+-This quoting mechanism is the most
+-simple and is recommended
+-for casual use.
+-.LP
+-A third quoting mechanism using double quotes
+-is also available
+-that prevents interpretation of some but not all
+-metacharacters.
+-Discussion of the
+-details is deferred
+-to section 3.4\|.
+-.SH
+-1.7\ Prompting
+-.LP
+-When the shell is used from a terminal it will
+-issue a prompt before reading a command.
+-By default this prompt is `\fB$\ \fR'\|.
+-It may be changed by saying,
+-for example,
+-.DS
+-      \s-1PS1\s0=yesdear
+-.DE
+-that sets the prompt to be the string \fIyesdear\|.\fP
+-If a newline is typed and further input is needed
+-then the shell will issue the prompt `\fB>\ \fR'\|.
+-Sometimes this can be caused by mistyping
+-a quote mark.
+-If it is unexpected then an interrupt (\s-1DEL\s0)
+-will return the shell to read another command.
+-This prompt may be changed by saying, for example,
+-.DS
+-      \s-1PS2\s0=more
+-.DE
+-.SH
+-1.8\ The\ shell\ and\ login
+-.LP
+-Following \fIlogin\fP (1)
+-the shell is called to read and execute
+-commands typed at the terminal.
+-If the user's login directory
+-contains the file \fB.profile\fP
+-then it is assumed to contain commands
+-and is read by the shell before reading
+-any commands from the terminal.
+-.SH
+-1.9\ Summary
+-.sp
+-.RS
+-.IP \(bu
+-\fBls\fP
+-.br
+-Print the names of files in the current directory.
+-.IP \(bu
+-\fBls >file\fP
+-.br
+-Put the output from \fIls\fP into \fIfile.\fP
+-.IP \(bu
+-\fBls \*(VT wc \(mil\fR
+-.br
+-Print the number of files in the current directory.
+-.IP \(bu
+-\fBls \*(VT grep old\fR
+-.br
+-Print those file names containing the string \fIold.\fP
+-.IP \(bu
+-\fBls \*(VT grep old \*(VT wc \(mil\fR
+-.br
+-Print the number of files whose name contains the string \fIold.\fP
+-.IP \(bu
+-\fBcc pgm.c &\fR
+-.br
+-Run \fIcc\fP in the background.
+-.RE
+//GO.SYSIN DD t1
+echo t2
+sed 's/.//' >t2 <<'//GO.SYSIN DD t2'
+-.bp
+-.SH
+-2.0\ Shell\ procedures
+-.LP
+-The shell may be used to read and execute commands
+-contained in a file.
+-For example,
+-.DS
+-      sh file [ args \*(ZZ ]
+-.DE
+-calls the shell to read commands from \fIfile.\fP
+-Such a file is called a \fIcommand procedure\fP
+-or \fIshell procedure.\fP
+-Arguments may be supplied with the call
+-and are referred to in \fIfile\fP
+-using the positional parameters
+-\fB$1, $2, \*(ZZ\|.\fR
+-For example, if the file \fIwg\fP contains
+-.DS
+-      who \*(VT grep $1
+-.DE
+-then
+-.DS
+-      sh wg fred
+-.DE
+-is equivalent to
+-.DS
+-      who \*(VT grep fred
+-.DE
+-.LP
+-UNIX files have three independent attributes,
+-\fIread,\fP \fIwrite\fP and \fIexecute.\fP
+-The UNIX command \fIchmod\fP (1) may be used
+-to make a file executable.
+-For example,
+-.DS
+-      chmod +x wg
+-.DE
+-will ensure that the file \fIwg\fP has execute status.
+-Following this, the command
+-.DS
+-      wg fred
+-.DE
+-is equivalent to
+-.DS
+-      sh wg fred
+-.DE
+-This allows shell procedures and programs
+-to be used interchangeably.
+-In either case a new process is created to
+-run the command.
+-.LP
+-As well as providing names for the positional
+-parameters,
+-the number of positional parameters in the call
+-is available as \fB$#\|.\fP
+-The name of the file being executed
+-is available as \fB$0\|.\fP
+-.LP
+-A special shell parameter \fB$\*(ST\fP
+-is used to substitute for all positional parameters
+-except \fB$0\|.\fP
+-A typical use of this is to provide
+-some default arguments,
+-as in,
+-.DS
+-      nroff \(miT450 \(mims $\*(ST
+-.DE
+-which simply prepends some arguments
+-to those already given.
+-.SH
+-2.1\ Control\ flow\ -\ for
+-.LP
+-A frequent use of shell procedures is to loop
+-through the arguments (\fB$1, $2, \*(ZZ\fR)
+-executing commands once for each argument.
+-An example of such a procedure is
+-\fItel\fP that searches the file
+-\fB/usr/lib/telnos\fR
+-that contains lines of the form
+-.DS
+-      \*(ZZ
+-      fred mh0123
+-      bert mh0789
+-      \*(ZZ
+-.DE
+-The text of \fItel\fP is
+-.DS
+-      for i
+-      do grep $i /usr/lib/telnos; done
+-.DE
+-The command
+-.DS
+-      tel fred
+-.DE
+-prints those lines in \fB/usr/lib/telnos\fR
+-that contain the string \fIfred\|.\fP
+-.DS
+-      tel fred bert
+-.DE
+-prints those lines containing \fIfred\fP
+-followed by those for \fIbert.\fP
+-.LP
+-The \fBfor\fP loop notation is recognized by the shell
+-and has the general form
+-.DS
+-      \fBfor\fR \fIname\fR \fBin\fR \fIw1 w2 \*(ZZ\fR
+-      \fBdo\fR \fIcommand-list\fR
+-      \fBdone\fR
+-.DE
+-A \fIcommand-list\fP is a sequence of one or more
+-simple commands separated or terminated by a newline or semicolon.
+-Furthermore, reserved words
+-like \fBdo\fP and \fBdone\fP are only
+-recognized following a newline or
+-semicolon.
+-\fIname\fP is a shell variable that is set
+-to the words \fIw1 w2 \*(ZZ\fR in turn each time the \fIcommand-list\fP
+-following \fBdo\fP
+-is executed.
+-If \fBin\fR \fIw1 w2 \*(ZZ\fR
+-is omitted then the loop
+-is executed once for each positional parameter;
+-that is, \fBin\fR \fI$\*(ST\fR is assumed.
+-.LP
+-Another example of the use of the \fBfor\fP
+-loop is the \fIcreate\fP command
+-whose text is
+-.DS
+-      for i do >$i; done
+-.DE
+-The command
+-.DS
+-      create alpha beta
+-.DE
+-ensures that two empty files
+-\fIalpha\fP and \fIbeta\fP exist
+-and are empty.
+-The notation \fI>file\fP may be used on its
+-own to create or clear the contents of a file.
+-Notice also that a semicolon (or newline) is required before \fBdone.\fP
+-.SH
+-2.2\ Control\ flow\ -\ case
+-.LP
+-A multiple way branch is provided for by the
+-\fBcase\fP notation.
+-For example,
+-.DS
+-      case $# in
+-      \*(Ca1) cat \*(AP$1 ;;
+-      \*(Ca2) cat \*(AP$2 <$1 ;;
+-      \*(Ca\*(ST)     echo \\'usage: append [ from ] to\\' ;;
+-      esac
+-.DE
+-is an \fIappend\fP command.
+-When called
+-with one argument as
+-.DS
+-      append file
+-.DE
+-\fB$#\fP is the string \fI1\fP and
+-the standard input is copied onto the
+-end of \fIfile\fP
+-using the \fIcat\fP command.
+-.DS
+-      append file1 file2
+-.DE
+-appends the contents of \fIfile1\fP
+-onto \fIfile2.\fP
+-If the number of arguments supplied to
+-\fIappend\fP is other than 1 or 2
+-then a message is printed indicating
+-proper usage.
+-.LP
+-The general form of the \fBcase\fP command
+-is
+-.DS
+-      \fBcase \fIword \fBin
+-      \*(Ca\fIpattern\|\fB)\ \fIcommand-list\fB\|;;
+-      \*(Ca\*(ZZ
+-      \fBesac\fR
+-.DE
+-The shell attempts to match
+-\fIword\fR with each \fIpattern,\fR
+-in the order in which the patterns
+-appear.
+-If a match is found the
+-associated \fIcommand-list\fP is
+-executed and execution
+-of the \fBcase\fP is complete.
+-Since \*(ST is the pattern that matches any
+-string it can be used for the default case.
+-.LP
+-A word of caution:
+-no check is made to ensure that only
+-one pattern matches
+-the case argument.
+-The first match found defines the set of commands
+-to be executed.
+-In the example below the commands following
+-the second \*(ST will never be executed.
+-.DS
+-      case $# in
+-      \*(Ca\*(ST) \*(ZZ ;;
+-      \*(Ca\*(ST) \*(ZZ ;;
+-      esac
+-.DE
+-.LP
+-Another example of the use of the \fBcase\fP
+-construction is to distinguish
+-between different forms
+-of an argument.
+-The following example is a fragment of a \fIcc\fP command.
+-.DS
+-      for i
+-      do case $i in
+-      \*(DC\(mi[ocs]) \*(ZZ ;;
+-      \*(DC\(mi\*(ST) echo \\'unknown flag $i\\' ;;
+-      \*(DC\*(ST.c)   /lib/c0 $i \*(ZZ ;;
+-      \*(DC\*(ST)     echo \\'unexpected argument $i\\' ;;
+-      \*(DOesac
+-      done
+-.DE
+-.LP
+-To allow the same commands to be associated
+-with more than one pattern
+-the \fBcase\fP command provides
+-for alternative patterns
+-separated by a \*(VT\|.
+-For example,
+-.DS
+-      case $i in
+-      \*(Ca\(mix\*(VT\(miy)   \*(ZZ
+-      esac
+-.DE
+-is equivalent to
+-.DS
+-      case $i in
+-      \*(Ca\(mi[xy])  \*(ZZ
+-      esac
+-.DE
+-.LP
+-The usual quoting conventions apply
+-so that
+-.DS
+-      case $i in
+-      \*(Ca\\\\?)     \*(ZZ
+-.DE
+-will match the character \fB?\|.\fP
+-.SH
+-2.3\ Here\ documents
+-.LP
+-The shell procedure \fItel\fP
+-in section 2.1 uses the file \fB/usr/lib/telnos\fR
+-to supply the data
+-for \fIgrep.\fP
+-An alternative is to include this
+-data
+-within the shell procedure as a \fIhere\fP document, as in,
+-.DS
+-      for i
+-      do grep $i \*(HE!
+-      \*(DO\*(ZZ
+-      \*(DOfred mh0123
+-      \*(DObert mh0789
+-      \*(DO\*(ZZ
+-      !
+-      done
+-.DE
+-In this example
+-the shell takes the lines between \fB\*(HE!\fR and \fB!\fR
+-as the standard input for \fIgrep.\fP
+-The string \fB!\fR is arbitrary, the document
+-being terminated by a line that consists
+-of the string following \*(HE\|.
+-.LP
+-Parameters are substituted in the document
+-before it is made available to \fIgrep\fP
+-as illustrated by the following procedure
+-called \fIedg\|.\fP
+-.DS
+-      ed $3 \*(HE%
+-      g/$1/s//$2/g
+-      w
+-      %
+-.DE
+-The call
+-.DS
+-      edg string1 string2 file
+-.DE
+-is then equivalent to the command
+-.DS
+-      ed file \*(HE%
+-      g/string1/s//string2/g
+-      w
+-      %
+-.DE
+-and changes all occurrences of \fIstring1\fP
+-in \fIfile\fP to \fIstring2\|.\fP
+-Substitution can be prevented using \\
+-to quote the special character \fB$\fP
+-as in
+-.DS
+-      ed $3 \*(HE+
+-      1,\\\\$s/$1/$2/g
+-      w
+-      +
+-.DE
+-(This version of \fIedg\fP is equivalent to
+-the first except that \fIed\fP will print
+-a \fB?\fR if there are no occurrences of
+-the string \fB$1\|.\fP)
+-Substitution within a \fIhere\fP document
+-may be prevented entirely by quoting
+-the terminating string,
+-for example,
+-.DS
+-      grep $i \*(HE\\\\#
+-      \*(ZZ
+-      #
+-.DE
+-The document is presented
+-without modification to \fIgrep.\fP
+-If parameter substitution is not required
+-in a \fIhere\fP document this latter form
+-is more efficient.
+-.SH
+-2.4\ Shell\ variables
+-.LP
+-The shell
+-provides string-valued variables.
+-Variable names begin with a letter
+-and consist of letters, digits and
+-underscores.
+-Variables may be given values by writing, for example,
+-.DS
+-      user=fred\ box=m000\ acct=mh0000
+-.DE
+-which assigns values to the variables
+-\fBuser, box\fP and \fBacct.\fP
+-A variable may be set to the null string
+-by saying, for example,
+-.DS
+-      null=
+-.DE
+-The value of a variable is substituted
+-by preceding its name with \fB$\|;\fP
+-for example,
+-.DS
+-      echo $user
+-.DE
+-will echo \fIfred.\fP
+-.LP
+-Variables may be used interactively
+-to provide abbreviations for frequently
+-used strings.
+-For example,
+-.DS
+-      b=/usr/fred/bin
+-      mv pgm $b
+-.DE
+-will move the file \fIpgm\fP
+-from the current directory to the directory \fB/usr/fred/bin\|.\fR
+-A more general notation is available for parameter
+-(or variable)
+-substitution, as in,
+-.DS
+-      echo ${user}
+-.DE
+-which is equivalent to
+-.DS
+-      echo $user
+-.DE
+-and is used when the parameter name is
+-followed by a letter or digit.
+-For example,
+-.DS
+-      tmp=/tmp/ps
+-      ps a >${tmp}a
+-.DE
+-will direct the output of \fIps\fR
+-to the file \fB/tmp/psa,\fR
+-whereas,
+-.DS
+-      ps a >$tmpa
+-.DE
+-would cause the value of the variable \fBtmpa\fP
+-to be substituted.
+-.LP
+-Except for \fB$?\fP the following
+-are set initially by the shell.
+-\fB$?\fP is set after executing each command.
+-.RS
+-.IP \fB$?\fP 8
+-The exit status (return code)
+-of the last command executed
+-as a decimal string.
+-Most commands return a zero exit status
+-if they complete successfully,
+-otherwise a non-zero exit status is returned.
+-Testing the value of return codes is dealt with
+-later under \fBif\fP and \fBwhile\fP commands.
+-.IP \fB$#\fP 8
+-The number of positional parameters
+-(in decimal).
+-Used, for example, in the \fIappend\fP command
+-to check the number of parameters.
+-.IP \fB$$\fP 8
+-The process number of this shell (in decimal).
+-Since process numbers are unique among
+-all existing processes, this string is
+-frequently used to generate
+-unique
+-temporary file names.
+-For example,
+-.DS
+-      ps a >/tmp/ps$$
+-      \*(ZZ
+-      rm /tmp/ps$$
+-.DE
+-.IP \fB$\|!\fP 8
+-The process number of the last process
+-run in the background (in decimal).
+-.IP \fB$\(mi\fP 8
+-The current shell flags, such as
+-\fB\(mix\fR and \fB\(miv\|.\fR
+-.RE
+-.LP
+-Some variables have a special meaning to the
+-shell and should be avoided for general
+-use.
+-.RS
+-.IP \fB$\s-1MAIL\s0\fP 8
+-When used interactively
+-the shell looks at the file
+-specified by this variable
+-before it issues a prompt.
+-If the specified file has been modified
+-since it
+-was last looked at the shell
+-prints the message
+-\fIyou have mail\fP before prompting
+-for the next command.
+-This variable is typically set
+-in the file \fB.profile,\fP
+-in the user's login directory.
+-For example,
+-.DS
+-      \s-1MAIL\s0=/usr/mail/fred
+-.DE
+-.IP \fB$\s-1HOME\s0\fP 8
+-The default argument
+-for the \fIcd\fP command.
+-The current directory is used to resolve
+-file name references that do not begin with
+-a \fB/\|,\fR
+-and is changed using the \fIcd\fP command.
+-For example,
+-.DS
+-      cd /usr/fred/bin
+-.DE
+-makes the current directory \fB/usr/fred/bin\|.\fR
+-.DS
+-      cat wn
+-.DE
+-will print on the terminal the file \fIwn\fP
+-in this directory.
+-The command
+-\fIcd\fP with no argument
+-is equivalent to
+-.DS
+-      cd $\s-1HOME\s0
+-.DE
+-This variable is also typically set in the
+-the user's login profile.
+-.IP \fB$\s-1PATH\s0\fP 8
+-A list of directories that contain commands (the \fIsearch path\fR\|).
+-Each time a command is executed by the shell
+-a list of directories is searched
+-for an executable file.
+-.ne 5
+-If \fB$\s-1PATH\s0\fP is not set
+-then the current directory,
+-\fB/bin\fP, and \fB/usr/bin\fP are searched by default.
+-.ne 5
+-Otherwise \fB$\s-1PATH\s0\fP consists of directory
+-names separated by \fB:\|.\fP
+-For example,
+-.DS
+-      \s-1PATH\s0=\fB:\fP/usr/fred/bin\fB:\fP/bin\fB:\fP/usr/bin
+-.DE
+-specifies that the current directory
+-(the null string before the first \fB:\fP\|),
+-\fB/usr/fred/bin, /bin \fRand\fP /usr/bin\fR
+-are to be searched in that order.
+-In this way individual users
+-can have their own `private' commands
+-that are accessible independently
+-of the current directory.
+-If the command name contains a \fB/\fR then this directory search
+-is not used; a single attempt
+-is made to execute the command.
+-.IP \fB$\s-1PS1\s0\fP 8
+-The primary shell prompt string, by default, `\fB$\ \fR'.
+-.IP \fB$\s-1PS2\s0\fP 8
+-The shell prompt when further input is needed,
+-by default, `\fB>\ \fR'.
+-.IP \fB$\s-1IFS\s0\fP 8
+-The set of characters used by \fIblank
+-interpretation\fR (see section 3.4).
+-.RE
+-.SH
+-2.5\ The\ test\ command
+-.LP
+-The \fItest\fP command, although not part of the shell,
+-is intended for use by shell programs.
+-For example,
+-.DS
+-      test \(mif file
+-.DE
+-returns zero exit status if \fIfile\fP
+-exists and non-zero exit status otherwise.
+-In general \fItest\fP evaluates a predicate
+-and returns the result as its exit status.
+-Some of the more frequently used \fItest\fP
+-arguments are given here, see \fItest\fP (1)
+-for a complete specification.
+-.DS
+-      test s          true if the argument \fIs\fP is not the null string
+-      test \(mif file true if \fIfile\fP exists
+-      test \(mir file true if \fIfile\fP is readable
+-      test \(miw file true if \fIfile\fP is writable
+-      test \(mid file true if \fIfile\fP is a directory
+-.DE
+-.SH
+-2.6\ Control\ flow\ -\ while
+-.LP
+-The actions of
+-the \fBfor\fP loop and the \fBcase\fP
+-branch are determined by data available to the shell.
+-A \fBwhile\fP or \fBuntil\fP loop
+-and an \fBif then else\fP branch
+-are also provided whose
+-actions are determined by the exit status
+-returned by commands.
+-A \fBwhile\fP loop has the general form
+-.DS
+-      \fBwhile\fP \fIcommand-list\*1\fP
+-      \fBdo\fP \fIcommand-list\*2\fP
+-      \fBdone\fP
+-.DE
+-.LP
+-The value tested by the \fBwhile\fP command
+-is the exit status of the last simple command
+-following \fBwhile.\fP
+-Each time round the loop
+-\fIcommand-list\*1\fP is executed;
+-if a zero exit status is returned then
+-\fIcommand-list\*2\fP
+-is executed;
+-otherwise, the loop terminates.
+-For example,
+-.DS
+-      while test $1
+-      do \*(ZZ
+-      \*(DOshift
+-      done
+-.DE
+-is equivalent to
+-.DS
+-      for i
+-      do \*(ZZ
+-      done
+-.DE
+-\fIshift\fP is a shell command that
+-renames the positional parameters
+-\fB$2, $3, \*(ZZ\fR as \fB$1, $2, \*(ZZ\fR
+-and loses \fB$1\|.\fP
+-.LP
+-Another kind of use for the \fBwhile/until\fP
+-loop is to wait until some
+-external event occurs and then run
+-some commands.
+-In an \fBuntil\fP loop
+-the termination condition is reversed.
+-For example,
+-.DS
+-      until test \(mif file
+-      do sleep 300; done
+-      \fIcommands\fP
+-.DE
+-will loop until \fIfile\fP exists.
+-Each time round the loop it waits for
+-5 minutes before trying again.
+-(Presumably another process
+-will eventually create the file.)
+-.SH
+-2.7\ Control\ flow\ -\ if
+-.LP
+-Also available is a
+-general conditional branch
+-of the form,
+-.DS
+-      \fBif\fP \fIcommand-list
+-      \fBthen \fIcommand-list
+-      \fBelse \fIcommand-list
+-      \fBfi\fR
+-.DE
+-that tests the value returned by the last simple command
+-following \fBif.\fP
+-.LP
+-The \fBif\fP command may be used
+-in conjunction with the \fItest\fP command
+-to test for the existence of a file as in
+-.DS
+-      if test \(mif file
+-      then    \fIprocess file\fP
+-      else    \fIdo something else\fP
+-      fi
+-.DE
+-.LP
+-An example of the use of \fBif, case\fP
+-and \fBfor\fP constructions is given in
+-section 2.10\|.
+-.LP
+-A multiple test \fBif\fP command
+-of the form
+-.DS
+-      if \*(ZZ
+-      then    \*(ZZ
+-      else    if \*(ZZ
+-              then    \*(ZZ
+-              else    if \*(ZZ
+-                      \*(ZZ
+-                      fi
+-              fi
+-      fi
+-.DE
+-may be written using an extension of the \fBif\fP
+-notation as,
+-.DS
+-      if \*(ZZ
+-      then    \*(ZZ
+-      elif    \*(ZZ
+-      then    \*(ZZ
+-      elif    \*(ZZ
+-      \*(ZZ
+-      fi
+-.DE
+-.LP
+-The following example is the \fItouch\fP command
+-which changes the `last modified' time for a list
+-of files.
+-The command may be used in conjunction
+-with \fImake\fP (1) to force recompilation of a list
+-of files.
+-.DS
+-      flag=
+-      for i
+-      do case $i in
+-      \*(DC\(mic)     flag=N ;;
+-      \*(DC\*(ST)     if test \(mif $i
+-      \*(DC   then    ln $i junk$$; rm junk$$
+-      \*(DC   elif test $flag
+-      \*(DC   then    echo file \\\\\'$i\\\\\' does not exist
+-      \*(DC   else    >$i
+-      \*(DC   fi
+-      \*(DO esac
+-      done
+-.DE
+-The \fB\(mic\fP flag is used in this command to
+-force subsequent files to be created if they do not already exist.
+-Otherwise, if the file does not exist, an error message is printed.
+-The shell variable \fIflag\fP
+-is set to some non-null string if the \fB\(mic\fP
+-argument is encountered.
+-The commands
+-.DS
+-      ln \*(ZZ; rm \*(ZZ
+-.DE
+-make a link to the file and then remove it
+-thus causing the last modified date to be updated.
+-.LP
+-The sequence
+-.DS
+-      if command1
+-      then    command2
+-      fi
+-.DE
+-may be written
+-.DS
+-      command1 && command2
+-.DE
+-Conversely,
+-.DS
+-      command1 \*(VT\*(VT command2
+-.DE
+-executes \fIcommand2\fP only if \fIcommand1\fP
+-fails.
+-In each case the value returned
+-is that of the last simple command executed.
+-.SH
+-2.8\ Command\ grouping
+-.LP
+-Commands may be grouped in two ways,
+-.DS
+-      \fB{\fI command-list\fB ; }\fR
+-.DE
+-and
+-.DS
+-      \fB(\fI command-list\fB )\fR
+-.DE
+-.LP
+-In the first \fIcommand-list\fP is simply executed.
+-The second form executes \fIcommand-list\fP
+-as a separate process.
+-For example,
+-.DS
+-      (cd x; rm junk )
+-.DE
+-executes \fIrm junk\fP in the directory
+-\fBx\fP without changing the current
+-directory of the invoking shell.
+-.LP
+-The commands
+-.DS
+-      cd x; rm junk
+-.DE
+-have the same effect but leave the invoking
+-shell in the directory \fBx.\fP
+-.SH
+-2.9\ Debugging\ shell\ procedures
+-.LP
+-The shell provides two tracing mechanisms
+-to help when debugging shell procedures.
+-The first is invoked within the procedure
+-as
+-.DS
+-      set \(miv
+-.DE
+-(\fBv\fP for verbose) and causes lines of the
+-procedure to be printed as they are read.
+-It is useful to help isolate syntax errors.
+-It may be invoked without modifying the procedure
+-by saying
+-.DS
+-      sh \(miv proc \*(ZZ
+-.DE
+-where \fIproc\fP is the name of the shell procedure.
+-This flag may be used in conjunction
+-with the \fB\(min\fP flag which prevents
+-execution of subsequent commands.
+-(Note that saying \fIset \(min\fP at a terminal
+-will render the terminal useless
+-until an end-of-file is typed.)
+-.LP
+-The command
+-.DS
+-      set \(mix
+-.DE
+-will produce an execution
+-trace.
+-Following parameter substitution
+-each command is printed as it is executed.
+-(Try these at the terminal to see
+-what effect they have.)
+-Both flags may be turned off by saying
+-.DS
+-      set \(mi
+-.DE
+-and the current setting of the shell flags is available as \fB$\(mi\|.\fR
+-.SH
+-2.10\ The\ man\ command
+-.LP
+-The following is the \fIman\fP command
+-which is used to print sections of the UNIX manual.
+-It is called, for example, as
+-.DS
+-              man sh
+-              man \(mit ed
+-              man 2 fork
+-.DE
+-In the first the manual section for \fIsh\fP
+-is printed.
+-Since no section is specified, section 1 is used.
+-The second example will typeset (\fB\(mit\fP option)
+-the manual section for \fIed.\fP
+-The last prints the \fIfork\fP manual page
+-from section 2.
+-.sp 2
+-.DS
+-      cd /usr/man
+-
+-      : \'colon is the comment command\'
+-      : \'default is nroff ($N), section 1 ($s)\'
+-      N=n\ s=1
+-
+-      for i
+-      do case $i in
+-.sp .5
+-      \*(DC[1\(mi9]\*(ST)     s=$i ;;
+-.sp .5
+-      \*(DC\(mit)     N=t ;;
+-.sp .5
+-      \*(DC\(min)     N=n ;;
+-.sp .5
+-      \*(DC\(mi\*(ST) echo unknown flag \\\\\'$i\\\\\' ;;
+-.sp .5
+-      \*(DC\*(ST)     if test \(mif man$s/$i.$s
+-      \*(DC   then    ${N}roff man0/${N}aa man$s/$i.$s
+-      \*(DC   else    : \'look through all manual sections\'
+-      \*(DC           found=no
+-      \*(DC           for j in 1 2 3 4 5 6 7 8 9
+-      \*(DC           do if test \(mif man$j/$i.$j
+-      \*(DC           \*(DOthen man $j $i
+-      \*(DC           \*(DO\*(THfound=yes
+-      \*(DC           \*(DOfi
+-      \*(DC           done
+-      \*(DC           case $found in
+-      \*(DC           \*(Cano) echo \\'$i: manual page not found\\'
+-      \*(DC           esac
+-      \*(DC   fi
+-      \*(DOesac
+-      done
+-.DE
+-.ce
+-.ft B
+-Figure 1. A version of the man command
+-.ft R
+//GO.SYSIN DD t2
+echo t3
+sed 's/.//' >t3 <<'//GO.SYSIN DD t3'
+-.bp
+-.SH
+-3.0\ Keyword\ parameters
+-.LP
+-Shell variables may be given values
+-by assignment
+-or when a shell procedure is invoked.
+-An argument to a shell procedure of the form
+-\fIname=value\fP
+-that precedes the command name
+-causes \fIvalue\fP
+-to be assigned to \fIname\fP
+-before execution of the procedure begins.
+-The value of \fIname\fP in the invoking
+-shell is not affected.
+-For example,
+-.DS
+-      user=fred\ command
+-.DE
+-will execute \fIcommand\fP with
+-\fBuser\fP set to \fIfred\fP.
+-The \fB\(mik\fR flag causes arguments of the form
+-\fIname=value\fP to be interpreted in this way
+-anywhere in the argument list.
+-Such \fInames\fP are sometimes
+-called keyword parameters.
+-If any arguments remain they
+-are available as positional
+-parameters \fB$1, $2, \*(ZZ\|.\fP
+-.LP
+-The \fIset\fP command
+-may also be used to set positional parameters
+-from within a procedure.
+-For example,
+-.DS
+-      set\ \(mi\ \*(ST
+-.DE
+-will set \fB$1\fP to the first file name
+-in the current directory, \fB$2\fP to the next,
+-and so on.
+-Note that the first argument, \(mi, ensures correct treatment
+-when the first file name begins with a \(mi\|.
+-.LP
+-.SH
+-3.1\ Parameter\ transmission
+-.LP
+-When a shell procedure is invoked both positional
+-and keyword parameters may be supplied with the call.
+-Keyword parameters are also made available implicitly
+-to a shell procedure
+-by specifying in advance that such parameters
+-are to be exported.
+-For example,
+-.DS
+-      export\ user\ box
+-.DE
+-marks the variables \fBuser\fP and \fBbox\fP
+-for export.
+-When a shell procedure is invoked
+-copies are made of all exportable variables
+-for use within the invoked procedure.
+-Modification of such variables
+-within the procedure does not
+-affect the values in the invoking shell.
+-It is generally true of
+-a shell procedure
+-that it
+-may not modify the state
+-of its caller without explicit
+-request on the part of the caller.
+-(Shared file descriptors are an
+-exception to this rule.)
+-.LP
+-Names whose value is intended to remain
+-constant may be declared \fIreadonly\|.\fP
+-The form of this command is the same as that of the \fIexport\fP
+-command,
+-.DS
+-      readonly name \*(ZZ
+-.DE
+-Subsequent attempts to set readonly variables
+-are illegal.
+-.SH
+-3.2\ Parameter\ substitution
+-.LP
+-If a shell parameter is not set
+-then the null string is substituted for it.
+-For example, if the variable \fBd\fP
+-is not set
+-.DS
+-      echo $d
+-.DE
+-or
+-.DS
+-      echo ${d}
+-.DE
+-will echo nothing.
+-A default string may be given
+-as in
+-.DS
+-      echo ${d\(mi\fB.\fR}
+-.DE
+-which will echo
+-the value of the variable \fBd\fP
+-if it is set and `\fB.\fP' otherwise.
+-The default string is evaluated using the usual
+-quoting conventions so that
+-.DS
+-      echo ${d\(mi\'\*(ST\'}
+-.DE
+-will echo \fB\*(ST\fP if the variable \fBd\fP
+-is not set.
+-Similarly
+-.DS
+-      echo ${d\(mi$1}
+-.DE
+-will echo the value of \fBd\fP if it is set
+-and the value (if any) of \fB$1\fP otherwise.
+-A variable may be assigned a default value
+-using
+-the notation
+-.DS
+-      echo ${d=\fB.\fR}
+-.DE
+-which substitutes the same string as
+-.DS
+-      echo ${d\(mi\fB.\fR}
+-.DE
+-and if \fBd\fP were not previously set
+-then it will be set to the string `\fB.\fP'\|.
+-(The notation ${\*(ZZ=\*(ZZ}
+-is not available for positional parameters.)
+-.LP
+-If there is no sensible default then
+-the notation
+-.DS
+-      echo ${d?message}
+-.DE
+-will echo the value of the variable \fBd\fP if it has
+-one, otherwise \fImessage\fP is printed by the shell and
+-execution of the shell procedure is abandoned.
+-If \fImessage\fP is absent then a standard message
+-is printed.
+-A shell procedure that requires some parameters
+-to be set might start as follows.
+-.DS
+-      :\ ${user?}\ ${acct?}\ ${bin?}
+-      \*(ZZ
+-.DE
+-Colon (\fB:\fP) is a command
+-that is
+-built in to the shell and does nothing
+-once its arguments have been evaluated.
+-If any of the variables \fBuser, acct\fP
+-or \fBbin\fP are not set then the shell
+-will abandon execution of the procedure.
+-.SH
+-3.3\ Command\ substitution
+-.LP
+-The standard output from a command can be
+-substituted in a similar way to parameters.
+-The command \fIpwd\fP prints on its standard
+-output the name of the current directory.
+-For example, if the current directory is
+-\fB/usr/fred/bin\fR
+-then the command
+-.DS
+-      d=\`pwd\`
+-.DE
+-is equivalent to
+-.DS
+-      d=/usr/fred/bin
+-.DE
+-.LP
+-The entire string between grave accents (\`\*(ZZ\`)
+-is taken as the command
+-to be executed
+-and is replaced with the output from
+-the command.
+-The command is written using the usual
+-quoting conventions
+-except that a \fB\`\fR must be escaped using
+-a \fB\\\|.\fR
+-For example,
+-.DS
+-      ls \`echo "$1"\`
+-.DE
+-is equivalent to
+-.DS
+-      ls $1
+-.DE
+-Command substitution occurs in all contexts
+-where parameter substitution occurs (including \fIhere\fP documents) and the
+-treatment of the resulting text is the same
+-in both cases.
+-This mechanism allows string
+-processing commands to be used within
+-shell procedures.
+-An example of such a command is \fIbasename\fP
+-which removes a specified suffix from a string.
+-For example,
+-.DS
+-      basename main\fB.\fPc \fB.\fPc
+-.DE
+-will print the string \fImain\|.\fP
+-Its use is illustrated by the following
+-fragment from a \fIcc\fP command.
+-.DS
+-      case $A in
+-      \*(Ca\*(ZZ
+-      \*(Ca\*(ST\fB.\fPc)     B=\`basename $A \fB.\fPc\`
+-      \*(Ca\*(ZZ
+-      esac
+-.DE
+-that sets \fBB\fP to the part of \fB$A\fP
+-with the suffix \fB.c\fP stripped.
+-.LP
+-Here are some composite examples.
+-.RS
+-.IP \(bu
+-.ft B
+-for i in \`ls \(mit\`; do \*(ZZ
+-.ft R
+-.br
+-The variable \fBi\fP is set
+-to the names of files in time order,
+-most recent first.
+-.IP \(bu
+-.ft B
+-set \`date\`; echo $6 $2 $3, $4
+-.ft R
+-.br
+-will print, e.g.,
+-.ft I
+-1977 Nov 1, 23:59:59
+-.ft R
+-.RE
+-.SH
+-3.4\ Evaluation\ and\ quoting
+-.LP
+-The shell is a macro processor that
+-provides parameter substitution, command substitution and file
+-name generation for the arguments to commands.
+-This section discusses the order in which
+-these evaluations occur and the
+-effects of the various quoting mechanisms.
+-.LP
+-Commands are parsed initially according to the grammar
+-given in appendix A.
+-Before a command is executed
+-the following
+-substitutions occur.
+-.RS
+-.IP \(bu
+-parameter substitution, e.g. \fB$user\fP
+-.IP \(bu
+-command substitution, e.g. \fB\`pwd\`\fP
+-.RS
+-.LP
+-Only one evaluation occurs so that if, for example, the value of the variable
+-\fBX\fP
+-is the string \fI$y\fP
+-then
+-.DS
+-      echo $X
+-.DE
+-will echo \fI$y\|.\fP
+-.RE
+-.IP \(bu
+-blank interpretation
+-.RS
+-.LP
+-Following the above substitutions
+-the resulting characters
+-are broken into non-blank words (\fIblank interpretation\fP).
+-For this purpose `blanks' are the characters of the string
+-\fB$\s-1IFS\s0\fP.
+-By default, this string consists of blank, tab and newline.
+-The null string
+-is not regarded as a word unless it is quoted.
+-For example,
+-.DS
+-      echo \'\'
+-.DE
+-will pass on the null string as the first argument to \fIecho\fP,
+-whereas
+-.DS
+-      echo $null
+-.DE
+-will call \fIecho\fR with no arguments
+-if the variable \fBnull\fP is not set
+-or set to the null string.
+-.RE
+-.IP \(bu
+-file name generation
+-.RS
+-.LP
+-Each word
+-is then scanned for the file pattern characters
+-\fB\*(ST, ?\fR and \fB[\*(ZZ]\fR
+-and an alphabetical list of file names
+-is generated to replace the word.
+-Each such file name is a separate argument.
+-.RE
+-.RE
+-.LP
+-The evaluations just described also occur
+-in the list of words associated with a \fBfor\fP
+-loop.
+-Only substitution occurs
+-in the \fIword\fP used
+-for a \fBcase\fP branch.
+-.LP
+-As well as the quoting mechanisms described
+-earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR
+-a third quoting mechanism is provided using double quotes.
+-Within double quotes parameter and command substitution
+-occurs but file name generation and the interpretation
+-of blanks does not.
+-The following characters
+-have a special meaning within double quotes
+-and may be quoted using \fB\\\|.\fP
+-.DS
+-      \fB$    \fPparameter substitution
+-      \fB\`\fP        command substitution
+-      \fB"\fP ends the quoted string
+-      \fB\e\fP        quotes the special characters \fB$ \` " \e\fP
+-.DE
+-For example,
+-.DS
+-      echo "$x"
+-.DE
+-will pass the value of the variable \fBx\fP as a
+-single argument to \fIecho.\fP
+-Similarly,
+-.DS
+-      echo "$\*(ST"
+-.DE
+-will pass the positional parameters as a single
+-argument and is equivalent to
+-.DS
+-      echo "$1 $2 \*(ZZ"
+-.DE
+-The notation \fB$@\fP
+-is the same as \fB$\*(ST\fR
+-except when it is quoted.
+-.DS
+-      echo "$@"
+-.DE
+-will pass the positional parameters, unevaluated, to \fIecho\fR
+-and is equivalent to
+-.DS
+-      echo "$1" "$2" \*(ZZ
+-.DE
+-.LP
+-The following table gives, for each quoting mechanism,
+-the shell metacharacters that are evaluated.
+-.DS
+-.ce
+-.ft I
+-metacharacter
+-.ft
+-.in 1.5i
+-      \e      $       *       \`      "       \'
+-\'    n       n       n       n       n       t
+-\`    y       n       n       t       n       n
+-"     y       y       n       y       t       n
+-
+-      t       terminator
+-      y       interpreted
+-      n       not interpreted
+-
+-.in
+-.ft B
+-.ce
+-Figure 2. Quoting mechanisms
+-.ft
+-.DE
+-.LP
+-In cases where more than one evaluation of a string
+-is required the built-in command \fIeval\fP
+-may be used.
+-For example,
+-if the variable \fBX\fP has the value
+-\fI$y\fP, and if \fBy\fP has the value \fIpqr\fP
+-then
+-.DS
+-      eval echo $X
+-.DE
+-will echo the string \fIpqr\|.\fP
+-.LP
+-In general the \fIeval\fP command
+-evaluates its arguments (as do all commands)
+-and treats the result as input to the shell.
+-The input is read and the resulting command(s)
+-executed.
+-For example,
+-.DS
+-      wg=\\'eval who\*(VTgrep\\'
+-      $wg fred
+-.DE
+-is equivalent to
+-.DS
+-      who\*(VTgrep fred
+-.DE
+-In this example,
+-\fIeval\fP is required
+-since there is no interpretation
+-of metacharacters, such as \fB\*(VT\|,\fP following
+-substitution.
+-.SH
+-3.5\ Error\ handling
+-.LP
+-The treatment of errors detected by
+-the shell depends on the type of error
+-and on whether the shell is being
+-used interactively.
+-An interactive shell is one whose
+-input and output are connected
+-to a terminal (as determined by
+-\fIgtty\fP (2)).
+-A shell invoked with the \fB\(mii\fP
+-flag is also interactive.
+-.LP
+-Execution of a command (see also 3.7) may fail
+-for any of the following reasons.
+-.IP \(bu
+-Input output redirection may fail.
+-For example, if a file does not exist
+-or cannot be created.
+-.IP \(bu
+-The command itself does not exist
+-or cannot be executed.
+-.IP \(bu
+-The command terminates abnormally,
+-for example, with a "bus error"
+-or "memory fault".
+-See Figure 2 below for a complete list
+-of UNIX signals.
+-.IP \(bu
+-The command terminates normally
+-but returns a non-zero exit status.
+-.LP
+-In all of these cases the shell
+-will go on to execute the next command.
+-Except for the last case an error
+-message will be printed by the shell.
+-All remaining errors cause the shell
+-to exit from a command procedure.
+-An interactive shell will return
+-to read another command from the terminal.
+-Such errors include the following.
+-.IP \(bu
+-Syntax errors.
+-e.g., if \*(ZZ then \*(ZZ done
+-.IP \(bu
+-A signal such as interrupt.
+-The shell waits for the current
+-command, if any, to finish execution and
+-then either exits or returns to the terminal.
+-.IP \(bu
+-Failure of any of the built-in commands
+-such as \fIcd.\fP
+-.LP
+-The shell flag \fB\(mie\fP
+-causes the shell to terminate
+-if any error is detected.
+-.DS
+-1     hangup
+-2     interrupt
+-3*    quit
+-4*    illegal instruction
+-5*    trace trap
+-6*    IOT instruction
+-7*    EMT instruction
+-8*    floating point exception
+-9     kill (cannot be caught or ignored)
+-10*   bus error
+-11*   segmentation violation
+-12*   bad argument to system call
+-13    write on a pipe with no one to read it
+-14    alarm clock
+-15    software termination (from \fIkill\fP (1))
+-
+-.DE
+-.ft B
+-.ce
+-Figure 3. UNIX signals
+-.ft
+-
+-Those signals marked with an asterisk
+-produce a core dump
+-if not caught.
+-However,
+-the shell itself ignores quit which is the only
+-external signal that can cause a dump.
+-The signals in this list of potential interest
+-to shell programs are 1, 2, 3, 14 and 15.
+-.SH
+-3.6\ Fault\ handling
+-.LP
+-Shell procedures normally terminate
+-when an interrupt is received from the
+-terminal.
+-The \fItrap\fP command is used
+-if some cleaning up is required, such
+-as removing temporary files.
+-For example,
+-.DS
+-      trap\ \'rm\ /tmp/ps$$; exit\'\ 2
+-.DE
+-sets a trap for signal 2 (terminal
+-interrupt), and if this signal is received
+-will execute the commands
+-.DS
+-      rm /tmp/ps$$; exit
+-.DE
+-\fIexit\fP is
+-another built-in command
+-that terminates execution of a shell procedure.
+-The \fIexit\fP is required; otherwise,
+-after the trap has been taken,
+-the shell will resume executing
+-the procedure
+-at the place where it was interrupted.
+-.LP
+-UNIX signals can be handled in one of three ways.
+-They can be ignored, in which case
+-the signal is never sent to the process.
+-They can be caught, in which case the process
+-must decide what action to take when the
+-signal is received.
+-Lastly, they can be left to cause
+-termination of the process without
+-it having to take any further action.
+-If a signal is being ignored
+-on entry to the shell procedure, for example,
+-by invoking it in the background (see 3.7) then \fItrap\fP
+-commands (and the signal) are ignored.
+-.LP
+-The use of \fItrap\fP is illustrated
+-by this modified version of the \fItouch\fP
+-command (Figure 4).
+-The cleanup action is to remove the file \fBjunk$$\fR\|.
+-.DS
+-      flag=
+-      trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15
+-      for i
+-      do\ case\ $i\ in
+-      \*(DC\(mic)     flag=N ;;
+-      \*(DC\*(ST)     if\ test\ \(mif\ $i
+-      \*(DC   then    ln\ $i\ junk$$;\ rm\ junk$$
+-      \*(DC   elif\ test\ $flag
+-      \*(DC   then    echo\ file\ \\\\\'$i\\\\\'\ does\ not\ exist
+-      \*(DC   else    >$i
+-      \*(DC   fi
+-      \*(DOesac
+-      done
+-.DE
+-.sp
+-.ft B
+-.ce
+-Figure 4. The touch command
+-.ft
+-.sp
+-The \fItrap\fP command
+-appears before the creation
+-of the temporary file;
+-otherwise it would be
+-possible for the process
+-to die without removing
+-the file.
+-.LP
+-Since there is no signal 0 in UNIX
+-it is used by the shell to indicate the
+-commands to be executed on exit from the
+-shell procedure.
+-.LP
+-A procedure may, itself, elect to
+-ignore signals by specifying the null
+-string as the argument to trap.
+-The following fragment is taken from the
+-\fInohup\fP command.
+-.DS
+-      trap \'\' 1 2 3 15
+-.DE
+-which causes \fIhangup, interrupt, quit \fRand\fI kill\fR
+-to be ignored both by the
+-procedure and by invoked commands.
+-.LP
+-Traps may be reset by saying
+-.DS
+-      trap 2 3
+-.DE
+-which resets the traps for signals 2 and 3 to their default values.
+-A list of the current values of traps may be obtained
+-by writing
+-.DS
+-      trap
+-.DE
+-.LP
+-The procedure \fIscan\fP (Figure 5) is an example
+-of the use of \fItrap\fP where there is no exit
+-in the trap command.
+-\fIscan\fP takes each directory
+-in the current directory, prompts
+-with its name, and then executes
+-commands typed at the terminal
+-until an end of file or an interrupt is received.
+-Interrupts are ignored while executing
+-the requested commands but cause
+-termination when \fIscan\fP is
+-waiting for input.
+-.DS
+-      d=\`pwd\`
+-      for\ i\ in\ \*(ST
+-      do\ if\ test\ \(mid\ $d/$i
+-      \*(DOthen\ cd\ $d/$i
+-      \*(DO\*(THwhile\ echo\ "$i:"
+-      \*(DO\*(TH\*(WHtrap\ exit\ 2
+-      \*(DO\*(TH\*(WHread\ x
+-      \*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done
+-      \*(DOfi
+-      done
+-.DE
+-.sp
+-.ft B
+-.ce
+-Figure 5. The scan command
+-.ft
+-.sp
+-\fIread x\fR is a built-in command that reads one line from the
+-standard input
+-and places the result in the variable \fBx\|.\fP
+-It returns a non-zero exit status if either
+-an end-of-file is read or an interrupt
+-is received.
+-.SH
+-3.7\ Command\ execution
+-.LP
+-To run a command (other than a built-in) the shell first creates
+-a new process using the system call \fIfork.\fP
+-The execution environment for the command
+-includes input, output and the states of signals, and
+-is established in the child process
+-before the command is executed.
+-The built-in command \fIexec\fP
+-is used in the rare cases when no fork
+-is required
+-and simply replaces the shell with a new command.
+-For example, a simple version of the \fInohup\fP
+-command looks like
+-.DS
+-      trap \\'\\' 1 2 3 15
+-      exec $\*(ST
+-.DE
+-The \fItrap\fP turns off the signals specified
+-so that they are ignored by subsequently created commands
+-and \fIexec\fP replaces the shell by the command
+-specified.
+-.LP
+-Most forms of input output redirection have already been
+-described.
+-In the following \fIword\fP is only subject
+-to parameter and command substitution.
+-No file name generation or blank interpretation
+-takes place so that, for example,
+-.DS
+-              echo \*(ZZ >\*(ST.c
+-.DE
+-will write its output into a file whose name is \fB\*(ST.c\|.\fP
+-Input output specifications are evaluated left to right
+-as they appear in the command.
+-.IP >\ \fIword\fP 12
+-The standard output (file descriptor 1)
+-is sent to the file \fIword\fP which is
+-created if it does not already exist.
+-.IP \*(AP\ \fIword\fP 12
+-The standard output is sent to file \fIword.\fP
+-If the file exists then output is appended
+-(by seeking to the end);
+-otherwise the file is created.
+-.IP <\ \fIword\fP 12
+-The standard input (file descriptor 0)
+-is taken from the file \fIword.\fP
+-.IP \*(HE\ \fIword\fP 12
+-The standard input is taken from the lines
+-of shell input that follow up to but not
+-including a line consisting only of \fIword.\fP
+-If \fIword\fP is quoted then no interpretation
+-of the document occurs.
+-If \fIword\fP is not quoted
+-then parameter and command substitution
+-occur and \fB\\\fP is used to quote
+-the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character
+-of \fIword.\fP
+-In the latter case \fB\\newline\fP is ignored (c.f. quoted strings).
+-.IP >&\ \fIdigit\fP 12
+-The file descriptor \fIdigit\fP is duplicated using the system
+-call \fIdup\fP (2)
+-and the result is used as the standard output.
+-.IP <&\ \fIdigit\fP 12
+-The standard input is duplicated from file descriptor \fIdigit.\fP
+-.IP <&\(mi 12
+-The standard input is closed.
+-.IP >&\(mi 12
+-The standard output is closed.
+-.LP
+-Any of the above may be preceded by a digit in which
+-case the file descriptor created is that specified by the digit
+-instead of the default 0 or 1.
+-For example,
+-.DS
+-      \*(ZZ 2>file
+-.DE
+-runs a command with message output (file descriptor 2)
+-directed to \fIfile.\fP
+-.DS
+-      \*(ZZ 2>&1
+-.DE
+-runs a command with its standard output and message output
+-merged.
+-(Strictly speaking file descriptor 2 is created
+-by duplicating file descriptor 1 but the effect is usually to
+-merge the two streams.)
+-.LP
+-The environment for a command run in the background such as
+-.DS
+-      list \*(ST.c \*(VT lpr &
+-.DE
+-is modified in two ways.
+-Firstly, the default standard input
+-for such a command is the empty file \fB/dev/null\|.\fR
+-This prevents two processes (the shell and the command),
+-which are running in parallel, from trying to
+-read the same input.
+-Chaos would ensue
+-if this were not the case.
+-For example,
+-.DS
+-      ed file &
+-.DE
+-would allow both the editor and the shell
+-to read from the same input at the same time.
+-.LP
+-The other modification to the environment of a background
+-command is to turn off the QUIT and INTERRUPT signals
+-so that they are ignored by the command.
+-This allows these signals to be used
+-at the terminal without causing background
+-commands to terminate.
+-For this reason the UNIX convention
+-for a signal is that if it is set to 1
+-(ignored) then it is never changed
+-even for a short time.
+-Note that the shell command \fItrap\fP
+-has no effect for an ignored signal.
+-.SH
+-3.8\ Invoking\ the\ shell
+-.LP
+-The following flags are interpreted by the shell
+-when it is invoked.
+-If the first character of argument zero is a minus,
+-then commands are read from the file \fB.profile\|.\fP
+-.IP \fB\(mic\fP\ \fIstring\fP
+-.br
+-If the \fB\(mic\fP flag is present then
+-commands are read from \fIstring\|.\fP
+-.IP \fB\(mis\fP
+-If the \fB\(mis\fP flag is present or if no
+-arguments remain
+-then commands are read from the standard input.
+-Shell output is written to
+-file descriptor 2.
+-.IP \fB\(mii\fP
+-If the \fB\(mii\fP flag is present or
+-if the shell input and output are attached to a terminal (as told by \fIgtty\fP)
+-then this shell is \fIinteractive.\fP
+-In this case TERMINATE is ignored (so that \fBkill 0\fP
+-does not kill an interactive shell) and INTERRUPT is caught and ignored
+-(so that \fBwait\fP is interruptable).
+-In all cases QUIT is ignored by the shell.
+-.SH
+-Acknowledgements
+-.LP
+-The design of the shell is
+-based in part on the original UNIX shell
+-.[
+-unix command language thompson
+-.]
+-and the PWB/UNIX shell,
+-.[
+-pwb shell mashey unix
+-.]
+-some
+-features having been taken from both.
+-Similarities also exist with the
+-command interpreters
+-of the Cambridge Multiple Access System
+-.[
+-cambridge multiple access system hartley
+-.]
+-and of CTSS.
+-.[
+-ctss
+-.]
+-.LP
+-I would like to thank Dennis Ritchie
+-and John Mashey for many
+-discussions during the design of the shell.
+-I am also grateful to the members of the Computing Science Research Center
+-and to Joe Maranzano for their
+-comments on drafts of this document.
+-.SH
+-.[
+-$LIST$
+-.]
+//GO.SYSIN DD t3
+echo t4
+sed 's/.//' >t4 <<'//GO.SYSIN DD t4'
+-.bp
+-.SH
+-Appendix\ A\ -\ Grammar
+-.LP
+-.DS
+-\fIitem:              word
+-              input-output
+-              name = value
+-.sp 0.8
+-simple-command: item
+-              simple-command item
+-.sp 0.8
+-command:      simple-command
+-              \fB( \fIcommand-list \fB)
+-              \fB{ \fIcommand-list \fB}
+-              \fBfor \fIname \fBdo \fIcommand-list \fBdone
+-              \fBfor \fIname \fBin \fIword \*(ZZ \fBdo \fIcommand-list \fBdone
+-              \fBwhile \fIcommand-list \fBdo \fIcommand-list \fBdone
+-              \fBuntil \fIcommand-list \fBdo \fIcommand-list \fBdone
+-              \fBcase \fIword \fBin \fIcase-part \*(ZZ \fBesac
+-              \fBif \fIcommand-list \fBthen \fIcommand-list \fIelse-part \fBfi
+-.sp 0.8
+-\fIpipeline:          command
+-              pipeline \fB\*(VT\fI command
+-.sp 0.8
+-andor:                pipeline
+-              andor \fB&&\fI pipeline
+-              andor \fB\*(VT\*(VT\fI pipeline
+-.sp 0.8
+-command-list: andor
+-              command-list \fB;\fI
+-              command-list \fB&\fI
+-              command-list \fB;\fI andor
+-              command-list \fB&\fI andor
+-.sp 0.8
+-input-output: \fB> \fIfile
+-              \fB< \fIfile
+-              \fB\*(AP \fIword
+-              \fB\*(HE \fIword
+-.sp 0.8
+-file:         word
+-              \fB&\fI digit
+-              \fB&\fI \(mi
+-.sp 0.8
+-case-part:    pattern\fB ) \fIcommand-list\fB ;;
+-.sp 0.8
+-\fIpattern:           word
+-              pattern \fB\*(VT\fI word
+-.sp 0.8
+-\fIelse-part: \fBelif \fIcommand-list\fB then\fI command-list else-part\fP
+-              \fBelse \fIcommand-list\fI
+-              empty
+-.sp 0.8
+-empty:
+-.sp 0.8
+-word:         \fRa sequence of non-blank characters\fI
+-.sp 0.8
+-name:         \fRa sequence of letters, digits or underscores starting with a letter\fI
+-.sp 0.8
+-digit:                \fB0 1 2 3 4 5 6 7 8 9\fP
+-.DE
+-.LP
+-.bp
+-.SH
+-Appendix\ B\ -\ Meta-characters\ and\ Reserved\ Words
+-.LP
+-a) syntactic
+-.RS
+-.IP \fB\*(VT\fR 6
+-pipe symbol
+-.IP \fB&&\fR 6
+-`andf' symbol
+-.IP \fB\*(VT\*(VT\fR 6
+-`orf' symbol
+-.IP \fB;\fP 6
+-command separator
+-.IP \fB;;\fP 6
+-case delimiter
+-.IP \fB&\fP 6
+-background commands
+-.IP \fB(\ )\fP 6
+-command grouping
+-.IP \fB<\fP 6
+-input redirection
+-.IP \fB\*(HE\fP 6
+-input from a here document
+-.IP \fB>\fP 6
+-output creation
+-.IP \fB\*(AP\fP 6
+-output append
+-.sp 2
+-.RE
+-.LP
+-b) patterns
+-.RS
+-.IP \fB\*(ST\fP 6
+-match any character(s) including none
+-.IP \fB?\fP 6
+-match any single character
+-.IP \fB[...]\fP 6
+-match any of the enclosed characters
+-.sp 2
+-.RE
+-.LP
+-c) substitution
+-.RS
+-.IP \fB${...}\fP 6
+-substitute shell variable
+-.IP \fB\`...\`\fP 6
+-substitute command output
+-.sp 2
+-.RE
+-.LP
+-d) quoting
+-.RS
+-.IP \fB\e\fP 6
+-quote the next character
+-.IP \fB\'...\'\fP 6
+-quote the enclosed characters except for \'
+-.IP \fB"\&..."\fR 6
+-quote the enclosed characters except
+-for \fB$ \` \e "\fP
+-.sp 2
+-.RE
+-.LP
+-e) reserved words
+-.DS
+-.ft B
+-if then else elif fi
+-case in esac
+-for while until do done
+-{  }
+-.ft
+-.DE
+//GO.SYSIN DD t4
diff --git a/doc/7thEdMan/vol2/summary.bun b/doc/7thEdMan/vol2/summary.bun
new file mode 100644 (file)
index 0000000..e396575
--- /dev/null
@@ -0,0 +1,1576 @@
+# To unbundle, run this file
+echo hel.mac
+sed 's/.//' >hel.mac <<'//GO.SYSIN DD hel.mac'
+-.hy 9
+-.de op
+-.nr PD 0
+-.IP \h'1i'\(ci 1i+2
+-.nr PD .5v
+-..
+-.de sh
+-.IP "\(sq\ \\$1" 1i
+-..
+-.de OP
+-.op \\$1 \\$2 \\$3
+-..
+-.de UC
+-\&\\$3\\s-1\\$1\\s0\\$2\&
+-..
+//GO.SYSIN DD hel.mac
+echo hel0
+sed 's/.//' >hel0 <<'//GO.SYSIN DD hel0'
+-.TL
+-7th Edition UNIX \(em Summary
+-.AU
+-September 6, 1978
+-.AI
+-.MH
+-.SH
+-A.  What's new: highlights of the 7th edition UNIX\(dg System
+-.FS
+-\(dg
+-.UC UNIX
+-is a Trademark of Bell Laboratories.
+-.FE
+-.LP
+-.B "Aimed at larger systems."
+-Devices are addressable to 2\u\s-231\s+2\d
+-bytes, files to 2\u\s-230\s+2\d bytes.
+-128K memory (separate instruction and data space) is needed for some utilities.
+-.LP
+-.B "Portability."
+-Code of the operating system and most utilities has
+-been extensively revised to minimize its
+-dependence on particular hardware.
+-.LP
+-.B "Fortran 77."
+-F77 compiler for the new standard language
+-is compatible with C at the object level.
+-A Fortran structurer, STRUCT, converts old, ugly Fortran into RATFOR,
+-a structured dialect usable with F77.
+-.LP
+-.B "Shell."
+-Completely new SH program supports string variables,
+-trap handling, structured programming, user profiles,
+-settable search path,
+-multilevel file name generation, etc.
+-.LP
+-.B "Document preparation."
+-TROFF phototypesetter utility is standard.
+-NROFF (for terminals) is now highly compatible
+-with TROFF.
+-MS macro package provides canned commands for
+-many common formatting and layout situations.
+-TBL provides an easy to learn language for preparing
+-complicated tabular material.
+-REFER fills in bibliographic citations
+-from a data base.
+-.LP
+-.B "UNIX-to-UNIX file copy."
+-UUCP performs spooled
+-file transfers between any two machines.
+-.LP
+-.B "Data processing."
+-SED stream editor does multiple editing functions
+-in parallel on a data stream of indefinite length.
+-AWK report generator does free-field pattern selection
+-and arithmetic operations.
+-.LP
+-.B "Program development."
+-MAKE
+-controls re-creation of complicated software,
+-arranging for minimal recompilation.
+-.LP
+-.B "Debugging."
+-ADB does postmortem and breakpoint debugging,
+-handles separate instruction and data spaces,
+-floating point, etc.
+-.LP
+-.B "C language."
+-The language now supports
+-definable data types, generalized initialization,
+-block structure, long integers,
+-unions,
+-explicit type conversions.
+-The LINT verifier does strong type checking
+-and detection of probable errors and portability problems
+-even across separately compiled functions.
+-.LP
+-.B "Lexical analyzer generator."
+-LEX converts specification of regular expressions
+-and semantic actions into a recognizing subroutine.
+-Analogous to YACC.
+-.LP
+-.B "Graphics."
+-Simple graph-drawing utility, graphic subroutines, and
+-generalized plotting filters adapted to various devices
+-are now standard.
+-.LP
+-.B "Standard input-output package."
+-Highly efficient buffered stream I/O is
+-integrated with formatted input and output.
+-.LP
+-.B "Other."
+-The operating system and utilities have been enhanced
+-and freed of restrictions in many
+-other ways too numerous to relate.
+-.sp 100
+//GO.SYSIN DD hel0
+echo hel1
+sed 's/.//' >hel1 <<'//GO.SYSIN DD hel1'
+-.SH
+-B.  Hardware
+-.PP
+-The
+-7th edition
+-.UC UNIX
+-operating system
+-runs on
+-a DEC PDP-11/45 or 11/70*
+-.FS
+-*PDP is a Trademark of Digital Equipment Corporation.
+-.FE
+-with at least the following equipment:
+-.IP
+-128K to 2M words of managed memory; parity not used.
+-.IP
+-disk: RP03, RP04, RP06, RK05 (more than 1 RK05) or equivalent.
+-.IP
+-console typewriter.
+-.IP
+-clock: KW11-L or KW11-P.
+-.LP
+-The following equipment is strongly recommended:
+-.IP
+-communications controller such as DL11 or DH11.
+-.IP
+-full duplex 96-character ASCII terminals.
+-.IP
+-9-track tape or extra disk for system backup.
+-.LP
+-The system is normally distributed on 9-track tape.
+-The minimum memory and disk space specified is enough to run
+-and maintain
+-.UC UNIX .
+-More will be needed to keep all source on line, or to handle
+-a large number of users,
+-big data bases, diversified complements of devices, or large
+-programs.
+-The resident code
+-occupies 12-20K words depending
+-on configuration;
+-system data occupies 10-28K words.
+-.PP
+-There is no commitment to provide 7th edition
+-.UC UNIX
+-on PDP-11/34, 11/40 and 11/60 hardware.
+-.SH
+-C.  Software
+-.PP
+-Most of the programs available as
+-.UC UNIX
+-commands are listed.
+-Source code and printed manuals are 
+-distributed for all of the listed software
+-except games.
+-Almost all of the code is written in C.
+-Commands are self-contained and do not require extra setup
+-information,
+-unless specifically noted as ``interactive.''
+-Interactive programs can be made to run from a prepared script
+-simply by redirecting input.
+-Most programs intended for interactive use
+-(e.g., the editor) 
+-allow for an escape to
+-command level (the Shell).
+-Most file processing commands
+-can also go from standard input to standard output
+-(``filters'').
+-The piping facility of the Shell may be used
+-to connect such filters directly to the input or output
+-of other programs.
+-.NH
+-Basic Software
+-.PP
+-This
+-includes the time-sharing operating
+-system with utilities, a machine language assembler and a 
+-compiler for the programming language C\(emenough
+-software to
+-write and run new applications
+-and to maintain or modify
+-.UC UNIX
+-itself.
+-.NH 2
+-Operating System
+-.sh UNIX
+-The basic resident code
+-on which everything else depends.
+-Supports the system calls, and maintains the file system.
+-A general description of
+-.UC UNIX
+-design
+-philosophy and system facilities appeared in
+-the Communications of the ACM, July, 1974.
+-A more extensive survey is in the Bell System Technical Journal
+-for July-August 1978.
+-Capabilities include:
+-.op
+-Reentrant code for user processes.
+-.op
+-Separate instruction and data spaces.
+-.op
+-``Group'' access permissions for cooperative projects,
+-with overlapping memberships.
+-.op
+-Alarm-clock timeouts.
+-.op
+-Timer-interrupt sampling and interprocess monitoring
+-for debugging and measurement.
+-.OP
+-Multiplexed I/O for machine-to-machine communication.
+-.sh DEVICES
+-All I/O is logically synchronous.
+-I/O devices are simply files in the file system.
+-Normally, invisible buffering makes all physical
+-record structure and device characteristics transparent and exploits the
+-hardware's ability to do overlapped I/O.
+-Unbuffered physical record
+-I/O is available for unusual applications.
+-Drivers for these devices are
+-available; others can be easily written:
+-.op
+-Asynchronous interfaces: DH11, DL11.
+-Support for most common ASCII terminals.
+-.op
+-Synchronous interface: DP11.
+-.op
+-Automatic calling unit interface: DN11.
+-.op
+-Line printer: LP11.
+-.op
+-Magnetic tape: TU10 and TU16.
+-.op
+-DECtape: TC11.
+-.op
+-Fixed head disk: RS11, RS03 and RS04.
+-.op
+-Pack type disk: RP03, RP04, RP06;
+-minimum-latency seek scheduling.
+-.op
+-Cartridge-type disk: RK05, one or more physical devices per
+-logical device.
+-.op
+-Null device.
+-.op
+-Physical memory of PDP-11, or mapped memory in resident system.
+-.op
+-Phototypesetter: Graphic Systems System/1 through DR11C.
+-.sh BOOT
+-Procedures to get
+-.UC UNIX
+-started.
+-.sh MKCONF
+-Tailor device-dependent system code to hardware configuration.
+-As distributed,
+-.UC UNIX
+-can 
+-be brought up directly on any acceptable CPU
+-with any acceptable disk, any sufficient amount of core,
+-and either clock.
+-Other changes, such as optimal
+-assignment of directories to devices, inclusion of floating
+-point simulator, or installation of device names in file system,
+-can then be made at leisure.
+-.NH 2
+-User Access Control
+-.LP
+-.sh LOGIN
+-Sign on as a new user.
+-.op
+-Verify password and establish user's 
+-individual and group (project) identity.
+-.op
+-Adapt to characteristics of terminal.
+-.op
+-Establish working directory.
+-.op
+-Announce presence of mail (from MAIL).
+-.op
+-Publish message of the day.
+-.op
+-Execute user-specified profile.
+-.op
+-Start command interpreter or other initial program.
+-.sh PASSWD
+-Change a password.
+-.op
+-User can change his own password.
+-.op
+-Passwords are kept encrypted for security.
+-.sh NEWGRP
+-Change working group (project).
+-Protects against unauthorized changes to projects.
+-.NH 2
+-Terminal Handling
+-.LP
+-.sh TABS
+-Set tab stops appropriately for specified terminal type.
+-.sh STTY
+-Set up options for optimal control of a terminal.
+-In so far as they are deducible from the input, these
+-options are set automatically by LOGIN.
+-.op
+-Half vs. full duplex.
+-.op
+-Carriage return+line feed vs. newline.
+-.op
+-Interpretation of tabs.
+-.op
+-Parity.
+-.op
+-Mapping of upper case to lower.
+-.op
+-Raw vs. edited input.
+-.op
+-Delays for tabs, newlines and carriage returns.
+-.NH 2
+-File Manipulation
+-.LP
+-.sh CAT
+-Concatenate one or more files onto standard output.
+-Particularly used for unadorned printing, for
+-inserting data into a pipeline,
+-and for buffering output that comes in dribs and drabs.
+-Works on any file regardless of contents.
+-.sh CP
+-Copy one file to another,
+-or a set of files to a directory.
+-Works on any file regardless of contents.
+-.sh PR
+-Print files with title, date, and page number on every page.
+-.op
+-Multicolumn output.
+-.op
+-Parallel column merge of several files.
+-.sh LPR
+-Off-line print.
+-Spools arbitrary files to the line printer.
+-.sh CMP
+-Compare two files and report if different.
+-.sh TAIL
+-Print last
+-.I n
+-lines of input
+-.op
+-May print last
+-.I n
+-characters, or from
+-.I n
+-lines or characters to end.
+-.sh SPLIT
+-Split a large file into more manageable pieces.
+-Occasionally necessary for editing (ED).
+-.sh DD
+-Physical file format translator,
+-for exchanging data with foreign
+-systems, especially IBM 370's.
+-.sh SUM
+-Sum the words of a file.
+-.NH 2
+-Manipulation of Directories and File Names
+-.LP
+-.sh RM
+-Remove a file.
+-Only the name goes away if any other names are linked to the file.
+-.OP
+-Step through a directory deleting files interactively.
+-.OP
+-Delete entire directory hierarchies.
+-.sh LN
+-``Link'' another name (alias) to an existing file.
+-.sh MV
+-Move a file or files.
+-Used for renaming files.
+-.sh CHMOD
+-Change permissions on one or more files.
+-Executable by files' owner.
+-.sh CHOWN
+-Change owner of one or more files.
+-.sh CHGRP
+-Change group (project) to which a file belongs.
+-.sh MKDIR
+-Make a new directory.
+-.sh RMDIR
+-Remove a directory.
+-.sh CD
+-Change working directory.
+-.sh FIND
+-Prowl the directory
+-hierarchy finding
+-every file that meets
+-specified criteria.
+-.op
+-Criteria include:
+-.in +2
+-.nf
+-name matches a given pattern,
+-creation date in given range,
+-date of last use in given range,
+-given permissions,
+-given owner,
+-given special file characteristics,
+-boolean combinations of above.
+-.in -2
+-.fi
+-.op
+-Any directory may be considered to be the root.
+-.op
+-Perform specified command on each file found.
+-.NH 2
+-Running of Programs
+-.LP
+-.sh SH
+-The Shell, or command language interpreter.
+-.op
+-Supply arguments to and run any executable program.
+-.op
+-Redirect standard input, standard output, and standard error files.
+-.op
+-Pipes:
+-simultaneous execution with output of one process connected
+-to the input of another.
+-.OP
+-Compose compound commands using:
+-.in+2
+-if ... then ... else,
+-.br
+-case switches,
+-.br
+-while loops,
+-.br
+-for loops over lists,
+-.br
+-break, continue and exit,
+-.br
+-parentheses for grouping.
+-.in -2
+-.op
+-Initiate background processes.
+-.op
+-Perform Shell programs, i.e., command scripts with
+-substitutable arguments.
+-.op
+-Construct argument lists from all file names
+-satisfying specified patterns.
+-.OP
+-Take special action on traps and interrupts.
+-.OP
+-User-settable search path for finding commands.
+-.OP
+-Executes user-settable profile upon login.
+-.OP
+-Optionally announces presence of mail as it arrives.
+-.op
+-Provides variables and parameters with default setting.
+-.sh TEST
+-Tests for use in Shell conditionals.
+-.op
+-String comparison.
+-.op
+-File nature and accessibility.
+-.op
+-Boolean combinations of the above.
+-.sh EXPR
+-String computations for calculating command arguments.
+-.OP
+-Integer arithmetic
+-.OP
+-Pattern matching
+-.sh WAIT
+-Wait for termination of asynchronously running processes.
+-.sh READ
+-Read a line from terminal,
+-for interactive Shell procedure.
+-.sh ECHO
+-Print remainder of command line.
+-Useful for diagnostics or prompts in Shell programs,
+-or for inserting data into a pipeline.
+-.sh SLEEP
+-Suspend execution for a specified time.
+-.sh NOHUP
+-Run a command immune to hanging up the terminal.
+-.sh NICE
+-Run a command in low (or high) priority.
+-.sh KILL
+-Terminate named processes.
+-.sh CRON
+-Schedule regular actions at specified times.
+-.op
+-Actions are arbitrary programs.
+-.op
+-Times are
+-conjunctions of month, day of month, day of week, hour
+-and minute.
+-Ranges are specifiable for each.
+-.sh AT
+-Schedule a one-shot action for an arbitrary time.
+-.sh TEE
+-Pass data between processes and divert a copy into one or more files.
+-.NH 2
+-Status Inquiries
+-.LP
+-.sh LS
+-List the names of one, several, or all files in one or more directories.
+-.op
+-Alphabetic or temporal sorting, up or down.
+-.op
+-Optional information:
+-size,
+-owner,
+-group,
+-date last modified,
+-date last accessed,
+-permissions,
+-i-node number.
+-.sh FILE
+-Try to determine 
+-what kind of information is in a file by consulting
+-the file system index and by reading the file itself.
+-.sh DATE
+-Print today's date and time.
+-Has considerable knowledge
+-of calendric and horological peculiarities.
+-.op
+-May set
+-.UC UNIX 's
+-idea of date and time.
+-.sh DF
+-Report amount of free space on file system devices.
+-.sh DU
+-Print a summary of total space occupied by all files in a hierarchy.
+-.sh QUOT
+-Print summary of file space usage by user id.
+-.sh WHO
+-Tell who's on the system.
+-.op
+-List of presently logged in users,
+-ports and times on.
+-.op
+-Optional history of all logins and logouts.
+-.sh PS
+-Report on active processes.
+-.op
+-List your own or everybody's processes.
+-.op
+-Tell what commands are being executed.
+-.op
+-Optional status information:
+-state and scheduling info,
+-priority,
+-attached terminal,
+-what it's waiting for,
+-size.
+-.sh IOSTAT
+-Print statistics about system I/O activity.
+-.sh TTY
+-Print name of your terminal.
+-.sh PWD
+-Print name of your working directory.
+-.NH 2
+-Backup and Maintenance
+-.LP
+-.sh MOUNT
+-Attach a device containing
+-a file system to
+-the tree of directories.
+-Protects against nonsense arrangements.
+-.sh UMOUNT
+-Remove the file system contained on a device
+-from the tree of directories.
+-Protects against removing a busy device.
+-.sh MKFS
+-Make a new file system on a device.
+-.sh MKNOD
+-Make an i-node (file system entry) for a special file.
+-Special files are
+-physical devices,
+-virtual devices, physical memory, etc.
+-.sh TP
+-.sh TAR
+-Manage file archives on magnetic tape or DECtape.
+-TAR is newer.
+-.op
+-Collect files into an archive.
+-.op
+-Update DECtape archive by date.
+-.op
+-Replace or delete DECtape files.
+-.op
+-Print table of contents.
+-.op
+-Retrieve from archive.
+-.sh DUMP
+-Dump the file system
+-stored on a specified device, selectively by date, or indiscriminately.
+-.sh RESTOR
+-Restore a dumped file system,
+-or selectively retrieve parts thereof.
+-.sh SU
+-Temporarily become the super user with all the rights and privileges
+-thereof.
+-Requires a password.
+-.sh DCHECK
+-.sh ICHECK
+-.sh NCHECK
+-Check consistency of file system.
+-.op
+-Print gross statistics:
+-number of files,
+-number of directories,
+-number of special files,
+-space used,
+-space free.
+-.op
+-Report duplicate use of space.
+-.op
+-Retrieve lost space.
+-.op
+-Report inaccessible files.
+-.op
+-Check consistency of directories.
+-.op
+-List names of all files.
+-.sh CLRI
+-Peremptorily expunge a file and its space from a file system.
+-Used to repair damaged file systems.
+-.sh SYNC
+-Force all outstanding I/O on the system to completion.
+-Used to shut down gracefully.
+-.NH 2
+-Accounting
+-.LP
+-The timing information on which the reports are based can be
+-manually cleared or shut off completely.
+-.sh AC
+-Publish cumulative connect time report.
+-.op
+-Connect time by user or by day.
+-.op
+-For all users or for selected users.
+-.sh SA
+-Publish Shell accounting
+-report.
+-Gives usage information on each command executed.
+-.op
+-Number of times used.
+-.op
+-Total system time, user time and elapsed time.
+-.op
+-Optional averages and percentages.
+-.op
+-Sorting on various fields.
+-.NH 2
+-Communication
+-.LP
+-.sh MAIL
+-Mail a message to one or more users.
+-Also used to read and dispose of incoming mail.
+-The presence of mail is announced by LOGIN
+-and optionally by SH.
+-.op
+-Each message can be disposed of individually.
+-.op
+-Messages can be saved in files or forwarded.
+-.sh CALENDAR
+-Automatic reminder service for events of today and tomorrow.
+-.sh WRITE
+-Establish direct terminal communication with another user.
+-.sh WALL
+-Write to all users.
+-.sh MESG
+-Inhibit receipt of messages from WRITE and WALL.
+-.sh CU
+-Call up another time-sharing system.
+-.OP
+-Transparent interface to remote machine.
+-.OP
+-File transmission.
+-.OP
+-Take remote input from local file or put remote output
+-into local file.
+-.OP
+-Remote system need not be
+-.UC UNIX .
+-.sh UUCP
+-.UC UNIX
+-to
+-.UC UNIX
+-copy.
+-.OP
+-Automatic queuing until line becomes available
+-and remote machine is up.
+-.OP
+-Copy between two remote machines.
+-.op
+-Differences, mail, etc., between two machines.
+-.NH 2
+-Basic Program Development Tools
+-.LP
+-Some of these utilities are used as integral parts of
+-the higher level languages described in section 2.
+-.sh AR
+-Maintain archives and libraries.
+-Combines several files into one for housekeeping efficiency.
+-.op
+-Create new archive.
+-.op
+-Update archive by date.
+-.op
+-Replace or delete files.
+-.op
+-Print table of contents.
+-.op
+-Retrieve from archive.
+-.sh AS
+-Assembler.
+-Similar to PAL-11, but different in detail.
+-.op
+-Creates object program consisting of
+-.in+2
+-.nf
+-code, possibly read-only,
+-initialized data or read-write code,
+-uninitialized data.
+-.in -2
+-.fi
+-.op
+-Relocatable object code is directly executable without
+-further transformation.
+-.op
+-Object code normally includes a symbol table.
+-.op
+-Multiple source files.
+-.op
+-Local labels.
+-.op
+-Conditional assembly.
+-.op
+-``Conditional jump'' instructions become
+-branches or branches plus jumps depending on distance.
+-.sh Library
+-The basic run-time library.
+-These routines are used freely by all software.
+-.op
+-Buffered character-by-character I/O.
+-.op
+-Formatted input and output conversion (SCANF and PRINTF)
+-for standard input and output, files, in-memory conversion.
+-.op
+-Storage allocator.
+-.op
+-Time conversions.
+-.op
+-Number conversions.
+-.op
+-Password encryption.
+-.op
+-Quicksort.
+-.op
+-Random number generator.
+-.op
+-Mathematical function library, including
+-trigonometric functions and inverses,
+-exponential, logarithm, square root,
+-bessel functions.
+-.sh ADB
+-Interactive debugger.
+-.op
+-Postmortem dumping.
+-.OP
+-Examination of arbitrary files, with no limit on size.
+-.op
+-Interactive breakpoint debugging with the debugger as a separate
+-process.
+-.OP
+-Symbolic reference to local and global variables.
+-.op
+-Stack trace for C programs.
+-.OP
+-Output formats:
+-.in+2
+-.nf
+-1-, 2-, or 4-byte integers in octal, decimal, or hex
+-.br
+-single and double floating point
+-.br
+-character and string
+-.br
+-disassembled machine instructions
+-.br
+-.fi
+-.in-2
+-.op
+-Patching.
+-.OP
+-Searching for integer, character, or floating patterns.
+-.OP
+-Handles separated instruction and data space.
+-.sh OD
+-Dump any file.
+-Output options include any combination of
+-octal or decimal by words,
+-octal by bytes,
+-ASCII,
+-opcodes,
+-hexadecimal.
+-.op
+-Range of dumping is controllable.
+-.sh LD
+-Link edit.
+-Combine relocatable object files.
+-Insert required routines from specified libraries.
+-.op
+-Resulting code may be sharable.
+-.op
+-Resulting code may have separate instruction and data spaces.
+-.sh LORDER
+-Places object file names in proper order for loading,
+-so that files depending on others come after them.
+-.sh NM
+-Print the namelist (symbol table) of an object program.
+-Provides control over the style and order of
+-names that are printed.
+-.sh SIZE
+-Report the core requirements
+-of one or more object files.
+-.sh STRIP
+-Remove the relocation and symbol table information from
+-an object file to save space.
+-.sh TIME
+-Run a command and report timing information on it.
+-.sh PROF
+-Construct a profile of time spent per routine
+-from statistics gathered by time-sampling the
+-execution of a program.
+-Uses floating point.
+-.op
+-Subroutine call frequency and average times for C programs.
+-.sh MAKE
+-Controls creation of large programs.
+-Uses a control file specifying source file dependencies
+-to make new version;
+-uses time last changed to deduce minimum amount of work necessary.
+-.op
+-Knows about CC, YACC, LEX, etc.
+-.NH 2
+-UNIX Programmer's Manual
+-.LP
+-.sh Manual
+-Machine-readable version of the
+-.UC UNIX
+-Programmer's Manual.
+-.op
+-System overview.
+-.op
+-All commands.
+-.op
+-All system calls.
+-.op
+-All subroutines in C and assembler libraries.
+-.op
+-All devices and other special files.
+-.op
+-Formats of file system and kinds
+-of files known to system software.
+-.op
+-Boot and maintenance procedures.
+-.sh MAN
+-Print specified manual section on your terminal.
+-.NH 2
+-Computer-Aided Instruction
+-.LP
+-.sh LEARN
+-A program for interpreting CAI scripts, plus scripts
+-for learning about 
+-.UC UNIX
+-by using it.
+-.op
+-Scripts for basic files and commands,
+-editor,
+-advanced files and commands,
+-.UC EQN ,
+-.UC MS
+-macros,
+-C programming language.
+//GO.SYSIN DD hel1
+echo hel2
+sed 's/.//' >hel2 <<'//GO.SYSIN DD hel2'
+-.NH
+-Languages
+-.NH 2
+-The C Language
+-.LP
+-.sh CC
+-Compile and/or link edit programs in the C
+-language.
+-The 
+-.UC UNIX
+-operating system, most of the
+-subsystems and C itself are written in C.
+-For a full description of C, read
+-.ul
+-The C Programming Language,
+-Brian W. Kernighan and Dennis M. Ritchie,
+-Prentice-Hall, 1978.
+-.op
+-General purpose language
+-designed for structured programming.
+-.op
+-Data types include
+-character,
+-integer,
+-float,
+-double,
+-pointers to all types,
+-functions returning above types,
+-arrays of all types,
+-structures and unions of all types.
+-.op
+-Operations intended to give machine-independent control
+-of full machine facility, including to-memory
+-operations and
+-pointer arithmetic.
+-.op
+-Macro preprocessor for parameterized code and inclusion of
+-standard files.
+-.op
+-All procedures recursive, with parameters by value.
+-.op
+-Machine-independent pointer manipulation.
+-.op
+-Object code uses full
+-addressing capability of the PDP-11.
+-.op
+-Runtime library gives access to all system facilities.
+-.OP
+-Definable data types.
+-.OP
+-Block structure
+-.sh  LINT
+-Verifier for C programs.
+-Reports questionable or nonportable usage such as:
+-.nf
+-.in +2
+-Mismatched data declarations and procedure interfaces.
+-.br
+-Nonportable type conversions.
+-.br
+-Unused variables, unreachable code, no-effect operations.
+-.br
+-Mistyped pointers.
+-.br
+-Obsolete syntax.
+-.in -2
+-.OP
+-Full cross-module checking of separately compiled programs.
+-.sh CB
+-A beautifier for C programs.
+-Does proper indentation and placement of braces.
+-.NH 2
+-Fortran
+-.LP
+-.sh  F77
+-A full compiler for 
+-ANSI Standard Fortran 77.
+-.OP
+-Compatible with C and supporting tools at object level.
+-.OP
+-Optional source compatibility with Fortran 66.
+-.OP
+-Free format source.
+-.op
+-Optional subscript-range checking, detection of uninitialized variables.
+-.OP
+-All widths of arithmetic:
+-2- and 4-byte integer; 4- and 8-byte real; 8- and 16-byte
+-complex.
+-.sh RATFOR
+-Ratfor adds rational
+-control structure \o'a\(ga' la C to Fortran.
+-.op
+-Compound statements.
+-.op
+-If-else, do, for, while,
+-repeat-until, break, next
+-statements.
+-.op
+-Symbolic constants.
+-.op
+-File insertion.
+-.op
+-Free format source
+-.op
+-Translation of relationals like >, >=.
+-.op
+-Produces genuine Fortran to carry away.
+-.op
+-May be used with F77.
+-.sh STRUCT
+-Converts ordinary ugly Fortran into structured Fortran (i.e., Ratfor),
+-using statement grouping, if-else, while, for, repeat-until.
+-.NH 2
+-Other Algorithmic Languages
+-.LP
+-.sh BAS
+-An interactive interpreter, similar in style to BASIC.
+-Interpret unnumbered statements immediately,
+-numbered statements upon `run'.
+-.op
+-Statements include:
+-.in+2
+-.nf
+-comment,
+-dump,
+-for...next,
+-goto,
+-if...else...fi,
+-list,
+-print,
+-prompt,
+-return,
+-run,
+-save.
+-.fi
+-.in 0
+-.op
+-All calculations double precision.
+-.op
+-Recursive function defining and calling.
+-.op
+-Builtin functions include log, exp, sin, cos, atn, int,
+-sqr, abs, rnd.
+-.op
+-Escape to ED for complex program editing.
+-.sh DC
+-Interactive programmable desk calculator.
+-Has named storage locations as well
+-as conventional stack for holding integers or programs.
+-.op
+-Unlimited precision decimal arithmetic.
+-.op
+-Appropriate treatment of decimal fractions.
+-.op
+-Arbitrary input and output radices, in particular
+-binary, octal, decimal and hexadecimal.
+-.op
+-Reverse Polish operators:
+-.in+2
+-.nf
+-+ \- * /
+-remainder, power, square root,
+-load, store, duplicate, clear,
+-print, enter program text, execute.
+-.in-2
+-.fi
+-.sh BC
+-A C-like interactive interface to the desk calculator DC.
+-.op
+-All the capabilities of DC with a high-level syntax.
+-.op
+-Arrays and recursive functions.
+-.op
+-Immediate evaluation of expressions and evaluation of
+-functions upon call.
+-.op
+-Arbitrary precision elementary functions:
+-exp, sin, cos, atan.
+-.op
+-Go-to-less programming.
+-.NH 2
+-Macroprocessing
+-.LP
+-.nr c 0 1
+-.sh  M4
+-A general purpose macroprocessor.
+-.OP
+-Stream-oriented, recognizes macros anywhere in text.
+-.OP
+-Syntax fits with functional syntax of most higher-level
+-languages.
+-.OP
+-Can evaluate integer arithmetic expressions.
+-.NH 2
+-Compiler-compilers
+-.LP
+-.sh YACC
+-An LR(1)-based compiler writing system.
+-During execution of resulting
+-parsers, arbitrary C functions may be
+-called to do code generation or semantic actions.
+-.op
+-BNF syntax specifications.
+-.op
+-Precedence relations.
+-.op
+-Accepts formally ambiguous grammars
+-with non-BNF resolution rules.
+-.sh  LEX
+-Generator of lexical analyzers.
+-Arbitrary C functions may be called
+-upon isolation of each lexical token.
+-.OP
+-Full regular expression,
+-plus left and right context dependence.
+-.OP
+-Resulting lexical analysers interface cleanly
+-with YACC parsers.
+//GO.SYSIN DD hel2
+echo hel3
+sed 's/.//' >hel3 <<'//GO.SYSIN DD hel3'
+-.NH
+-Text Processing
+-.NH 2
+-Document Preparation
+-.LP
+-.sh ED
+-Interactive context editor.
+-Random access to all lines of a file.
+-.op
+-Find lines by number or pattern.
+-Patterns may include:
+-specified characters,
+-don't care characters,
+-choices among characters,
+-repetitions of these constructs,
+-beginning of line,
+-end of line.
+-.op
+-Add, delete, change, copy, move or join lines.
+-.op
+-Permute or split contents of a line.
+-.op
+-Replace one or all instances of a pattern within a line.
+-.op
+-Combine or split files.
+-.op
+-Escape to Shell (command language) during editing.
+-.ne3
+-.op
+-Do any of above operations on
+-every pattern-selected line in a given range.
+-.OP
+-Optional encryption for extra security.
+-.sh PTX
+-Make a permuted (key word in context) index.
+-.sh SPELL
+-Look for spelling errors by comparing each word in a
+-document against a word list.
+-.OP
+-25,000-word list includes proper names.
+-.OP
+-Handles common prefixes and suffixes.
+-.OP
+-Collects words to help tailor local spelling lists.
+-.sh LOOK
+-Search for words in dictionary that begin with specified prefix.
+-.sh TYPO
+-Look for spelling errors by a statistical technique;
+-not limited to English.
+-.sh CRYPT
+-Encrypt and decrypt files for security.
+-.NH 2
+-Document Formatting
+-.LP
+-.sh ROFF
+-A typesetting program for terminals.
+-Easy for nontechnical people to learn, and good
+-for simple documents.
+-Input consists of data lines intermixed with control lines,
+-such as
+-.ta  8n
+-.ti 10
+-.li
+-.sp 2 insert two lines of space
+-.ti10
+-.li
+-.ce   center the next line
+-.br
+-ROFF is deemed to be obsolete;
+-it is intended only for casual use.
+-.op
+-Justification of either or both margins.
+-.op
+-Automatic hyphenation.
+-.op
+-Generalized running heads and feet, with even-odd page
+-capability, numbering, etc.
+-.op
+-Definable macros for frequently used
+-control sequences (no substitutable arguments).
+-.op
+-All 4 margins and page size dynamically adjustable.
+-.op
+-Hanging indents and one-line indents.
+-.op
+-Absolute and relative parameter settings.
+-.op
+-Optional legal-style numbering of output lines.
+-.op
+-Multiple file capability.
+-.OP
+-Not usable as a filter.
+-.sh TROFF
+-.sh NROFF
+-Advanced typesetting.
+-TROFF drives a Graphic Systems phototypesetter;
+-NROFF drives ascii terminals of all types.
+-This summary was typeset using TROFF.
+-TROFF and NROFF style is similar to ROFF, but they are capable of much more elaborate
+-feats of formatting,
+-when appropriately programmed.
+-TROFF and NROFF accept the same input language.
+-.op
+-All ROFF capabilities available or definable.
+-.op
+-Completely definable page format keyed to dynamically planted
+-``interrupts'' at specified lines.
+-.op
+-Maintains several separately definable typesetting environments (e.g., one for
+-body text, one for footnotes, and one for unusually elaborate
+-headings).
+-.op
+-Arbitrary number of output pools can be combined at will.
+-.op
+-Macros with substitutable arguments, and macros invocable
+-in mid-line.
+-.op
+-Computation and printing of numerical quantities.
+-.op
+-Conditional execution of macros.
+-.op
+-Tabular layout facility.
+-.op
+-Positions expressible in inches, centimeters, ems, points,
+-machine units
+-or arithmetic combinations thereof.
+-.op
+-Access to character-width computation for unusually difficult
+-layout problems.
+-.op
+-Overstrikes, built-up brackets, horizontal and vertical line drawing.
+-.op
+-Dynamic relative or absolute positioning and size selection,
+-globally or at the character level.
+-.op
+-Can exploit the characteristics of the terminal being used,
+-for approximating special characters, reverse motions,
+-proportional spacing, etc.
+-.LP
+-The Graphic Systems typesetter has a
+-vocabulary of several 102-character fonts (4 simultaneously)
+-in 15 sizes.
+-TROFF provides
+-terminal output for rough sampling of the product.
+-.LP
+-NROFF will produce multicolumn output on terminals capable of reverse line feed,
+-or through the postprocessor COL.
+-.LP
+-High programming skill is required to exploit the formatting
+-capabilities of TROFF and NROFF, although unskilled personnel can easily be trained
+-to enter documents according to canned formats
+-such as those provided by MS, below.
+-TROFF and EQN are essentially identical to NROFF and NEQN
+-so it is usually possible to define interchangeable 
+-formats to produce
+-approximate proof copy on terminals
+-before actual typesetting.
+-The preprocessors MS, TBL, and REFER are fully compatible
+-with TROFF and NROFF.
+-.sh MS
+-A standardized manuscript layout package
+-for use with NROFF/TROFF.
+-This document was formatted with MS.
+-.op
+-Page numbers and draft dates.
+-.op
+-Automatically numbered subheads.
+-.op
+-Footnotes.
+-.op
+-Single or double column.
+-.op
+-Paragraphing, display and indentation.
+-.op
+-Numbered equations.
+-.sh EQN
+-A mathematical typesetting preprocessor for TROFF.
+-Translates easily readable formulas, either in-line or displayed, into 
+-detailed typesetting instructions.
+-Formulas are written in a style like this:
+-.DS
+-sigma sup 2 ~=~ 1 over N sum from i=1 to N ( x sub i \- x bar ) sup 2
+-.DE
+-which produces:
+-.EQ
+-sigma sup 2 ~=~ 1 over N sum from i=1 to N ( x sub i - x bar ) sup 2
+-.EN
+-.op
+-Automatic calculation of size changes for subscripts, sub-subscripts,
+-etc.
+-.op
+-Full vocabulary of Greek letters and special symbols, such as `gamma', `GAMMA', `integral'.
+-.op
+-Automatic calculation of large bracket sizes.
+-.op
+-Vertical ``piling'' of formulae for matrices, conditional
+-alternatives, etc.
+-.op
+-Integrals, sums, etc., with arbitrarily complex limits.
+-.op
+-Diacriticals: dots, double dots, hats, bars, etc.
+-.op
+-Easily learned by nonprogrammers and mathematical typists.
+-.sh NEQN
+-A version of EQN for NROFF;
+-accepts the same input language.
+-Prepares formulas for display on
+-any terminal that NROFF knows about,
+-for example, those based on Diablo printing mechanism.
+-.op
+-Same facilities as EQN within graphical capability of
+-terminal.
+-.sh TBL
+-A preprocessor for NROFF/TROFF
+-that translates simple descriptions of table layouts
+-and contents into detailed typesetting instructions.
+-.op
+-Computes column widths.
+-.op
+-Handles left- and right-justified columns,
+-centered columns and decimal-point
+-alignment.
+-.op
+-Places column titles.
+-.op
+-Table entries can be text,
+-which is adjusted to fit.
+-.op
+-Can box all or parts of table.
+-.sh REFER
+-Fills in bibliographic citations in a document
+-from a data base (not supplied).
+-.op
+-References may be printed in any style,
+-as they occur or collected at the end.
+-.op
+-May be numbered sequentially, by name of author, etc.
+-.sh TC
+-Simulate Graphic Systems typesetter on Tektronix 4014 scope.
+-Useful for checking TROFF page layout before typesetting.
+-.sh GREEK
+-Fancy printing on Diablo-mechanism terminals
+-like DASI-300 and DASI-450,
+-and on Tektronix 4014.
+-.op
+-Gives half-line forward and reverse motions.
+-.op
+-Approximates Greek letters and other special characters
+-by overstriking.
+-.sh COL
+-Canonicalize files with reverse line feeds
+-for one-pass printing.
+-.sh DEROFF
+-Remove all TROFF commands from input.
+-.sh CHECKEQ
+-Check document for possible errors in EQN usage.
+//GO.SYSIN DD hel3
+echo hel4
+sed 's/.//' >hel4 <<'//GO.SYSIN DD hel4'
+-.NH
+-Information Handling
+-.LP
+-.sh SORT
+-Sort or merge ASCII files line-by-line.
+-No limit on input size.
+-.op
+-Sort up or down.
+-.op
+-Sort lexicographically or on numeric key.
+-.op
+-Multiple keys located by delimiters or by character position.
+-.op
+-May sort upper case together with lower into dictionary order.
+-.OP
+-Optionally suppress duplicate data.
+-.sh TSORT
+-Topological sort \(em converts a partial order into a total order.
+-.sh UNIQ
+-Collapse successive duplicate lines
+-in a file into one line.
+-.op
+-Publish lines that were originally unique,
+-duplicated, or both.
+-.op
+-May give redundancy count for each line.
+-.sh TR
+-Do one-to-one character translation according to
+-an arbitrary code.
+-.op
+-May coalesce selected repeated characters.
+-.op
+-May delete selected characters.
+-.sh DIFF
+-Report line changes, additions and deletions necessary to bring two files
+-into agreement.
+-.op
+-May produce an editor script to convert one file into another.
+-.op
+-A variant compares two new versions against one old one.
+-.sh COMM
+-Identify common lines in two sorted files.
+-Output in up to 3 columns shows lines present in first file only,
+-present in both, and/or present in second only.
+-.sh JOIN
+-Combine two files by joining records that have identical keys.
+-.sh GREP
+-Print all lines in a file that satisfy
+-a pattern as used in the editor ED.
+-.op
+-May print all lines that fail to match.
+-.op
+-May print count of hits.
+-.op
+-May print first hit in each file.
+-.sh LOOK
+-Binary search in sorted file for lines
+-with specified prefix.
+-.sh WC
+-Count the lines, ``words'' (blank-separated strings) and characters in a file.
+-.sh SED
+-Stream-oriented version of ED.
+-Can perform a sequence of editing operations on
+-each line of an
+-input stream of unbounded length.
+-.op
+-Lines may be selected by address or range of addresses.
+-.op
+-Control flow and conditional testing.
+-.op
+-Multiple output streams.
+-.op
+-Multi-line capability.
+-.sh AWK
+-Pattern scanning and processing language.
+-Searches input for patterns, and
+-performs actions on each line of input that satisfies
+-the pattern.
+-.op
+-Patterns include regular expressions,
+-arithmetic and lexicographic conditions,
+-boolean combinations and ranges of these.
+-.op
+-Data treated as string or numeric as appropriate.
+-.op
+-Can break input into fields;
+-fields are variables.
+-.op
+-Variables and arrays (with non-numeric subscripts).
+-.op
+-Full set of arithmetic operators and control flow.
+-.op
+-Multiple output streams to files and pipes.
+-.op
+-Output can be formatted as desired.
+-.op
+-Multi-line capabilities.
+//GO.SYSIN DD hel4
+echo hel5
+sed 's/.//' >hel5 <<'//GO.SYSIN DD hel5'
+-.NH
+-Graphics
+-.LP
+-The programs in this section are predominantly intended for use
+-with Tektronix 4014 storage scopes.
+-.sh GRAPH
+-Prepares a graph of a set of input numbers.
+-.op
+-Input scaled to fit standard plotting area.
+-.op
+-Abscissae may be supplied automatically.
+-.op
+-Graph may be labeled.
+-.op
+-Control over grid style, line style, graph orientation, etc.
+-.sh SPLINE
+-Provides a smooth curve through a set of points
+-intended for GRAPH.
+-.sh PLOT
+-A set of filters for printing graphs produced by GRAPH
+-and other programs
+-on various terminals.
+-Filters provided for
+-4014, DASI terminals, Versatec printer/plotter.
+//GO.SYSIN DD hel5
+echo hel6
+sed 's/.//' >hel6 <<'//GO.SYSIN DD hel6'
+-.NH
+-Novelties, Games, and Things That Didn't Fit Anywhere Else
+-.LP
+-.sh BACKGAMMON
+-.br
+-A player of modest accomplishment.
+-.sh CHESS
+-Plays good class D chess.
+-.sh CHECKERS
+-Ditto, for checkers.
+-.sh BCD
+-Converts ascii to card-image form.
+-.sh PPT
+-Converts ascii to paper tape form.
+-.sh BJ
+-A blackjack dealer.
+-.sh CUBIC
+-An accomplished player of 4\(mu4\(mu4 tic-tac-toe.
+-.sh MAZE
+-Constructs random mazes for you to solve.
+-.sh MOO
+-A fascinating number-guessing game.
+-.sh CAL
+-Print a calendar of specified month and year.
+-.sh BANNER
+-Print output in huge letters.
+-.sh CHING
+-The
+-.ul
+-I Ching.
+-Place your own interpretation on the output.
+-.sh FORTUNE
+-Presents a random fortune cookie on each invocation.
+-Limited jar of cookies included.
+-.sh UNITS
+-Convert amounts between different scales of measurement.
+-Knows hundreds of units.
+-For example, how many km/sec is a parsec/megayear?
+-.sh TTT
+-A tic-tac-toe program that learns.
+-It never makes the same mistake twice.
+-.sh ARITHMETIC
+-.br
+-Speed and accuracy test for number facts.
+-.sh FACTOR
+-Factor large integers.
+-.sh QUIZ
+-Test your knowledge of Shakespeare, Presidents, capitals, etc.
+-.sh WUMP
+-Hunt the wumpus, thrilling search in a dangerous cave.
+-.sh REVERSI
+-A two person board game,
+-isomorphic to
+-Othello\(rg.
+-.sh HANGMAN
+-Word-guessing game.
+-Uses the dictionary supplied with SPELL.
+-.sh FISH
+-Children's card-guessing game.
+//GO.SYSIN DD hel6
diff --git a/doc/7thEdMan/vol2/tbl b/doc/7thEdMan/vol2/tbl
new file mode 100644 (file)
index 0000000..3dce488
--- /dev/null
@@ -0,0 +1,1902 @@
+.if \nM=0 .RP
+.TM 76-1274-5 39199 39199-11
+.if \n(tm>0 .ND June 11, 1976*
+.TL
+Tbl \(em A Program to Format Tables
+.AU "MH 2C-569" 6377
+M. E. Lesk
+.AI
+.MH
+.if \n(tm>0 .FS
+.if \n(tm>0 * This printing revised through August 5, 1977
+.if \n(tm>0 .FE
+.AB
+.I
+Tbl
+.R
+is a document formatting preprocessor for
+.I
+troff
+.R
+or
+.I
+nroff
+.R
+which makes
+even
+fairly complex tables easy to specify and enter.
+It is available on
+the
+.SM
+PDP-11 UNIX*
+.NL
+system
+.FS
+* UNIX is a Trademark/Service Mark of the Bell System
+.FE
+and on Honeywell 6000
+.SM
+GCOS.
+.NL
+Tables are made up of columns which may be independently centered, right-adjusted,
+left-adjusted, or aligned by decimal points.
+Headings may be placed over single columns or groups of columns.
+A table entry may contain equations, or may consist of several rows of text.
+Horizontal or vertical lines may be drawn as desired
+in the table,
+and any table or element may be enclosed in a box.
+For example:
+.in 0
+.ll
+.sp .5
+.TS
+center, box;
+c  s  s  s
+c  s  s  s
+c |c |c |c
+c |c |c |c
+l |n |n |n.
+1970 Federal Budget Transfers
+\s-2(in billions of dollars)\s0
+=
+State  Taxes   Money   Net
+\^     collected       spent   \^
+_
+New York       22.91   21.35   \-1.56
+New Jersey     8.33    6.96    \-1.37
+Connecticut    4.12    3.10    \-1.02
+Maine  0.74    0.67    \-0.07
+California     22.29   22.42   +0.13
+New Mexico     0.70    1.49    +0.79
+Georgia        3.30    4.28    +0.98
+Mississippi    1.15    2.32    +1.17
+Texas  9.33    11.13   +1.80
+.TE
+.AE
+.OK
+Phototypesetting
+Documentation
+.CS  16 0 16 0 12 6
+.tr # 
+.de e1
+.nr \\$1 \\$2
+..
+.de e2
+.if !\\n(\\$1=\\n% .tm Error in example \\$1: referred to page \\n(\\$1, is on page \\n%
+.rr \\$1
+..
+.di qq
+.EQ
+delim $$
+.EN
+.di
+.rm qq
+.SH
+Introduction.
+.PP
+.I
+Tbl
+.R
+turns a simple description
+of a table into a
+.I
+troff
+.R
+or
+.I
+nroff
+.R
+[1]
+program (list of commands) that prints the table.
+.I
+Tbl
+.R
+may be used on the
+\s-2PDP-\s011 \s-2UNIX\s0
+.NL
+[2] system and on the Honeywell 6000
+.SM
+GCOS
+.NL
+system.
+It
+attempts to isolate a portion of a job that it can
+successfully
+handle and leave the remainder for other programs.
+Thus
+.I
+tbl
+.R
+may be used with the equation formatting
+program
+.I
+eqn
+.R
+[3]
+or various
+layout macro packages
+[4,5,6],
+but does not duplicate their functions.
+.PP
+This memorandum is divided into two parts.
+First we give the rules for preparing
+.I
+tbl
+.R
+input; then some examples are shown.
+The description of rules is precise but technical, and
+the beginning user may prefer to read the examples first,
+as they show some common table arrangements.
+A section explaining how to invoke
+.I
+tbl
+.R
+precedes the examples.
+To avoid repetition, henceforth read
+.I
+troff
+.R
+as
+.I
+``troff
+.R
+or
+.I
+nroff.''
+.R
+.ds . \^\s14.\s0
+.PP
+The input to
+.I
+tbl
+.R
+is text for a document, with tables preceded by a ``\*.TS''
+(table start)
+command and followed by a ``\*.TE''
+(table end) command.
+.I
+Tbl
+.R
+processes the tables, generating
+.I
+troff
+.R
+formatting commands,
+and leaves the remainder of the text unchanged.
+The ``\*.TS'' and ``\*.TE''
+lines are copied, too, so that
+.I
+troff
+.R
+page layout macros
+(such as the memo formatting macros [4]\|) can use these lines
+to delimit and place tables as they see fit.
+In particular, any arguments on the ``\*.TS'' or ``\*.TE''
+lines
+are copied but otherwise ignored, and may be used by document layout
+macro commands.
+.PP
+The format of the input is as follows:
+.DS
+\&text
+\&\*.TS
+\&\fItable\fR
+\&\*.TE
+\&text
+\&\*.TS
+\&\fItable\fR
+\&\*.TE
+\&text
+\&\&\*. \*. \*.
+.DE
+where the format of each table is as follows:
+.DS
+\&\*.TS
+\fIoptions \fB;\fR
+\fIformat \*.
+data
+\&\fR\*.TE
+.DE
+Each table is independent, and must contain formatting
+information
+followed by the data to be entered in the table.
+The formatting information, which describes the
+individual columns and rows of the table, may be preceded
+by a few options that affect the entire table.
+A detailed description of tables is given in the next section.
+.sp .5
+.SH
+Input commands.
+.PP
+As indicated above, a table contains, first, global options,
+then a format section describing the layout of the table
+entries, and then the data to be printed.  The format and data
+are always required, but not the options.
+The various parts of the table are entered as follows:
+.sp .5v
+.IP 1)
+O\s-2PTIONS.\s0
+There may be a single line of options
+affecting the whole table.
+If present, this line must follow the \*.TS line immediately
+and must contain a list of option names
+separated by spaces, tabs, or commas, and must be terminated by a semicolon.
+The allowable options are:
+.RS
+.IP \fB##center\fR 13
+\(em center the table (default is left-adjust);
+.IP \fB##expand\fR
+\(em make the table as wide as the current line length;
+.IP \fB##box\fR
+\(em enclose the table in a box;
+.IP \fB##allbox\fR
+\(em enclose each item in the table in a box;
+.IP \fB##doublebox\fR
+\(em enclose the table in two boxes;
+.IP \fB##tab#\fR(\fIx\fR\^)
+\(em use \fIx\fR instead of tab to separate data items.
+.IP \fB##linesize#(\fIn\fR\^)
+\(em set lines or rules (e.g. from \fBbox\fR\^) in \fIn\fR point type;
+.IP \fB##delim#(\fIxy\fR\^)
+\(em recognize \fIx\fR and \fIy\fR as the \fIeqn\fR delimiters.
+.RE
+.LP
+.ns
+.IP
+The
+.I
+tbl
+.R
+program
+tries to keep boxed tables on one page by issuing
+appropriate ``need'' (\fI\*.ne\fR\|) commands.
+These requests are calculated from the number of lines in the tables,
+and if there are spacing commands embedded in the input, these requests may be inaccurate;
+use normal
+.I
+troff
+.R
+procedures, such as keep-release macros, in that case.
+The user who must have a multi-page boxed table
+should use macros designed for this purpose,
+as explained below under `Usage.'
+.sp .5v
+.IP 2) 5
+F\s-2ORMAT\s0.
+The format section of the table specifies the layout
+of the columns.
+Each line in this section corresponds to one line
+of the table (except that the last line corresponds to all following
+lines up to the next \*.T&, if any \(em see below),
+and each line contains a key-letter for each column
+of the table.
+It is good practice to separate the key letters for each
+column by spaces or tabs.
+Each key-letter is one of the following:
+.RS
+.cs B 25
+.IP "##\fBL\fR#or#\fBl\fR" 10
+to indicate a left-adjusted column entry;
+.IP "##\fBR\fR#or#\fBr\fR
+to indicate a right-adjusted column entry;
+.IP "##\fBC\fR#or#\fBc\fR
+to indicate a centered column entry;
+.IP "##\fBN\fR#or#\fBn\fR
+to indicate a numerical column entry, to be aligned with other
+numerical entries so that the units digits of numbers line up;
+.IP "##\fBA\fR#or#\fBa\fR
+to indicate an alphabetic subcolumn;
+all corresponding entries are aligned on the left, and positioned
+so that the widest is centered within the column (see
+example on page 12);
+.IP "##\fBS\fR#or#\fBs\fR
+to indicate a spanned heading, i.e. to indicate that the
+entry from the previous column continues across this
+column
+(not allowed for the first column, obviously); or
+.IP ##\fB\s+4\v'6p'^\v'-6p'\s0\fR
+to indicate a vertically spanned heading, i.e. to indicate that
+the entry from the previous row continues down through this row.
+(Not allowed for the first row of the table, obviously).
+.cs B
+.RE
+.LP
+.ns
+.IP
+When numerical alignment is specified, a location for the decimal
+point is sought.  The rightmost dot (\*.)
+adjacent to a digit is used as a decimal point; if there is no
+dot adjoining a digit, the rightmost digit is used as a units digit;
+if no alignment is indicated, the item is centered in the column.
+However, the special non-printing character string \e& may be used
+to override unconditionally dots
+and digits, or to align alphabetic data;
+this string lines up where a dot normally would,
+and then disappears from the final output.
+In the example below, the items shown at the left will be
+aligned (in a numerical column) as shown on the right:
+.KS
+.TS
+center;
+l6 n.
+13     13
+4\*.2  4\&\*.2
+26\*.4\*.12    26\*.4\&\*.12
+abc    abc
+abc\e& abc\&
+43\e&3\*.22    43\&3\*.22
+749\*.12       749\&\*.12
+.TE
+.KE
+.IP
+\fBNote:\fR
+If numerical data are used in the same column with wider
+.B L
+or
+.B r
+type table entries, the widest \fInumber\fR is centered relative
+to the wider
+.B L
+or
+.B r
+items (\fBL\fR is used instead of \fBl\fR for readability;
+they have the same meaning as key-letters).
+Alignment within the numerical items is preserved.
+This is similar to the behavior of
+.B a
+type data, as explained above.
+However,
+alphabetic subcolumns (requested by the
+.B
+a
+.R
+key-letter)
+are always slightly indented relative to
+.B
+L
+.R
+items;
+if necessary, the column width is increased to force this.
+This is not true for \fBn\fR type entries.
+.IP
+.bd I 3
+.ft I
+Warning:
+.ft 1
+.bd I
+the \fBn\fR and \fBa\fR items should not be used in
+the same column.
+.IP
+For readability, the key-letters describing each column should
+be separated by spaces.
+The end of the format section is indicated by a period.
+The layout of the key-letters in the format section resembles
+the layout of the actual data in the table.
+Thus a simple format might appear as:
+.br
+.ne 3
+.in +2
+.nf
+c  s  s
+l  n  n \*.
+.fi
+.in -2
+which specifies a table of three columns. The first line
+of the table contains a heading centered across all three
+columns; each remaining line contains a left-adjusted item
+in the first column followed by two columns of numerical
+data.
+A sample table in this format might be:
+.br
+.ne 6v
+.br
+.in +4
+.TS
+c s s
+l n n.
+Overall title
+Item-a 34.22   9.1
+Item-b 12.65   .02
+Items: c,d,e   23      5.8
+Total  69.87   14.92
+.TE
+.in -4
+There are some additional features of the key-letter system:
+.RS
+.IP "\fI##Horizontal lines#\fR"
+\(em A key-letter may be replaced by `\(ul'
+(underscore) to indicate
+a horizontal line in place of the corresponding column entry,
+or by `=' to indicate a double horizontal line.
+If an adjacent column contains a horizontal line, or if
+there are vertical lines adjoining this column,
+this horizontal line is extended to meet the nearby lines.
+If any data entry is provided for this column, it is ignored and
+a warning message is printed.
+.QQ do the D(x) and M(x) to draw a line of 'x' characters.
+.QQ D will draw divided lines, M merged lines. thus - is simplh M(\(ru)
+.IP "\fI##Vertical lines#\fR"
+\(em A vertical bar may be placed between column key-letters.  This will
+cause a vertical line between the corresponding columns of the table.
+A vertical bar to the left of the first key-letter
+or to the right of the last one produces a line at the
+edge of the table.
+If two vertical bars appear between key-letters, a double vertical
+line is drawn.
+.IP "\fI##Space between columns#\fR"
+\(em A number may follow the key-letter.  This indicates the amount of separation
+between this column and the next column.
+The number normally specifies the separation in
+.I
+ens
+.R
+(one
+en
+.ne 3
+is about the width of the letter `n').* 
+.FS
+* More precisely, an en is a number of points (1 point = 1/72 inch)
+equal to half the current type size.
+.FE
+If the ``expand'' option is used, then these numbers are multiplied
+by a constant such that the table is as wide as the current line length.
+The default column separation number is 3.
+If the separation is changed the worst case (largest space requested) governs.
+.IP "\fI##Vertical spanning#\fR"
+\(em Normally, vertically spanned items extending over several
+rows of the table are centered in their vertical range.
+If a key-letter is followed by
+.B
+t
+.R
+or
+.B T ,
+any corresponding vertically spanned item
+will begin at the top line of its range.
+.IP "\fI##Font changes#\fR"
+\(em A key-letter may be followed by a string containing a font
+name or number
+preceded by the letter
+.B f
+or
+.B F .
+This indicates that the corresponding column should be in a different
+font from the default font (usually Roman).
+All font names are one or two letters; a one-letter font
+name should be separated from whatever follows by a space or tab.
+The single letters
+\f3B\f1, \f3b\f1, \f3I\f1,
+and
+\f3i\f1
+are shorter synonyms for
+.B f\^B
+and
+.B f\^I .
+Font change commands given with the table entries
+override these specifications.
+.IP "\fI##Point size changes#\fR"
+\(em A key-letter may be followed by the letter
+.B p
+or
+.B P
+and a number to indicate the point size of the corresponding table entries.
+The number may be a signed digit, in which case it is taken as
+an increment or decrement
+from the current point size.
+If both a point size and a column separation value are given,
+one or more blanks must separate them.
+.IP "\fI##Vertical spacing changes#\fR"
+\(em A key-letter may be followed by the letter
+.B v
+or
+.B V
+and a number to indicate the vertical line spacing to be used
+within a multi-line corresponding table entry.
+The number may be a signed digit, in which case it is taken as an increment
+or decrement from the current vertical spacing.
+A column separation value must be separated by blanks or some other
+specification from a vertical spacing request.
+This request has no effect unless the corresponding table entry
+is a text block (see below).
+.IP "\fI##Column width indication#\fR"
+\(em A key-letter may be followed by the letter
+.B w
+or
+.B W
+and a width value in parentheses.
+This width is used as a minimum column width.
+If the largest element in the column is not as wide as the width value
+given after the \fBw\fR, the largest element is assumed to be that wide.
+If the largest element in the column is wider than the specified value,
+its width is used.
+The width is also used as a default line
+length for included text blocks.
+Normal
+.I
+troff
+.R
+units can be used to scale the width value; if none are used,
+the default is
+ens.
+If the width specification is a unitless integer
+the parentheses may be omitted.
+If the width value is changed in a column, the \fIlast\fR one given controls.
+.IP "\fI##Equal width columns#\fR"
+\(em A key-letter may be followed by the letter
+.B e
+or
+.B E
+to indicate equal width columns.
+All columns whose
+key-letters are followed by \fBe\fR or \fBE\fR are made the same width.
+This permits the user to get a group of regularly spaced
+columns.
+.IP "##\fBNote:\fR#"
+The order of the above features is immaterial; they need not be separated
+by spaces, except as indicated above to avoid ambiguities involving
+point size and font changes.  Thus
+a numerical column entry in italic font and 12 point type with a minimum
+width of 2.5 inches and separated by 6 ens from the next column could
+be specified as
+.in +5
+np12w(2\*.5i)f\|I  6
+.in -5
+.IP "\fI##Alternative notation#\fR"
+\(em Instead of listing the format of successive lines of a table
+on consecutive lines of the format section,
+successive line formats may be given on the same line, separated
+by commas, so that the format for the example
+above might have been written:
+.in +5
+c s s, l n n \*.
+.in -5
+.IP "\fI##Default#\fR"
+\(em Column descriptors missing from the end
+of a format line are assumed to be \fBL\fR.
+The longest line in the format section, however,
+defines the number of columns
+in the table;
+extra columns in the data are ignored silently.
+.QQ put in the diagnostics.
+.RE
+.sp .5v
+.IP 3)
+D\s-2ATA\s0.
+The data for the table are typed after the format.
+Normally, each table line is typed as one line of data.
+Very long input lines can be broken: any line whose last character is
+\e is combined with the following line (and the \e vanishes).
+The data for different columns (the table entries) are separated by tabs,
+or by whatever character has been specified in the option
+.I tabs
+option.
+There are a few special cases:
+.RS
+.IP "\fI##Troff commands within tables\fR#"
+\(em An input line
+beginning with a `\*.' followed by anything
+but a number is assumed to be a command to
+.I
+troff
+.R
+and is passed through unchanged, retaining its position in the table.
+So, for example, space within a table may be produced by ``\*.sp''
+commands
+in the data.
+.IP "\fI##Full width horizontal lines\fR#"
+\(em An input
+.I line
+containing only the character $fat "\(ul" $ (underscore)
+or \fB=\fR (equal sign) is taken to be a single or double
+line, respectively, extending the
+full width
+of the
+.I table.
+.IP "\fI##Single column horizontal lines\fR#"
+\(em An input table
+.I entry
+containing only the character $fat "\(ul" $ or \fB=\fR
+is taken to be a single or double line extending
+the full width of the
+.I column.
+Such lines are extended to meet horizontal or vertical
+lines adjoining this column.
+To obtain these characters explicitly in a column, either
+precede them by \e& or
+follow them by a space before the usual tab or newline.
+.IP "\fI##Short horizontal lines\fR#"
+\(em An input table
+.I entry
+containing only the string $fat "\e\(ul"$
+is taken to be a single line as wide as the contents of
+the column.  It is not extended to meet
+adjoining lines.
+.IP "\fI##Repeated characters\fR#"
+\(em An input table
+.I entry
+containing only a string of the form $fat "\e"$\f3R\f2x\f1
+where
+.I x
+is any character is replaced by repetitions of the character
+.I x
+as wide as the data in the column.
+The sequence of
+.I x 's
+is not extended to meet adjoining columns.
+.IP "\fI##Vertically spanned items\fR#"
+\(em An input table entry containing only the
+character string
+.ft B
+\e\s+2\v'2p'^\v'-2p'\s0
+.ft R
+indicates that the table entry immediately
+above spans downward over this row.  It is equivalent
+to a table format key-letter of `^'.
+.IP "\fI##Text blocks\fR#"
+\(em In order to include a block of text as a table entry,
+precede it by $fat roman "T{" $ and follow
+it by $fat roman "T}" $.
+Thus the sequence
+.in +2
+.nf
+  \*. \*. \*. $fat roman "T{"$
+.I
+  block of
+  text
+.R
+  $fat roman "T}"$ \*. \*. \*.
+.in -2
+.fi
+is the way to enter, as a single entry in the table, something
+that cannot conveniently be typed as a simple string between
+tabs.
+Note that the $fat roman "T}" $ end delimiter must begin a line;
+additional columns of data may follow after a tab on the same line.
+See the example on page 10 for an illustration of included text blocks
+.e1 aa 10
+in a table.
+If more than twenty or thirty text blocks are used in a table,
+various limits in the
+.I
+troff
+.R
+program are likely to be exceeded,
+producing diagnostics such as `too many string/macro names' or `too many
+number registers.'
+.IP
+Text blocks are pulled out from the table, processed separately by
+.I
+troff,
+.R
+and replaced in the table as a solid block.  If no line length
+is specified in the
+.I
+block of text
+.R
+itself, or in the table format,
+the default is to use
+$ L times C / (N+1) $
+where
+.I
+L
+.R
+is the current line length,
+.I
+C
+.R
+is the number of table columns spanned by the text,
+and
+.I
+N
+.R
+is the total number of columns in the table.
+The other parameters (point size, font, etc.) used in setting the
+.I
+block of text
+.R
+are those in effect at the beginning of the table (including
+the effect of the ``\*.TS'' macro)
+and any table format specifications of size, spacing and font,
+using the \fBp\fR, \fBv\fR and \fBf\fR modifiers to the column key-letters.
+Commands within the text block itself are also recognized, of course.
+However,
+.I troff
+commands within the table data but not within the text block
+do not affect that block.
+.br
+.di RR
+.     this is going down a rathole
+.EQ
+delim off
+.EN
+.di
+.rm RR
+.IP "##\fBWarnings:\fR#"
+\(em Although any number of lines may be present in a table,
+only the first 200 lines are used in calculating
+the widths of the various columns.  A multi-page table,
+of course, may be arranged as several single-page tables
+if this proves to be a problem.
+Other difficulties with formatting may arise because,
+in the calculation of column widths all table entries
+are assumed to be in the font and size being used when
+the ``\*.TS'' command was encountered, except for font and size changes
+indicated (a) in the table format section and (b)
+within the table data (as in the entry
+\es+3\efIdata\efP\es0\|).
+Therefore, although arbitrary
+.I
+troff
+.R
+requests may be sprinkled in a table, care must be taken
+to avoid confusing the width calculations;
+use requests such as `\*.ps' with care.
+.tr ##
+.sp .5v
+.RE
+.IP 4)
+A\s-2DDITIONAL COMMAND LINES\s0.
+If the format of a table must be changed after
+many similar lines, as with sub-headings or summarizations, the ``\*.T&''
+(table continue)
+command can be used
+to change column parameters.
+The outline of such a table input is:
+.DS
+.ft R
+\&\*.TS
+.ft I
+\&options \fB;\fP
+\&format \*.
+\&data
+\&\*. \*. \*.
+.ft R
+\&\*.T&
+.ft I
+\&format \*.
+\&data
+.ft R
+\&\*.T&
+.ft I
+\&format \*.
+\&data
+.ft R
+\&\*.TE
+.DE
+as in the examples on pages 10 and 12.
+.e1 ab 10
+.e1 ac 12
+Using this procedure, each table line can be close to its corresponding format line.
+.bd I 3
+.br
+.sp 3p
+.ft I
+Warning:
+.ft R
+.bd I
+it is not possible to change the number of columns, the space
+between columns, the global options such as \fIbox,\fR
+or the selection of columns to be made equal width.
+.SH
+Usage.
+.PP
+On
+\s-2UNIX\s0,
+.I
+tbl
+.R
+can be run on a simple table with the command
+.DS
+tbl input-file | troff
+.DE
+but
+for more complicated use, where there are several input files,
+and they contain equations and \fIms\fR memorandum layout commands as well
+as tables, the normal command would be
+.DS
+tbl file-1 file-2 \*. \*. \*. | eqn | troff \-ms
+.DE
+and, of course, the usual options may be used on the
+.I
+troff
+.R
+and
+.I
+eqn
+.R
+commands.  The usage for
+.I
+nroff
+.R
+is similar
+to that for
+.I
+troff,
+.R
+but only
+\s-2TELETYPE\s+2\(rg Model 37 and
+Diablo-mechanism (\s-2DASI\s0 or \s-2GSI\s0)
+terminals can print boxed tables directly.
+.PP
+For the convenience of users employing line printers without
+adequate driving tables or post-filters, there is a special
+.I \-TX
+command line option to
+.I tbl
+which produces output that does not have fractional line
+motions in it.
+The only other command line options recognized by
+.I tbl
+are
+.I \-ms
+and
+.I \-mm
+which are turned into
+commands to fetch the corresponding macro files;
+usually it is more convenient to place these arguments
+on the
+.I troff
+part of the command line,
+but they are accepted by
+.I tbl
+as well.
+.PP
+Note that when
+.I
+eqn
+.R
+and
+.I
+tbl
+.R
+are used together on the same file
+.I
+tbl
+.R
+should be used first.
+If there are no equations within tables,
+either order works, but it is usually faster
+to run
+.I
+tbl
+.R
+first, since
+.I
+eqn
+.R
+normally produces a larger expansion of the input
+than
+.I
+tbl.
+.R
+However, if there are equations within tables
+(using the
+.I
+delim
+.R
+mechanism in
+.I
+eqn\fR),
+.I
+tbl
+.R
+must be first or the output will be scrambled.
+Users must also beware of using equations in
+\fBn\fR-style columns; this is nearly always wrong,
+since
+.I
+tbl
+.R
+attempts to split numerical format items into two parts and this
+is not possible with equations.
+The user can defend against this by giving the
+.I delim(xx)
+table option;
+this prevents splitting of numerical columns within the delimiters.
+For example, if the
+.I eqn
+delimiters
+are
+.I $$ ,
+giving
+.I delim($$)
+a numerical column such as
+``1245 $+- 16$''
+will be divided after 1245, not after 16.
+.PP
+.I
+Tbl
+.R
+limits tables to twenty columns; however,
+use of more than 16 numerical columns may fail because of
+limits in
+.I
+troff,
+.R
+producing the `too many number registers' message.
+\fITroff\fR number registers used by
+.I
+tbl
+.R
+must be avoided by the user within tables;
+these include two-digit names from 31 to 99,
+and names of the forms
+#\fIx\fR, \fIx\fR+, \fIx\fR\ |, \v'3p'^\v'-3p'\fIx\fR, and \fIx\fR\(mi,
+where
+\fIx\fR is any lower case letter.
+The names
+##, #\(mi, and #^ are also used in certain circumstances.
+To conserve number register names, the
+\fBn\fR
+and
+\fBa\fR
+formats share a register;
+hence the restriction above that they may not be used in the same column.
+.PP
+For aid in writing layout macros,
+.I
+tbl
+.R
+defines a number register TW which is
+the table width; it is defined by the time that the ``\*.TE'' macro
+is invoked and may be used in the expansion of that macro.
+More importantly, to assist in laying out multi-page boxed tables
+the macro T# is defined to produce the bottom lines and side lines of a boxed
+table, and then invoked at its end.  By use of this macro
+in the page footer a multi-page table can be boxed.
+In particular, the
+.I
+ms
+.R
+macros can be used to print a multi-page boxed table with a repeated heading
+by giving the
+argument H to the ``\*.TS'' macro.
+If the table start macro is written
+.br
+       \&\*.TS H
+.br
+a line of the form
+.br
+       \&\*.TH
+.br
+must be given in the table after any table heading (or at the start if none).
+Material up to the ``\*.TH'' is placed at the top of each page of table;
+the remaining lines in the table are placed on several pages as required.
+Note that this is
+.I
+not
+.R
+a feature of
+.I
+tbl,
+.R
+but of the \fIms\fR layout macros.
+.SH
+Examples.
+.PP
+Here are some examples illustrating features of
+.I
+tbl.
+.R
+.ds T \|\h'.4n'\v'-.2n'\s6\zT\s0\s10\v'.2n'\h'-.4n'\(ci\|\s0
+The symbol \*T in the input represents a tab character.
+.de IN
+.po \\n(POu
+.sp |\\n(.hu
+.sp
+.ne \\$1
+.mk
+.B
+Input:
+.R
+.sp .5
+.nf
+.in +3n
+..
+.de OU
+.br
+.in -3n
+.rt
+.po +3i
+.B
+Output:
+.R
+.sp .5
+..
+.rm TS
+.rm TE
+.nf
+.IN 2.5i
+\&\*.TS
+\&box;
+\&c c c
+\&l l l\*.
+\&Language\*TAuthors\*TRuns on
+\&
+\&Fortran\*TMany\*TAlmost anything
+\&PL/1\*TIBM\*T360/370
+\&C\*TBTL\*T11/45,H6000,370
+\&BLISS\*TCarnegie-Mellon\*TPDP-10,11
+\&IDS\*THoneywell\*TH6000
+\&Pascal\*TStanford\*T370
+\&\*.TE
+.OU
+.TS
+box;
+c c c
+l l l.
+Language       Authors Runs on
+
+Fortran        Many    Almost anything
+PL/1   IBM     360/370
+C      BTL     11/45,H6000,370
+BLISS  Carnegie-Mellon PDP-10,11
+IDS    Honeywell       H6000
+Pascal Stanford        370
+.TE
+.IN 2.8i
+\&\*.TS
+\&allbox;
+\&c s s
+\&c c c
+\&n n n\*.
+\&AT&T Common Stock
+\&Year\*TPrice\*TDividend
+\&1971\*T41-54\*T$2\*.60
+\&2\*T41-54\*T2\*.70
+\&3\*T46-55\*T2\*.87
+\&4\*T40-53\*T3\*.24
+\&5\*T45-52\*T3\*.40
+\&6\*T51-59\*T\*.95*
+\&\*.TE
+\&* (first quarter only)
+.OU
+.TS
+allbox;
+c s s
+c c c
+n n n.
+AT&T Common Stock
+Year   Price   Dividend
+1971   41-54   $2.60
+2      41-54   2.70
+3      46-55   2.87
+4      40-53   3.24
+5      45-52   3.40
+6      51-59   .95*
+.TE
+* (first quarter only)
+.IN 4i
+\&\*.TS
+\&box;
+\&c s s
+\&c | c | c
+\&l | l | n\*.
+\&Major New York Bridges
+\&=
+\&Bridge\*TDesigner\*TLength
+\&\(ul
+\&Brooklyn\*TJ\*. A\*. Roebling\*T1595
+\&Manhattan\*TG\*. Lindenthal\*T1470
+\&Williamsburg\*TL\*. L\*. Buck\*T1600
+\&\(ul
+\&Queensborough\*TPalmer &\*T1182
+\&\*T  Hornbostel
+\&\(ul
+\&\*T\*T1380
+\&Triborough\*TO\*. H\*. Ammann\*T\(ul
+\&\*T\*T383
+\&\(ul
+\&Bronx Whitestone\*TO\*. H\*. Ammann\*T2300
+\&Throgs Neck\*TO\*. H\*. Ammann\*T1800
+\&\(ul
+\&George Washington\*TO\*. H\*. Ammann\*T3500
+\&\*.TE
+.OU
+.TS
+box;
+c s s
+c | c | c
+l | l | n.
+Major New York Bridges
+=
+Bridge Designer        Length
+_
+Brooklyn       J. A. Roebling  1595
+Manhattan      G. Lindenthal   1470
+Williamsburg   L. L. Buck      1600
+_
+Queensborough  Palmer &        1182
+         Hornbostel
+_
+               1380
+Triborough     O. H. Ammann    _
+               383
+_
+Bronx Whitestone       O. H. Ammann    2300
+Throgs Neck    O. H. Ammann    1800
+_
+George Washington      O. H. Ammann    3500
+.TE
+.IN 3.0i
+\&\*.TS
+\&c c
+\&np-2 | n | \*.
+\&\*TStack
+\&\*T\(ul
+\&1\*T46
+\&\*T\(ul
+\&2\*T23
+\&\*T\(ul
+\&3\*T15
+\&\*T\(ul
+\&4\*T6\*.5
+\&\*T\(ul
+\&5\*T2\*.1
+\&\*T\(ul
+\&\*.TE
+.OU
+.TS
+c c
+np-2 | n |.
+       Stack
+       _
+1      46
+       _
+2      23
+       _
+3      15
+       _
+4      6.5
+       _
+5      2.1
+       _
+.TE
+.IN 2.5i
+\&\*.TS
+\&box;
+\&L L L
+\&L L \(ul
+\&L L | LB
+\&L L \(ul
+\&L L L\*.
+\&january\*Tfebruary\*Tmarch
+\&april\*Tmay
+\&june\*Tjuly\*TMonths
+\&august\*Tseptember
+\&october\*Tnovember\*Tdecember
+\&\*.TE
+.OU
+.TS
+box;
+L L L
+L L _
+L L | LB
+L L _
+L L L.
+january        february        march
+april  may
+june   july    Months
+august september
+october        november        december
+.TE
+.IN 5.0i
+.e2 ab
+\&\*.TS
+\&box;
+\&cfB s s s\*.
+\&Composition of Foods
+\&\(ul
+\&\*.T&
+\&c  | c s s
+\&c  | c s s
+\&c   | c  | c  | c\*.
+\&Food\*TPercent by Weight
+\&\e^\*T\(ul
+\&\e^\*TProtein\*TFat\*TCarbo-
+\&\e^\*T\e^\*T\e^\*Thydrate
+\&\(ul
+\&\*.T&
+\&l  | n  | n  | n\*.
+\&Apples\*T\*.4\*T\*.5\*T13\*.0
+\&Halibut\*T18\*.4\*T5\*.2\*T\*. \*. \*.
+\&Lima beans\*T7\*.5\*T\*.8\*T22\*.0
+\&Milk\*T3\*.3\*T4\*.0\*T5\*.0
+\&Mushrooms\*T3\*.5\*T\*.4\*T6\*.0
+\&Rye bread\*T9\*.0\*T\*.6\*T52\*.7
+\&\*.TE
+.OU
+.TS
+box;
+cfB s s s.
+Composition of Foods
+_
+.T&
+c  |c s s
+c  |c s s
+c   |c  |c  |c.
+Food   Percent by Weight
+\^     _
+\^     Protein Fat     Carbo-
+\^     \^      \^      hydrate
+_
+.T&
+l  |n  |n  |n.
+Apples .4      .5      13.0
+Halibut        18.4    5.2     ...
+Lima beans     7.5     .8      22.0
+Milk   3.3     4.0     5.0
+Mushrooms      3.5     .4      6.0
+Rye bread      9.0     .6      52.7
+.TE
+.IN 3.7i
+.e2 aa
+\&\*.TS
+\&allbox;
+\&cfI  s   s
+\&c    cw(1i)   cw(1i)
+\&lp9 lp9 lp9\*.
+\&New York Area Rocks
+\&Era\*TFormation\*TAge (years)
+\&Precambrian\*TReading Prong\*T>1 billion
+\&Paleozoic\*TManhattan Prong\*T400 million
+\&Mesozoic\*TT{
+\&\*.na
+\&Newark Basin, incl\*.
+\&Stockton, Lockatong, and Brunswick
+\&formations; also Watchungs
+\&and Palisades\*.
+\&T}\*T200 million
+\&Cenozoic\*TCoastal Plain\*TT{
+\&On Long Island 30,000 years;
+\&Cretaceous sediments redeposited
+\&by recent glaciation\*.
+\&\*.ad
+\&T}
+\&\*.TE
+.OU
+.fi
+.TS
+allbox;
+cfI s   s
+c   cw(1i)   cw(1i)
+lp9 lp9 lp9.
+New York Area Rocks
+Era    Formation       Age (years)
+Precambrian    Reading Prong   >1 billion
+Paleozoic      Manhattan Prong 400 million
+Mesozoic       T{
+.na
+Newark Basin, incl.
+Stockton, Lockatong, and Brunswick
+formations; also Watchungs
+and Palisades.
+T}     200 million
+Cenozoic       Coastal Plain   T{
+On Long Island 30,000 years;
+Cretaceous sediments redeposited
+by recent glaciation.
+.ad
+T}
+.TE
+.IN 2i
+\&\*.EQ
+\&delim $$
+\&\*.EN
+.sp
+\&\*. \*. \*.
+.sp
+\&\*.TS
+\&doublebox;
+\&c c
+\&l l\*.
+\&Name\*TDefinition
+\&\*.sp
+\&\*.vs +2p
+\&Gamma\*T$GAMMA (z) = int sub 0 sup inf  t sup {z-1} e sup -t dt$
+\&Sine\*T$sin (x) = 1 over 2i ( e sup ix - e sup -ix )$
+\&Error\*T$ roman erf (z) = 2 over sqrt pi int sub 0 sup z e sup {-t sup 2} dt$
+\&Bessel\*T$ J sub 0 (z) = 1 over pi int sub 0 sup pi cos ( z sin theta ) d theta $
+\&Zeta\*T$ zeta (s) = sum from k=1 to inf k sup -s ~~( Re~s > 1)$
+\&\*.vs -2p
+\&\*.TE
+.di qq
+.EQ
+delim $$
+.EN
+.di
+.rm qq
+.rs
+.OU
+.TS
+doublebox;
+c c
+l l.
+Name   Definition
+.sp
+.vs +2p
+Gamma  $GAMMA (z) = int sub 0 sup inf  t sup {z-1} e sup -t dt$
+Sine   $sin (x) = 1 over 2i ( e sup ix - e sup -ix )$
+Error  $ roman erf (z) = 2 over sqrt pi int sub 0 sup z e sup {-t sup 2} dt$
+Bessel $ J sub 0 (z) = 1 over pi int sub 0 sup pi cos ( z sin theta ) d theta $
+Zeta   $ zeta (s) = sum from k=1 to inf k sup -s ~~( Re~s > 1)$
+.vs -2p
+.TE
+.ds : \|:\|
+.IN 2i
+\&\*.TS
+\&box, tab(\*:);
+\&cb s s s s
+\&cp-2 s s s s
+\&c |\|| c | c | c | c
+\&c |\|| c | c | c | c
+\&r2 |\|| n2 | n2 | n2 | n\*.
+\&Readability of Text
+\&Line Width and Leading for 10-Point Type
+\&=
+\&Line\*:Set\*:1-Point\*:2-Point\*:4-Point
+\&Width\*:Solid\*:Leading\*:Leading\*:Leading
+\&_
+\&9 Pica\*:\e-9\*.3\*:\e-6\*.0\*:\e-5\*.3\*:\e-7\*.1
+\&14 Pica\*:\e-4\*.5\*:\e-0\*.6\*:\e-0\*.3\*:\e-1\*.7
+\&19 Pica\*:\e-5\*.0\*:\e-5\*.1\*: 0\*.0\*:\e-2\*.0
+\&31 Pica\*:\e-3\*.7\*:\e-3\*.8\*:\e-2\*.4\*:\e-3\*.6
+\&43 Pica\*:\e-9\*.1\*:\e-9\*.0\*:\e-5\*.9\*:\e-8\*.8
+\&\*.TE
+.OU
+.TS
+box, tab(:);
+cb s s s s
+cp-2 s s s s
+c ||c |c |c |c
+c ||c |c |c |c
+r2 ||n2 |n2 |n2 |n.
+Readability of Text
+Line Width and Leading for 10-Point Type
+=
+Line:Set:1-Point:2-Point:4-Point
+Width:Solid:Leading:Leading:Leading
+_
+9 Pica:\-9.3:\-6.0:\-5.3:\-7.1
+14 Pica:\-4.5:\-0.6:\-0.3:\-1.7
+19 Pica:\-5.0:\-5.1: 0.0:\-2.0
+31 Pica:\-3.7:\-3.8:\-2.4:\-3.6
+43 Pica:\-9.1:\-9.0:\-5.9:\-8.8
+.TE
+.IN 7i
+.e2 ac
+\&\*.TS
+\&c s
+\&cip-2 s
+\&l n
+\&a n\*.
+\&Some London Transport Statistics
+\&(Year 1964)
+\&Railway route miles\*T244
+\&Tube\*T66
+\&Sub-surface\*T22
+\&Surface\*T156
+\&\*.sp \*.5
+\&\*.T&
+\&l r
+\&a r\*.
+\&Passenger traffic \e- railway
+\&Journeys\*T674 million
+\&Average length\*T4\*.55 miles
+\&Passenger miles\*T3,066 million
+\&\*.T&
+\&l r
+\&a r\*.
+\&Passenger traffic \e- road
+\&Journeys\*T2,252 million
+\&Average length\*T2\*.26 miles
+\&Passenger miles\*T5,094 million
+\&\*.T&
+\&l n
+\&a n\*.
+\&\*.sp \*.5
+\&Vehicles\*T12,521
+\&Railway motor cars\*T2,905
+\&Railway trailer cars\*T1,269
+\&Total railway\*T4,174
+\&Omnibuses\*T8,347
+\&\*.T&
+\&l n
+\&a n\*.
+\&\*.sp \*.5
+\&Staff\*T73,739
+\&Administrative, etc\*.\*T5,582
+\&Civil engineering\*T5,134
+\&Electrical eng\*.\*T1,714
+\&Mech\*. eng\*. \e- railway\*T4,310
+\&Mech\*. eng\*. \e- road\*T9,152
+\&Railway operations\*T8,930
+\&Road operations\*T35,946
+\&Other\*T2,971
+\&\*.TE
+.OU
+.TS
+c s
+cip-2 s
+l n
+a n.
+Some London Transport Statistics
+(Year 1964)
+Railway route miles    244
+Tube   66
+Sub-surface    22
+Surface        156
+.sp .5
+.T&
+l r
+a r.
+Passenger traffic \(mi railway
+Journeys       674 million
+Average length 4.55 miles
+Passenger miles        3,066 million
+.T&
+l r
+a r.
+Passenger traffic \(mi road
+Journeys       2,252 million
+Average length 2.26 miles
+Passenger miles        5,094 million
+.T&
+l n
+a n.
+.sp .5
+Vehicles       12,521
+Railway motor cars     2,905
+Railway trailer cars   1,269
+Total railway  4,174
+Omnibuses      8,347
+.T&
+l n
+a n.
+.sp .5
+Staff  73,739
+Administrative, etc.   5,582
+Civil engineering      5,134
+Electrical eng.        1,714
+Mech. eng. \(mi railway        4,310
+Mech. eng. \(mi road   9,152
+Railway operations     8,930
+Road operations        35,946
+Other  2,971
+.TE
+.po \n(POu
+.sp |\n(.hu
+.de IN
+.sp
+.ne 1i
+.B
+Input:
+.R
+.sp .5
+.in +3n
+.nf
+..
+.de OU
+.sp
+.in -3n
+.ne 1i
+.B
+Output:
+.R
+.sp .5
+..
+.ns
+.EQ
+delim off
+.EN
+.IN
+\&\*.ps 8
+\&\*.vs 10p
+\&\*.TS
+center box;
+\&c s s
+\&ci s s
+\&c c c
+\&lB l n\*.
+\&New Jersey Representatives
+\&(Democrats)
+\&\*.sp \*.5
+\&Name\*TOffice address\*TPhone
+\&\*.sp \*.5
+\&James J\*. Florio\*T23 S\*. White Horse Pike, Somerdale 08083\*T609-627-8222
+\&William J\*. Hughes\*T2920 Atlantic Ave\*., Atlantic City 08401\*T609-345-4844
+\&James J\*. Howard\*T801 Bangs Ave\*., Asbury Park 07712\*T201-774-1600
+\&Frank Thompson, Jr\*.\*T10 Rutgers Pl\*., Trenton 08618\*T609-599-1619
+\&Andrew Maguire\*T115 W\*. Passaic St\*., Rochelle Park 07662\*T201-843-0240
+\&Robert A\*. Roe\*TU\*.S\*.P\*.O\*., 194 Ward St\*., Paterson 07510\*T201-523-5152
+\&Henry Helstoski\*T666 Paterson Ave\*., East Rutherford 07073\*T201-939-9090
+\&Peter W\*. Rodino, Jr\*.\*TSuite 1435A, 970 Broad St\*., Newark 07102\*T201-645-3213
+\&Joseph G\*. Minish\*T308 Main St\*., Orange 07050\*T201-645-6363
+\&Helen S\*. Meyner\*T32 Bridge St\*., Lambertville 08530\*T609-397-1830
+\&Dominick V\*. Daniels\*T895 Bergen Ave\*., Jersey City 07306\*T201-659-7700
+\&Edward J\*. Patten\*TNatl\*. Bank Bldg\*., Perth Amboy 08861\*T201-826-4610
+\&\*.sp \*.5
+\&\*.T&
+\&ci s s
+\&lB l n\*.
+\&(Republicans)
+\&\*.sp \*.5v
+\&Millicent Fenwick\*T41 N\*. Bridge St\*., Somerville 08876\*T201-722-8200
+\&Edwin B\*. Forsythe\*T301 Mill St\*., Moorestown 08057\*T609-235-6622
+\&Matthew J\*. Rinaldo\*T1961 Morris Ave\*., Union 07083\*T201-687-4235
+\&\*.TE
+\&\*.ps 10
+\&\*.vs 12p
+.ne 3.2i
+.OU
+.ps 8
+.vs 10p
+.TS
+center box;
+c s s
+ci s s
+c c c
+lB l n.
+New Jersey Representatives
+(Democrats)
+.sp .5
+Name   Office address  Phone
+.sp .5
+James J. Florio        23 S. White Horse Pike, Somerdale 08083 609-627-8222
+William J. Hughes      2920 Atlantic Ave., Atlantic City 08401 609-345-4844
+James J. Howard        801 Bangs Ave., Asbury Park 07712       201-774-1600
+Frank Thompson, Jr.    10 Rutgers Pl., Trenton 08618   609-599-1619
+Andrew Maguire 115 W. Passaic St., Rochelle Park 07662 201-843-0240
+Robert A. Roe  U.S.P.O., 194 Ward St., Paterson 07510  201-523-5152
+Henry Helstoski        666 Paterson Ave., East Rutherford 07073        201-939-9090
+Peter W. Rodino, Jr.   Suite 1435A, 970 Broad St., Newark 07102        201-645-3213
+Joseph G. Minish       308 Main St., Orange 07050      201-645-6363
+Helen S. Meyner        32 Bridge St., Lambertville 08530       609-397-1830
+Dominick V. Daniels    895 Bergen Ave., Jersey City 07306      201-659-7700
+Edward J. Patten       Natl. Bank Bldg., Perth Amboy 08861     201-826-4610
+.sp .5
+.T&
+ci s s
+lB l n.
+(Republicans)
+.sp .5v
+Millicent Fenwick      41 N. Bridge St., Somerville 08876      201-722-8200
+Edwin B. Forsythe      301 Mill St., Moorestown 08057  609-235-6622
+Matthew J. Rinaldo     1961 Morris Ave., Union 07083   201-687-4235
+.TE
+.ps 10
+.vs 12p
+.sp
+.fi
+This is a paragraph of normal text placed here only to indicate where
+the left and right margins are.  In this way the reader can judge
+the appearance of centered tables or expanded tables, and observe
+how such tables are formatted.
+.IN
+\&\*.TS
+\&expand;
+\&c s s s
+\&c c c c
+\&l l n n\*.
+\&Bell Labs Locations
+\&Name\*TAddress\*TArea Code\*TPhone
+\&Holmdel\*THolmdel, N\*. J\*. 07733\*T201\*T949-3000
+\&Murray Hill\*TMurray Hill, N\*. J\*. 07974\*T201\*T582-6377
+\&Whippany\*TWhippany, N\*. J\*. 07981\*T201\*T386-3000
+\&Indian Hill\*TNaperville, Illinois 60540\*T312\*T690-2000
+\&\*.TE
+.ne 1.3i
+.OU
+.TS
+expand;
+c s s s
+c c c c
+l l n n.
+Bell Labs Locations
+Name   Address Area Code       Phone
+Holmdel        Holmdel, N. J. 07733    201     949-3000
+Murray Hill    Murray Hill, N. J. 07974        201     582-6377
+Whippany       Whippany, N. J. 07981   201     386-3000
+Indian Hill    Naperville, Illinois 60540      312     690-2000
+.TE
+.br
+.ps 8
+.vs 9p
+.ne 5i
+.IN
+\&\*.TS
+\&box;
+\&cb   s   s   s
+\&c | c | c   s
+\&ltiw(1i) | ltw(2i) | lp8 | lw(1\*.6i)p8\*.
+\&Some Interesting Places
+\&_
+\&Name\*TDescription\*TPractical Information
+\&_
+\&T{
+\&American Museum of Natural History
+\&T}\*TT{
+\&The collections fill 11\*.5 acres (Michelin) or 25 acres (MTA)
+\&of exhibition halls on four floors\*.  There is a full-sized replica
+\&of a blue whale and the world's largest star sapphire (stolen in 1964)\*.
+\&T}\*THours\*T10-5, ex\*. Sun 11-5, Wed\*. to 9
+\&\e^\*T\e^\*TLocation\*TT{
+\&Central Park West & 79th St\*.
+\&T}
+\&\e^\*T\e^\*TAdmission\*TDonation: $1\*.00 asked
+\&\e^\*T\e^\*TSubway\*TAA to 81st St\*.
+\&\e^\*T\e^\*TTelephone\*T212-873-4225
+\&_
+\&Bronx Zoo\*TT{
+\&About a mile long and \*.6 mile wide, this is the largest zoo in America\*.
+\&A lion eats 18 pounds
+\&of meat a day while a sea lion eats 15 pounds of fish\*.
+\&T}\*THours\*TT{
+\&10-4:30 winter, to 5:00 summer
+\&T}
+\&\e^\*T\e^\*TLocation\*TT{
+\&185th St\*. & Southern Blvd, the Bronx\*.
+\&T}
+\&\e^\*T\e^\*TAdmission\*T$1\*.00, but Tu,We,Th free
+\&\e^\*T\e^\*TSubway\*T2, 5 to East Tremont Ave\*.
+\&\e^\*T\e^\*TTelephone\*T212-933-1759
+\&_
+\&Brooklyn Museum\*TT{
+\&Five floors of galleries contain American and ancient art\*.
+\&There are American period rooms and architectural ornaments saved
+\&from wreckers, such as a classical figure from Pennsylvania Station\*.
+\&T}\*THours\*TWed-Sat, 10-5, Sun 12-5
+\&\e^\*T\e^\*TLocation\*TT{
+\&Eastern Parkway & Washington Ave\*., Brooklyn\*.
+\&T}
+\&\e^\*T\e^\*TAdmission\*TFree
+\&\e^\*T\e^\*TSubway\*T2,3 to Eastern Parkway\*.
+\&\e^\*T\e^\*TTelephone\*T212-638-5000
+\&_
+\&T{
+\&New-York Historical Society
+\&T}\*TT{
+\&All the original paintings for Audubon's
+\&\*.I
+\&Birds of America
+\&\*.R
+\&are here, as are exhibits of American decorative arts, New York history,
+\&Hudson River school paintings, carriages, and glass paperweights\*.
+\&T}\*THours\*TT{
+\&Tues-Fri & Sun, 1-5; Sat 10-5
+\&T}
+\&\e^\*T\e^\*TLocation\*TT{
+\&Central Park West & 77th St\*.
+\&T}
+\&\e^\*T\e^\*TAdmission\*TFree
+\&\e^\*T\e^\*TSubway\*TAA to 81st St\*.
+\&\e^\*T\e^\*TTelephone\*T212-873-3400
+\&\*.TE
+.br
+.ps \n(PS
+.vs \n(VSp
+.OU
+.fi
+.rr 10 11 12 13 14 15 16 17 18 19 20 21 22 98 99
+.rr 60 61 62 63 64 65 66 67 68 69 70
+.rr 43 44 45 46 47 48 49 50 51 52 53
+.rr 83 84 85 86 87 88 89 90 91 92 93
+.rr #a
+.rr #b
+.rr #c
+.rr #d
+.rr #e
+.rr YY
+.rr OJ
+.rr P
+.rr AV CW GW DW FL KN SJ A1 A2 A3 I1 I2 I3
+.in 0
+.hy 1
+.TS
+box;
+cb   s   s   s
+c | c | c   s
+ltiw(1i) | ltw(2i) | lp8| lw(1.6i)p8.
+Some Interesting Places
+_
+Name   Description     Practical Information
+_
+T{
+American Museum of Natural History
+T}     T{
+The collections fill 11.5 acres (Michelin) or 25 acres (MTA)
+of exhibition halls on four floors.  There is a full-sized replica
+of a blue whale and the world's largest star sapphire (stolen in 1964).
+T}     Hours   10-5, ex. Sun 11-5, Wed. to 9
+\^     \^      Location        T{
+Central Park West & 79th St.
+T}
+\^     \^      Admission       Donation: $1.00 asked
+\^     \^      Subway  AA to 81st St.
+\^     \^      Telephone       212-873-4225
+_
+Bronx Zoo      T{
+About a mile long and .6 mile wide, this is the largest zoo in America.
+A lion eats 18 pounds
+of meat a day while a sea lion eats 15 pounds of fish.
+T}     Hours   T{
+10-4:30 winter, to 5:00 summer
+T}
+\^     \^      Location        T{
+185th St. & Southern Blvd, the Bronx.
+T}
+\^     \^      Admission       $1.00, but Tu,We,Th free
+\^     \^      Subway  2, 5 to East Tremont Ave.
+\^     \^      Telephone       212-933-1759
+_
+Brooklyn Museum        T{
+Five floors of galleries contain American and ancient art.
+There are American period rooms and architectural ornaments saved
+from wreckers, such as a classical figure from Pennsylvania Station.
+T}     Hours   Wed-Sat, 10-5, Sun 12-5
+\^     \^      Location        T{
+Eastern Parkway & Washington Ave., Brooklyn.
+T}
+\^     \^      Admission       Free
+\^     \^      Subway  2,3 to Eastern Parkway.
+\^     \^      Telephone       212-638-5000
+_
+T{
+New-York Historical Society
+T}     T{
+All the original paintings for Audubon's
+.I
+Birds of America
+.R
+are here, as are exhibits of American decorative arts, New York history,
+Hudson River school paintings, carriages, and glass paperweights.
+T}     Hours   T{
+Tues-Fri & Sun, 1-5; Sat 10-5
+T}
+\^     \^      Location        T{
+Central Park West & 77th St.
+T}
+\^     \^      Admission       Free
+\^     \^      Subway  AA to 81st St.
+\^     \^      Telephone       212-873-3400
+.TE
+.rr 40
+.rr 41
+.rr 42
+.rr 43
+.rr 80
+.rr 81
+.rr 82
+.rr 83
+.rr 60
+.rr 61
+.rr 62
+.rr 63
+.rr #a
+.rr #b
+.rr #c
+.rr #d
+.rr #e
+.rr ##
+.ne 2i
+.fi
+.LP
+.SH
+Acknowledgments.
+.PP
+Many thanks are due to J. C. Blinn, who has done a large amount
+of testing and assisted with the design of the program.
+He has also written many of the more intelligible sentences
+in this document and helped edit all of it.
+All phototypesetting programs on \s-2UNIX\s0 are dependent on the work
+of the late J. F. Ossanna, whose assistance with this program in particular
+had been most helpful.
+This program is patterned on a table formatter originally
+written by J. F. Gimpel.
+The assistance of
+T. A. Dolotta, B. W. Kernighan, and J. N. Sturman
+is gratefully acknowledged.
+.SG MH-1274-MEL-troff
+.ne 2i
+.SH
+References.
+.IP [1]
+J. F. Ossanna,
+.I
+N\s-2ROFF\s0/T\s-2ROFF\s0 User's Manual,
+.R
+Computing Science Technical Report No. 54,
+Bell Laboratories, 1976.
+.IP [2]
+K. Thompson and D. M. Ritchie,
+``The U\s-2NIX\s0 Time-Sharing System,''
+\fIComm. ACM. \fB17\fR, pp. 365\(mi75 (1974).
+.IP [3]
+B. W. Kernighan and L. L. Cherry,
+``A System for Typesetting Mathematics,''
+\fIComm. ACM. \fB18\fR, pp. 151\(mi57 (1975).
+.IP [4]
+M. E. Lesk,
+.I
+Typing Documents on U\s-2NIX\s0,
+.R
+UNIX Programmer's Manual, Volume 2.
+.IP [5]
+M. E. Lesk and B. W. Kernighan,
+.I
+Computer Typesetting of Technical Journals on U\s-2NIX\s0,
+.R
+\f2Proc. AFIPS NCC\f1, vol. 46, pp. 879-888 (1977).
+.IP [6]
+J. R. Mashey and D. W. Smith,
+``Documentation Tools and Techniques,''
+.I
+Proc. 2nd Int. Conf. on Software Engineering,
+.R
+pp. 177-181 (October, 1976).
+.sp 3
+.SH
+.ce
+List of Tbl Command Characters and Words
+.LP
+.EQ
+delim $$
+gfont roman
+.EN
+.TS
+center;
+cI cI cI
+aB lf1 nf1 .
+Command        Meaning Section
+a A    Alphabetic subcolumn    2
+allbox Draw box around all items       1
+b B    Boldface item   2
+box    Draw box around table   1
+c C    Centered column 2
+center Center table in page    1
+doublebox      Doubled box around table        1
+e E    Equal width columns     2
+expand Make table full line width      1
+f F    Font change     2
+i I    Italic item     2
+l L    Left adjusted column    2
+n N    Numerical column        2
+\fInnn\fR      Column separation       2
+p P    Point size change       2
+r R    Right adjusted column   2
+s S    Spanned item    2
+t T    Vertical spanning at top        2
+tab \fR(\fIx\|\fR)     Change data separator character 1
+$fat roman "T{" ~~ fat roman "T}"$     Text block      3
+v V    Vertical spacing change 2
+w W    Minimum width value     2
+\&\s+4.\s0\fIxx\fR     Included \fItroff\fR command    3
+\(bv   Vertical line   2
+\(bv\|\(bv     Double vertical line    2
+\&\s+4\v'4p'^\v'-4p'\s0        Vertical span   2
+\e\&\s+4\v'4p'^\v'-4p'\s0      Vertical span   3
+\&=    Double horizontal line  2,3
+\&$fat "_"$    Horizontal line 2,3
+\&$fat "\e_"$  Short horizontal line   3
+\&$fat "\e"$\f3R\f2x   Repeat character        3
+.TE
diff --git a/doc/7thEdMan/vol2/troff.bun b/doc/7thEdMan/vol2/troff.bun
new file mode 100644 (file)
index 0000000..6722be9
--- /dev/null
@@ -0,0 +1,3808 @@
+# To unbundle, run this file
+echo add
+sed 's/.//' >add <<'//GO.SYSIN DD add'
+-.nr i 1i
+-.de H
+-'sp |.5i-1
+-.tl 'May 15, 1977'''
+-'sp |1i
+-..
+-.de F
+-'bp
+-..
+-.wh 0 H
+-.wh -1i F
+-.de pp
+-.ft R
+-.sp
+-.ti 0
+-..
+-.de h
+-.sp
+-.ti0
+-\fB\\$1\fP
+-.br
+-..
+-.ce
+-.ftB
+-Summary of Changes to N/TROFF Since October 1976 Manual
+-.ft
+-.ta \niu
+-.in \niu
+-.h Options
+-.pp
+--h    (Nroff only) Output tabs used during horizontal spacing
+-to speed output as well as reduce output byte count.
+-Device tab settings assumed to be every
+-8 nominal character widths.
+-The default settings of input (logical) tabs is also
+-initialized to every 8 nominal character widths.
+-.pp
+--z    Efficiently suppresses formatted output.
+-Only message output will occur (from "tm"s and diagnostics).
+-.h "Old Requests"
+-.pp
+-\&.ad\ c      The adjustment type indicator "c" may now also be a number
+-previously obtained from the ".j" register (see below).
+-.pp
+-\&.so\ name   The contents of file "name" will be interpolated
+-at the point the "so" is encountered.
+-Previously, the interpolation was done upon return to the file-reading input level.
+-.h "New Request"
+-.pp
+-\&.ab\ text   \
+-Prints "text" on the message output and terminates
+-without further processing.
+-If "text" is missing, "User Abort." is printed.
+-Does not cause a break.
+-The output buffer is flushed.
+-.pp
+-\&.fz F N     \
+-forces f\b_ont "F" to be in siz\b_e N.
+-N may have the form N, +N, or -N.
+-For example,
+-     .fz 3 -2
+-.br
+-will cause an implicit \es-2 every time font 3 is entered,
+-and a corresponding \es+2 when it is left.
+-Special font characters occurring during the
+-reign of font F will have the same size modification.
+-If special characters are to be treated differently,
+-     .fz S F N
+-.br
+-may be used to specify the size treatment of special
+-characters during font F.
+-For example,
+-     .fz 3 -3
+-     .fz S 3 -0
+-.br
+-will cause automatic reduction of font 3 by 3 points
+-while the special characters would not be affected.
+-Any ``.fp'' request specifying a font on some position
+-must precede ``.fz'' requests relating to that position.
+-.h "New Predefined Number Registers."
+-.pp
+-\&.k  Read-only. Contains the horizontal size
+-of the text portion (without indent) of the current
+-partially collected output line, if any, in
+-the current environment.
+-.pp
+-\&.j  Read-only. A number representing the current adjustment mode and type.
+-Can be saved and later given to the "ad" request to restore a previous mode.
+-.pp
+-\&.P  Read-only.
+-1 if the current page is being printed,
+-and zero otherwise.
+-.pp
+-\&.L  Read-only.
+-Contains the current line-spacing parameter ("ls").
+-.pp
+-\&c.  General register access to the input line-number
+-in the current input file.
+-Contains the same value as the read-only ".c" register.
+//GO.SYSIN DD add
+echo m.mac
+sed 's/.//' >m.mac <<'//GO.SYSIN DD m.mac'
+-.if \n(mo=1 .ds mo January
+-.if \n(mo=2 .ds mo February
+-.if \n(mo=3 .ds mo March
+-.if \n(mo=4 .ds mo April
+-.if \n(mo=5 .ds mo May
+-.if \n(mo=6 .ds mo June
+-.if \n(mo=7 .ds mo July
+-.if \n(mo=8 .ds mo August
+-.if \n(mo=9 .ds mo September
+-.if \n(mo=10 .ds mo October
+-.if \n(mo=11 .ds mo November
+-.if \n(mo=12 .ds mo December
+-.if \n(dw=1 .ds dw Sunday
+-.if \n(dw=2 .ds dw Monday
+-.if \n(dw=3 .ds dw Tuesday
+-.if \n(dw=4 .ds dw Wednesday
+-.if \n(dw=5 .ds dw Thursday
+-.if \n(dw=6 .ds dw Friday
+-.if \n(dw=7 .ds dw Saturday
+-.\"
+-.bd S B 3
+-.ds NR "\s-1NROFF\s+1
+-.ds TR "\s-1TROFF\s+1
+-.ds Nr "N\s-2ROFF\s+2
+-.ds Tr "T\s-2ROFF\s+2
+-.nr PS 10
+-.hy14
+-.ds u \v'-0.3m'\s-2
+-.ds d \s0\v'0.3m'
+-.nr a .8i
+-.nr b 1.6i
+-.nr c 2.4i
+-.nr d 2.9i
+-.nr e 0.25i
+-.nr p 0 1
+-.nr s 0 1
+-.af p 1
+-.af s 1
+-.nr m -1i
+-.nr x 0 1
+-.nr y 0+\nmu
+-.ev1
+-.ps \n(PS-2
+-.vs \n(PS
+-.ll6.5i
+-'in 0
+-.ev
+-.tr &.
+-.de xx
+-.sp 0.4
+-..
+-.de ht
+-.tl `\*(Nr/\*(Tr User's Manual```
+-.tl 'October 11, 1976'''\".tl 'Version \n(mo/\n(dy/\n(yr'''
+-..
+-.de hd
+-.tl '\(rn'''
+-.if \\n%>1 \{'sp |.33i
+-.ht
+-.ps \\n(S2
+-.ps \\n(S1
+-.ft
+-'sp |1i\}
+-.nr x 0 1
+-.nr y 0+\\nmu
+-.ch fo \\nmu
+-.if \\n(dn .fz
+-.ns
+-.mx
+-.nr cl 0 1
+-.mk
+-..
+-.de fz
+-.fn
+-.nf
+-.fy
+-.fi
+-.ef
+-..
+-.de fx
+-.if \\nx .di fy
+-..
+-.de fo
+-.cx
+-.nr dn 0
+-.if \\nx .xf
+-.nr x 0 \"disable fx
+-.ie \\n(2C&(\\n+(cl<2) \{\
+-.po +3.4i
+-.rt
+-.nr y 0+\\nmu
+-.ch fo \\nmu
+-.if \\n(dn .fz
+-.ns \}
+-.el \{\
+-.po 26i/27u
+-.nr S1 \\n(.s
+-.ps
+-.nr S2 \\n(.s
+-.ps 10
+-'bp \}
+-..
+-.de 2C
+-.br
+-.mk
+-.nr 2C 1
+-.ll 3.1i
+-.ev 1
+-.ll 3.1i
+-.ev
+-..
+-.de 1C
+-.br
+-.nr 2C 0
+-.ll 6.5i
+-.ev1
+-.ll 6.5i
+-.ev
+-..
+-.de co
+-.de cx
+-.br
+-\fI(Continued next page.)\fP
+-.br
+-.rm cx
+-\\..
+-..
+-.de pp
+-'ps \\n(PS
+-.ftR
+-'tl ''- % -''
+-'bp
+-..
+-.wh 0 hd
+-.wh 12i fo
+-.wh \nmu fx
+-.ch fo \nmu
+-.de fn
+-.da FN
+-.ev1
+-.if \\n+x=1 .fs
+-.fi
+-.ti0
+-..
+-.de xf
+-.ev1
+-.nf
+-.FN
+-.rm FN
+-.di
+-.ev
+-..
+-.de fs
+-.ti0
+-\l'1i'
+-.br
+-..
+-.de ef
+-.br
+-.ev
+-.di
+-.nr y -\\n(dn
+-.if \\nx=1 .nr y -2p
+-.ch fo \\nyu
+-.if \\n(nl+\\n(.v-\\n(.p-\\ny .ch fo \\n(nlu+\\n(.vu
+-..
+-.wh -.6i pp
+-.de h1
+-.xx
+-.ne 5
+-.nf
+-.ta \\nau \\nbu \\ncu \\ndu +\\neu
+-.ft I
+-.bd I 3
+-Request       Initial If No
+-Form  Value\\$2       Argument        Notes\\$1       Explanation
+-.bd I
+-.ft R
+-.ft
+-.fi
+-.in \\ndu
+-..
+-.de bt
+-.ftR
+-.xx
+-.ne 1.1
+-.ti0
+-..
+-.de b1
+-.br
+-.ti0
+-..
+-.de pg
+-.ft R
+-.fi
+-.in0
+-.xx
+-.ne 1.1
+-..
+-.de sc
+-.pg
+-\fI\\*H\\np.\\n+s.\|\\c
+-.ftR
+-.ul
+-..
+-.de mh
+-.nr s 0
+-.in0
+-.xx
+-.ne 2.5
+-.ft B
+-\\*H\\n+p.
+-..
+-.de x1
+-.xx
+-.in.5i
+-.nf
+-..
+-.de x2
+-.xx
+-.in0
+-.fi
+-..
+-.de EM
+-.br
+-\&\c
+-'bp
+-.pl2i
+-..
+-.em EM
+-.de TS
+-.sp
+-..
+-.de TE
+-.sp
+-.ce 0
+-.ft R
+-.ps \n(PS
+-.ta \\nau \\nbu \\ncu \\ndu +\\neu
+-..
+//GO.SYSIN DD m.mac
+echo m0
+sed 's/.//' >m0 <<'//GO.SYSIN DD m0'
+-.br
+-.rs
+-.sp |1.50i
+-.ce1000
+-.ps12
+-.ftB
+-\*(Nr\(sl\*(Tr User's Manual
+-.sp .2i
+-.ftI
+-.ps10
+-Joseph F. Ossanna
+-.ftR
+-.sp
+-Bell Laboratories
+-Murray Hill, New Jersey 07974
+-.ce0
+-.sp2
+-.ps \n(PS
+-.fi
+-.ftB
+-Introduction
+-.pg
+-\*(NR and \*(TR are text processors under
+-the \s-1PDP\s+1-11 \s-1UNIX\s+1 Time-Sharing System\*u1\*d
+-that format text for typewriter-like terminals and
+-for a \%Graphic Systems phototypesetter, respectively.
+-They accept lines of text interspersed with lines of
+-format control information and
+-format the text into a printable, paginated document
+-having a user-designed style.
+-\*(NR and \*(TR offer
+-unusual freedom in document styling,
+-including:
+-arbitrary style headers and footers;
+-arbitrary style footnotes;
+-multiple automatic sequence numbering for paragraphs, sections, etc;
+-multiple column output;
+-dynamic font and point-size control;
+-arbitrary horizontal and vertical local motions at any point;
+-and
+-a family of automatic overstriking, bracket construction, and
+-line drawing functions.
+-.pg
+-\*(NR and \*(TR are highly compatible with each other and it is almost always
+-possible to prepare input acceptable to both.
+-Conditional input is provided that enables
+-the user to embed input expressly destined for either program.
+-\*(NR can prepare output directly for a variety of terminal types and
+-is capable of utilizing the full resolution of each terminal.
+-.pg
+-.ftB
+-Usage
+-.pg
+-The general form of invoking \*(NR (or \*(TR) at \s-1UNIX\s+1 command level is
+-.x1
+-\fBnroff  \fIoptions  files\fR\
+-\h'|2i'(or  \fBtroff  \fIoptions  files\fR)
+-.x2
+-where \fIoptions\fR represents any of a number of option arguments
+-and \fIfiles\fR represents the list of files containing the document
+-to be formatted.
+-An argument consisting of a single minus (\fB\-\fR) is taken to be
+-a file name corresponding to the standard input.
+-If no file names are given input is taken from the standard input.
+-The options, which may appear in any order so long as they appear
+-before the files, are:
+-.sp
+-.ta .2i 1.0i
+-.ftI
+-.bd I 3
+-      Option  Effect
+-.br
+-.bd I
+-.ftR
+-.ta .3i 1.0i
+-.in 1.0i
+-.ll-.3i
+-.bt
+-      \fB\-o\fIlist\fR        \
+-Print only pages whose page numbers appear in \fIlist\fR,
+-which consists of comma-separated numbers and number ranges.
+-A number range has the form \fIN\-M\fR
+-and means pages \fIN\fR through \fIM;\fR
+-a initial \fI\-N\fR means
+-from the beginning to page \fIN;\fR and a final \fIN\-\fR means
+-from \fIN\fR to the end.
+-.bt
+-      \fB\-n\fIN\fR   Number first generated page \fIN\fR.
+-.bt
+-      \fB\-s\fIN\fR   Stop every \fIN\fR pages.
+-\*(NR will halt prior to every \fIN\fR pages (default \fIN\fR=1)
+-to allow paper loading or
+-changing, and will resume upon receipt of a newline.
+-\*(TR will stop the phototypesetter every \fIN\fR pages,
+-produce a trailer to allow changing cassettes,
+-and will resume after the phototypesetter \s-1START\s+1 button is pressed.
+-.bt
+-      \fB\-m\fIname\fR        Prepends the macro file
+-\fB\(slusr\(sllib\(sltmac.\fIname\fR
+-to the input \fIfiles\fR.
+-.bt
+-      \fB\-r\fIaN\fR  Register \fIa\fR (one-character) is set to \fIN\fR.
+-.bt
+-      \fB\-i\fP       Read standard input after the input files are exhausted.
+-.bt
+-      \fB\-q\fR       \
+-Invoke the simultaneous input-output mode of the \fBrd\fR request.
+-.sp
+-.ne 3
+-.ftI
+-.bd I 3
+-              \*(NR Only
+-.br
+-.bd I
+-.ft
+-.bt
+-      \fB\-T\fIname\fR        Specifies
+-the name of the output terminal type.
+-Currently defined names are \fB37\fR for the (default) Model 37 Teletype\(rg,
+-\fBtn300\fR for the GE TermiNet\ 300 (or any terminal without half-line
+-capabilities),
+-\fB300S\fR for the \s-1DASI\s+1-300S,
+-\fB300\fR for the \s-1DASI\s+1-300,
+-and
+-\fB450\fR for the \s-1DASI\s+1-450 (Diablo Hyterm).
+-.bt
+-      \fB\-e\fR       \
+-Produce equally-spaced words in adjusted
+-lines, using full terminal resolution.
+-.sp
+-.ne 3
+-.ftI
+-.bd I 3
+-              \*(TR Only
+-.br
+-.bd I
+-.ft
+-.bt
+-      \fB\-t\fP       Direct output to the standard output instead
+-of the phototypesetter.
+-.bt
+-      \fB\-f\fP       Refrain from feeding out paper and stopping
+-phototypesetter at the end of the run.
+-.bt
+-      \fB\-w\fP       Wait until phototypesetter is available, if
+-currently busy.
+-.bt
+-      \fB\-b\fR       \*(TR will report whether the phototypesetter
+-is busy or available.
+-No text processing is done.
+-.bt
+-      \fB\-a\fP       Send a printable \s-1(ASCII)\s+1 approximation
+-of the results to the standard output.
+-.bt
+-      \fB\-p\fIN\fR   Print all characters in point size \fIN\fR
+-while retaining all prescribed spacings and motions,
+-to reduce phototypesetter elasped time.
+-.bt
+-      \fB\-g\fR       Prepare output for the Murray Hill
+-Computation Center phototypesetter and direct it to the standard output.
+-.ll
+-.in0
+-.xx
+-.pg
+-Each option is invoked as a separate argument;
+-for example,
+-.x1
+-\fBnroff  \-o\fI4,8\-10  \fB\-T\fI300S  \fB\-m\fIabc  file1  file2\fR
+-.x2
+-requests formatting of pages 4, 8, 9, and 10 of a document contained in the files
+-named \fIfile1\fR and \fIfile2\fR,
+-specifies the output terminal as a \s-1DASI\s+1-300S,
+-and invokes the macro package \fIabc\fR.
+-.pg
+-Various pre- and post-processors are available for use with \*(NR and \*(TR.
+-These include the equation preprocessors \s-1NEQN\s+1 and \s-1EQN\s+1\*u2\*d
+-(for \*(NR and \*(TR respectively),
+-and the table-construction preprocessor \s-1TBL\s+1\*u3\*d.
+-A reverse-line postprocessor \s-1COL\s+1\*u4\*d
+-is available for multiple-column \*(NR output on terminals without reverse-line ability;
+-\s-1COL\s+1 expects the Model 37 Teletype
+-escape sequences that \*(NR produces by default.
+-\s-1TK\s+1\*u4\*d
+-is a 37 Teletype simulator postprocessor for printing \*(NR output on a Tektronix 4014.
+-\s-1TCAT\s+1\*u4\*d
+-is phototypesetter-simulator postprocessor
+-for \*(TR that produces an approximation of phototypesetter output
+-on a Tektronix 4014.
+-For example, in
+-.x1
+-\fBtbl  \fIfiles  \fB|  eqn  |  troff  \-t \fIoptions  \fB|  tcat\fR
+-.x2
+-the first \|\fB|\fR\| indicates the piping of \s-1TBL\s+1's output to \s-1EQN\s+1's input;
+-the second the piping of \s-1EQN\s+1's output to \*(TR's input;
+-and the third indicates the piping of \*(TR's output to \s-1TCAT\s+1.
+-\s-1GCAT\s+1\*u4\*d can be used to send \*(TR (\fB\-g\fR) output to
+-the Murray Hill Computation Center.
+-.br
+-.pg
+-The remainder of this manual consists of:
+-a Summary and Index;
+-a Reference Manual keyed to the index;
+-and
+-a set of Tutorial Examples.
+-Another tutorial is [5].
+-.sp.4i
+-.ta 4i
+-      Joseph F. Ossanna
+-.sp.4
+-.ps -1
+-.vs -1p
+-.pg
+-.ftB
+-References
+-.pg
+-.ta .3i
+-.in .3i
+-.ti0
+-[1]   K. Thompson, D. M. Ritchie,
+-.ul
+-UNIX Programmer's Manual,
+-Sixth Edition (May 1975).
+-.sp.4
+-.ti0
+-[2]   B. W. Kernighan, L. L. Cherry,
+-.ul
+-Typesetting Mathematics \(em User's Guide (Second Edition),
+-Bell Laboratories internal memorandum.
+-.sp.4
+-.ti0
+-[3]   M. E. Lesk,
+-.ul
+-Tbl \(em A Program to Format Tables,
+-Bell Laboratories internal memorandum.
+-.sp.4
+-.ti0
+-[4]   Internal on-line documentation, on \s-1UNIX\s+1.
+-.sp.4
+-.ti0
+-[5]   B. W. Kernighan, \fIA TROFF Tutorial\fR,
+-Bell Laboratories internal memorandum.
+-.in0
+-.ps
+-.vs
+//GO.SYSIN DD m0
+echo m0a
+sed 's/.//' >m0a <<'//GO.SYSIN DD m0a'
+-.pn3
+-.br
+-.tr |
+-.ce
+-.ftB
+-SUMMARY AND INDEX
+-.ftR
+-.de mx
+-.ev2
+-.nf
+-.h1
+-.in
+-.sp
+-.fi
+-.ev
+-.ns
+-..
+-.xx
+-.h1 \s-1#\s+1 *
+-.fn
+-.sp.3
+-*Values separated by "\fB;\fR" are for \*(NR and \*(TR respectively.
+-.sp.2
+-\s-1#\s+1Notes are explained at the end of this Summary and Index
+-.ef
+-.mh
+-General Explanation
+-.mh
+-Font and Character Size Control
+-.bt
+-\fB&ps\fI\|\(+-N\fR   10\|point       previous        E       Point size; also \fB\es\fI\(+-N\fR.\(dg
+-.b1
+-\fB&ss\fI|N\fR        12\(sl36\|em    ignored E       Space-character size
+-set to \fIN\fR\(sl36\|em.\(dg
+-.b1
+-\fB&cs\fI\|F\|N\|M\fR off     -       P       Constant character
+-space (width)
+-mode (font \fIF\^\fR\^).\(dg
+-.b1
+-\fB&bd\fI|F|N\fR      off     -       P       Embolden font \fIF\fR by \fIN\fR\(mi1 units.\(dg
+-.b1
+-\fB&bd|S|\fIF|N\fR    off     -       P       Embolden Special Font when current font is \fIF\fR.\(dg
+-.fn
+-.sp.2
+-\(dgNo effect in \*(NR.
+-.ef
+-.b1
+-\fB&ft\fI|F\fR        Roman   previous        E       Change to font
+-\fIF\fR|= \fIx\fR, \fIxx\fR, or 1-4.
+-Also \fB\ef\fIx\fR,\|\fB\ef(\fIxx\fR,\|\fB\ef\fIN\fR.
+-.b1
+-\fB&fp\fI|N|F\fR      R,I,B,S ignored -       Font named \fIF\fR mounted on physical position 1\(<=\fIN\fR\(<=4.
+-.mh
+-Page Control
+-.bt
+-\fB&pl\fI\|\(+-N\fR   11\|in  11\|in  \fBv\fR Page length.
+-.b1
+-\fB&bp|\fI\(+-N\fR    \fIN\(eq\fR1    -       B\(dd,\fBv\fR   \
+-Eject current page; next page number \fIN\fR.
+-.fn
+-.sp.2
+-\(ddThe use of "\ \fB\'\fR\ " as control character (instead of "\fB.\fR")
+-suppresses the break function.
+-.ef
+-.b1
+-\fB&pn\fI|\(+-N       N\(eq\fR1       ignored -       Next page number \fIN\fR.
+-.b1
+-\fB&po\fI|\(+-N\fR    0;|26\(sl27\|in previous        \fBv\fR Page offset.
+-.b1
+-\fB&ne\fI|N\fR        -       \fIN\(eq\fR1\fIV\fR     D,\fBv\fR       Need \fIN\fR vertical space (\fIV\fR = vertical spacing).
+-.b1
+-\fB&mk|\fIR\fR        none    internal        D       Mark current vertical place in register \fIR\fR.
+-.b1
+-\fB&rt\fI|\(+-N\fR    none    internal        D,\fBv\fR       Return \fI(upward only)\fR to marked vertical place.
+-.mh
+-Text Filling, Adjusting, and Centering
+-.bt
+-\fB&br\fR     -       -       B       Break.
+-.b1
+-.lg0
+-\fB&fi\fR     \(fill  -       B,E     Fill output lines.
+-.lg
+-.b1
+-\fB&nf\fR     fill    -       B,E     No filling or adjusting of output lines.
+-.b1
+-\fB&ad\fI|c\fR        adj,both        adjust  E       Adjust output lines with mode \fIc\fR.
+-.b1
+-\fB&na\fR     adjust  -       E       No output line adjusting.
+-.b1
+-\fB&ce\fI|N\fR        off     \fIN\(eq\fR1    B,E     Center following \fIN\fR input text lines.
+-.mh
+-Vertical Spacing
+-.bt
+-\fB&vs\fI|N\fR        1\(sl6in;12pts  previous        E,\fBp\fR       Vertical base line spacing (\fIV\fR\^).
+-.b1
+-\fB&ls\fI|N   N\(eq\fR1       previous        E       Output \fIN\(mi\fR1 \fIV\^\fRs after each text output line.
+-.b1
+-\fB&sp\fI|N\fR        -       \fIN\(eq\fR1\fIV\fR     B,\fBv\fR       Space \
+-vertical distance \fIN\fR \fIin either direction\fR.
+-.b1
+-\fB&sv\fI|N\fR        -       \fIN\(eq\fR1\fIV\fR     \fBv\fR Save vertical distance \fIN\fR.
+-.b1
+-\fB&os\fR     -       -       -       Output saved vertical distance.
+-.b1
+-\fB&ns\fR     space   -       D       Turn no-space mode on.
+-.b1
+-\fB&rs\fR     -       -       D       Restore spacing; turn no-space mode off.
+-.mh
+-Line Length and Indenting
+-.bt
+-\fB&ll\fI|\(+-N\fR    6.5\|in previous        E,\fBm\fR       Line length.
+-.b1
+-\fB&in\fI|\(+-N\fR    \fIN\(eq\fR\^0  previous        B,E,\fBm\fR     Indent.
+-.b1
+-\fB&ti\fI|\(+-N\fR    -       ignored B,E,\fBm\fR     Temporary indent.
+-.mh
+-Macros, Strings, Diversion, and Position Traps
+-.bt
+-\fB&de\fI|xx|yy\fR    -       \fI.yy=\fB..\fR -       Define or redefine macro \fIxx;\fR end at call of \fIyy\fR.
+-.b1
+-\fB&am\fI|xx|yy\fR    -       \fI.yy=\fB..\fR -       Append to a macro.
+-.b1
+-\fB&ds\fI|xx|string\fR        -       ignored -       Define a string \fIxx\fR containing \fIstring\fR.
+-.b1
+-\fB&as\fI|xx|string\fR        -       ignored -       Append \fIstring\fR to string \fIxx\fR.
+-.b1
+-\fB&rm\fI|xx\fR       -       ignored -       Remove request, macro, or string.
+-.b1
+-\fB&rn\fI|xx|yy\fR    -       ignored -       Rename request, macro, or string \fIxx\fR to \fIyy\fR.
+-.b1
+-\fB&di\fI|xx\fR       -       end     D       Divert output to macro \fIxx\fR.
+-.b1
+-\fB&da\fI|xx\fR       -       end     D       Divert and append to \fIxx\fR.
+-.b1
+-\fB&wh\fI|N|xx\fR     -       -       \fBv\fR Set location trap; negative is w.r.t. page bottom.
+-.b1
+-\fB&ch\fI|xx|N\fR     -       -       \fBv\fR Change trap location.
+-.b1
+-\fB&dt\fI|N|xx\fR     -       off     D,\fBv\fR       Set a diversion trap.
+-.b1
+-\fB&it\fI|N|xx\fR     -       off     E       Set an input-line count trap.
+-.b1
+-\fB&em\fI|xx\fR       none    none    -       End macro is \fIxx\fI.
+-.mh
+-Number Registers
+-.bt
+-\fB&nr\fI|R|\(+-N|M\fR        -       \fBu\fR Define and set number register \fIR\fR; auto-increment by \fIM\fR.
+-.b1
+-\fB&af\fI|R|c\fR      arabic  -       -       Assign format to register \fIR\fR (\fIc=\fB1\fR, \fBi\fR, \fBI\fR, \fBa\fR, \fBA\fR).
+-.b1
+-\fB&rr\fI|R\fR        -       -       -       Remove register \fIR\fR.
+-.mh
+-Tabs, Leaders, and Fields
+-.bt
+-\fB&ta\fI|Nt|...\fR   0.8;|0.5in      none    E,\fBm\fR       Tab settings; \fIleft\fR type, unless \fIt=\fBR\fR(right), \fBC\fR(centered).
+-.b1
+-\fB&tc\fI|c\fR        none    none    E       Tab repetition character.
+-.b1
+-\fB&lc\fI|c\fR        \fB.\fR none    E       Leader repetition character.
+-.b1
+-\fB&fc\fI|a|b\fR      off     off     -       Set field delimiter \fIa\fR and pad character \fIb\fR.
+-.mh
+-Input and Output Conventions and Character Translations
+-.bt
+-\fB&ec\fI|c\fR        \e      \e      -       Set escape character.
+-.b1
+-\fB&eo\fR     on      -       -       Turn off escape character mechanism.
+-.b1
+-\fB&lg\fI|N\fR        -;\|on  on      -       Ligature mode
+-on if \fIN\fR>0.
+-.b1
+-\fB&ul\fI|N\fR        off     \fIN\(eq\fR1    E       Underline (italicize in \*(TR) \fIN\fR input lines.
+-.b1
+-\fB&cu\fI|N\fR        off     \fIN\(eq\fR1    E       Continuous underline in \*(NR; like \fBul\fR in \*(TR.
+-.b1
+-\fB&uf\fI|F\fR        Italic  Italic  -       Underline font set to \fIF\fR (to be switched to by \fBul\fR).
+-.b1
+-\fB&cc\fI|c\fR        \fB.    .\fR    E       Set control character to \fIc\fR.
+-.b1
+-\fB&c2\fI|c\fR        \fB\'   \'\fR   E       Set nobreak control character to \fIc\fR.
+-.b1
+-\fB&tr\fI|abcd....\fR none    -       O       Translate \fIa\fR to \fIb\fR, etc. on output.
+-.mh
+-Local Horizontal and Vertical Motions, and the Width Function
+-.mh
+-Overstrike, Bracket, Line-drawing, and Zero-width Functions
+-.mh
+-Hyphenation.
+-.bt
+-\fB&nh\fR     hyphenate       -       E       No hyphenation.
+-.b1
+-\fB&hy\fI|N\fR        hyphenate       hyphenate       E       Hyphenate; \fIN =\fR mode.
+-.b1
+-\fB&hc\fI|c\fR        \fB\e%  \e%\fR  E       Hyphenation indicator character \fIc\fR.
+-.b1
+-\fB&hw\fI|word1|...\fR        ignored -       Exception words.
+-.mh
+-Three Part Titles.
+-.bt
+-\fB&tl\fI|\'left\|\'center\|\'right\|\'\fR    -       -       Three part title.
+-.b1
+-\fB&pc\fI|c\fR        \fB%\fR off     -       Page number character.
+-.b1
+-\fB&lt\fI|\(+-N\fR    6.5\|in previous        E,\fBm\fR       Length of title.
+-.mh
+-Output Line Numbering.
+-.bt
+-\fB&nm\fI|\(+-N|M|S|I\fR      off     E       Number mode on or off, set parameters.
+-.b1
+-\fB&nn\fI|N\fR        -       \fIN\(eq\fR1    E       Do not number next \fIN\fR lines.
+-.mh
+-Conditional Acceptance of Input
+-.bt
+-\fB&if\fI|c|anything\fR               -       -       If condition \fIc\fR true, accept \fIanything\fR as input,
+-.b1
+-                              for multi-line use \fI\e{anything\|\e}\fR.
+-.b1
+-\fB&if|!\fIc|anything\fR      -       -       If condition \fIc\fR false, accept \fIanything\fR.
+-.b1
+-\fB&if\fI|N|anything\fR       -       \fBu\fR If expression \fIN\fR > 0, accept \fIanything\fR.
+-.b1
+-\fB&if|!\fIN|anything\fR      -       \fBu\fR If expression \fIN\fR \(<= 0, accept \fIanything\fR.
+-.b1
+-\fB&if\fI|\|\'string1\|\'string2\|\'|anything\fR      -       If \fIstring1\fR identical to \fIstring2\fR,
+-accept \fIanything\fR.
+-.b1
+-\fB&if|!\fI\|\'string1\|\'string2\|\'|anything\fR     -       If \fIstring1\fR not identical to \fIstring2\fR,
+-accept \fIanything\fR.
+-.b1
+-\fB&ie\fI|c|anything\fR       -       \fBu\fR If portion of if-else; all above forms (like \fBif\fR).
+-.b1
+-\fB&el\fI|anything\fR         -       -       Else portion of if-else.
+-.mh
+-Environment Switching.
+-.bt
+-\fB&ev\fI|N\fR        \fIN\(eq\fR0    previous        -       Environment switched (\fIpush down\fR).
+-.mh
+-Insertions from the Standard Input
+-.bt
+-\fB&rd\fI|prompt\fR\fR        -       \fIprompt=\s-1\fRBEL\s+1        -       Read insertion.
+-.b1
+-\fB&ex\fR     -       -       -       \
+-Exit from \*(NR\(sl\*(TR.
+-.mh
+-Input\(slOutput File Switching
+-.bt
+-\fB&so\fI|filename\fR         -       -       Switch source file \fI(push down)\fR.
+-.b1
+-\fB&nx\fI|filename\fR         end-of-file     -       Next file.
+-.b1
+-\fB&pi\fI|program\fR          -       -       Pipe output to \fIprogram\fR (\*(NR only).
+-.mh
+-Miscellaneous
+-.bt
+-\fB&mc\fI|c|N\fR      -       off     E,\fBm\fR       Set margin character \fIc\fR and separation \fIN\fR.
+-.b1
+-\fB&tm\fI|string\fR   -       newline -       Print \fIstring\fR on terminal \
+-(\s-1UNIX\s+1 standard message output).
+-.b1
+-\fB&ig\fI|yy\fR       -       \fI.yy=\fB..\fR -       Ignore till call of \fIyy\fR.
+-.b1
+-\fB&pm\fI|t\fR        -       all     -       Print macro names and sizes;
+-.b1
+-                              if \fIt\fR present, print only total of sizes.
+-.b1
+-.lg0
+-\fB&fl\fR     -       -       B       Flush output buffer.
+-.lg
+-.mh
+-Output and Error Messages
+-.xx
+-.nf
+-.rm mx
+-.ftR
+-\l'\n(.lu'
+-.ftB
+-.xx
+-.ta .3iC .6i
+-      Notes-
+-.xx
+-.ftR
+-      B       Request normally causes a break.
+-      D       Mode or relevant parameters associated with current diversion level.
+-      E       Relevant parameters are a part of the current environment.
+-      O       Must stay in effect until logical output.
+-      P       Mode must be still or again in effect at the time of physical output.
+-      \fBv\fR,\fBp\fR,\fBm\fR,\fBu\fR Default scale indicator; if not specified, scale indicators are \fIignored\fR.
+-.br
+-.nr zz 11
+-.de cl
+-.ie \\n+(cl<\n(zz \{\
+-.     po +\\n(.lu/\n(zzu
+-.     rt\}
+-.el \{.po 26i/27u\}
+-..
+-.nr cl 0 1
+-.di zz
+-.ta .3iR
+-.nf
+-.ps 8
+-.vs 10
+-ad    4
+-af    8
+-am    7
+-as    7
+-bd    2
+-bp    3
+-br    4
+-c2    10
+-cc    10
+-ce    4
+-ch    7
+-cs    2
+-cu    10
+-da    7
+-de    7
+-di    7
+-ds    7
+-dt    7
+-ec    10
+-el    16
+-em    7
+-eo    10
+-ev    17
+-ex    18
+-fc    9
+-fi    4
+-fl    20
+-fp    2
+-ft    2
+-hc    13
+-hw    13
+-hy    13
+-ie    16
+-if    16
+-ig    20
+-in    6
+-it    7
+-lc    9
+-lg    10
+-li    10
+-ll    6
+-ls    5
+-lt    14
+-mc    20
+-mk    3
+-na    4
+-ne    3
+-nf    4
+-nh    13
+-nm    15
+-nn    15
+-nr    8
+-ns    5
+-nx    19
+-os    5
+-pc    14
+-pi    19
+-pl    3
+-pm    20
+-pn    3
+-po    3
+-ps    2
+-rd    18
+-rm    7
+-rn    7
+-rr    8
+-rs    5
+-rt    3
+-so    19
+-sp    5
+-ss    2
+-sv    5
+-ta    9
+-tc    9
+-ti    6
+-tl    14
+-tm    20
+-tr    10
+-uf    10
+-ul    10
+-vs    5
+-wh    7
+-.di
+-.nr aa \n(dn/\n(zz
+-.ne \\n(aau+10p
+-.sp
+-.ftB
+-Alphabetical Request and Section Number Cross Reference
+-.ft
+-.sp.3
+-.wh \n(nlu+\n(aau cl
+-.nr qq \n(nlu+\n(aau
+-.ps
+-.vs
+-.mk
+-.zz
+-.rt
+-.sp \n(.tu
+-.ch cl 12i
+-.sp
+-.bp
+-.nf
+-.ftB
+-Escape Sequences for Characters, Indicators, and Functions
+-.ftR
+-.xx
+-.TS
+-c2l
+-c2l2l
+-n2l2l.
+-.ftI
+-.bd I 3
+-Section       Escape
+-Reference     Sequence        Meaning
+-.ftR
+-.bd I
+-.xx
+-10.1  \fB\e\e\fR      \e (to prevent or delay the interpretation of \e\|)
+-10.1  \fB\ee\fR       Printable version of the \fIcurrent\fR escape character.
+-2.1   \fB\e\'\fR      \' (acute accent); equivalent to \fB\e(aa\fR
+-2.1   \fB\e\`\fR      \` (grave accent); equivalent to \fB\e(ga\fR
+-2.1   \fB\e\-\fR      \- Minus sign in the \fIcurrent\fR font
+-7     \fB\e\^.\fR     Period (dot) (see \fBde\fR)
+-11.1  \fB\e\fR(space) Unpaddable space-size space character
+-11.1  \fB\e0\fR       Digit width space
+-.tr ||
+-11.1  \fB\e\||\fR     1\(sl6\|em narrow space character (zero width in \*(NR)
+-.tr |
+-11.1  \fB\e^\fR       1\(sl12\|em half-narrow space character (zero width in \*(NR)
+-.tr &&
+-4.1   \fB\e&\fR       Non-printing, zero width character
+-.tr &.
+-10.6  \fB\e!\fR       Transparent line indicator
+-10.7  \fB\e"\fR       Beginning of comment
+-7.3   \fB\e$\fIN\fR   Interpolate argument 1\(<=\fIN\fR\(<=9
+-13    \fB\e%\fR       Default optional hyphenation character
+-2.1   \fB\e(\fIxx\fR  Character named \fIxx\fR
+-7.1   \fB\e\(**\fIx\fR,|\fB\e\(**(\fIxx\fR    Interpolate string \fIx\fR or \fIxx\fR
+-9.1   \fB\ea\fR       Non-interpreted leader character
+-12.3  \fB\eb\fI\'abc...\|\'\fR        Bracket building function
+-4.2   \fB\ec\fR       Interrupt text processing
+-11.1  \fB\ed\fR       Forward (down) 1\(sl2\|em vertical motion (1\(sl2 line in \*(NR)
+-2.2   \fB\ef\fIx\fR,\fB\ef(\fIxx\fR,\fB\ef\fIN\fR     Change to font named \fIx\fR or \fIxx\fR, or position \fIN\fR
+-11.1  \fB\eh\fI\'N|\'\fR      Local horizontal motion; move right \fIN\fR \fI(negative left)\fR
+-11.3  \fB\ek\fIx\fR   Mark horizontal \fIinput\fR place in register \fIx\fR
+-12.4  \fB\el\fI\|\'Nc\|\'\fR  Horizontal line drawing function (optionally with \fIc\fR\|)
+-12.4  \fB\eL\fI\'Nc\|\'\fR    Vertical line drawing function (optionally with \fIc\fR\|)
+-8     \fB\en\fIx\fR,\fB\en(\fIxx\fR   Interpolate number register \fIx\fR or \fIxx\fR
+-12.1  \fB\eo\fI\'abc...\|\'\fR        Overstrike characters \fIa, b, c, ...\fR
+-4.1   \fB\ep\fR       Break and spread output line
+-11.1  \fB\er\fR       Reverse 1\|em vertical motion (reverse line in \*(NR)
+-2.3   \fB\es\fIN\fR,\|\fB\es\fI\(+-N\fR       Point-size change function
+-9.1   \fB\et\fR       Non-interpreted horizontal tab
+-11.1  \fB\eu\fR       Reverse (up) 1\(sl2\|em vertical motion (1\(sl2 line in \*(NR)
+-11.1  \fB\ev\fI\'N\|\|\'\fR   Local vertical motion; move down \fIN\fR \fI(negative up)\fR
+-11.2  \fB\ew\fI\'string\|\'\fR        Interpolate width of \fIstring\fR
+-5.2   \fB\ex\fI\'N\|\|\'\fR   Extra line-space function \fI(negative before, positive after)\fR
+-12.2  \fB\ez\fIc\fR   Print \fIc\fR with zero width (without spacing)
+-16    \fB\e{\fR       Begin conditional input
+-16    \fB\e}\fR       End conditional input
+-10.7  \fB\e\fR(newline)       Concealed (ignored) newline
+--     \fB\e\fIX\fR    \fIX\fR, any character \fInot\fR listed above
+-.TE
+-.fi
+-.sp
+-The escape sequences
+-\fB\e\e\fR,
+-\fB\e\^.\fR,
+-\fB\e"\fR,
+-\fB\e$\fR,
+-\fB\e\(**\fR,
+-\fB\ea\fR,
+-\fB\en\fR,
+-\fB\et\fR,
+-and
+-\fB\e\fR(newline) are interpreted in \fIcopy mode\fR (\(sc7.2).
+-.bp
+-.ftB
+-.nf
+-Predefined General Number Registers
+-.ft
+-.TS
+-c2l
+-c2l2l
+-n2l2l.
+-.ftI
+-.bd I 3
+-Section       Register
+-Reference     Name    Description
+-.ftR
+-.bd I
+-.xx
+-3     \fB%\fR Current page number.
+-11.2  \fBct\fR        Character type (set by \fIwidth\fR function).
+-7.4   \fBdl\fR        Width (maximum) of last completed diversion.
+-7.4   \fBdn\fR        Height (vertical size) of last completed diversion.
+--     \fBdw\fR        Current day of the week (1-7).
+--     \fBdy\fR        Current day of the month (1-31).
+-11.3  \fBhp\fR        Current horizontal place on \fIinput\fR line.
+-15    \fBln\fR        Output line number.
+--     \fBmo\fR        Current month (1-12).
+-4.1   \fBnl\fR        Vertical position of last printed text base-line.
+-11.2  \fBsb\fR        Depth of string below base line (generated by \fIwidth\fR function).
+-11.2  \fBst\fR        Height of string above base line (generated by \fIwidth\fR function).
+--     \fByr\fR        Last two digits of current year.
+-.TE
+-.sp
+-.ftB
+-Predefined Read-Only Number Registers
+-.ftR
+-.TS
+-c2l
+-c2l2l
+-n2l2l.
+-.ftI
+-.bd I 3
+-Section       Register
+-Reference     Name    Description
+-.ftR
+-.bd I
+-.xx
+-7.3   \fB&$\fR        Number of arguments available at the current macro level.
+--     \fB&A\fR        Set to 1 in \*(TR, if \fB\-a\fR option used; always 1 in \*(NR.
+-11.1  \fB&H\fR        Available horizontal resolution in basic units.
+--     \fB&T\fR        Set to 1 in \*(NR, if \fB\-T\fR option used; always 0 in \*(TR.
+-11.1  \fB&V\fR        Available vertical resolution in basic units.
+-5.2   \fB&a\fR        Post-line extra line-space most recently utilized \
+-using \fB\ex\fI\'N\|\'\fR.
+--     \fB&c\fR        Number of \fIlines\fR read from current input file.
+-7.4   \fB&d\fR        Current vertical place in current diversion; equal to \fBnl\fR, if no diversion.
+-2.2   \fB&f\fR        Current font as physical quadrant (1-4).
+-4     \fB&h\fR        Text base-line high-water mark on current page or diversion.
+-6     \fB&i\fR        Current indent.
+-6     \fB&l\fR        Current line length.
+-4     \fB&n\fR        Length of text portion on previous output line.
+-3     \fB&o\fR        Current page offset.
+-3     \fB&p\fR        Current page length.
+-2.3   \fB&s\fR        Current point size.
+-7.5   \fB&t\fR        Distance to the next trap.
+-4.1   \fB&u\fR        Equal to 1 in fill mode and 0 in nofill mode.
+-5.1   \fB&v\fR        Current vertical line spacing.
+-11.2  \fB&w\fR        Width of previous character.
+--     \fB&x\fR        Reserved version-dependent register.
+--     \fB&y\fR        Reserved version-dependent register.
+-7.4   \fB&z\fR        Name of current diversion.
+-.TE
+-.in0
+-.fi
+//GO.SYSIN DD m0a
+echo m1
+sed 's/.//' >m1 <<'//GO.SYSIN DD m1'
+-.pn8
+-.tr |
+-.tr ~|
+-.rm mx
+-.br
+-.ce
+-.ftB
+-.ps+2
+-.rs
+-.sp1.0i
+-REFERENCE MANUAL
+-.ftR
+-.ps-2
+-.sp
+-.mh
+-General Explanation
+-.sc
+-Form of input.
+-Input consists of \fItext lines\fR, which are destined to be printed,
+-interspersed with \fIcontrol lines\fR,
+-which set parameters or otherwise control subsequent processing.
+-Control lines begin with a \fIcontrol character\fR\(em\
+-normally \fB.\fR (period) or \fB\'\fR (acute accent)\(em\
+-followed by a one or two character name that specifies
+-a basic \fIrequest\fR or the substitution of
+-a user-defined \fImacro\fR in place of the control line.
+-The control character \fB\'\fR suppresses the \fIbreak\fR function\(em\
+-the forced output of a partially filled line\(em\
+-caused by certain requests.
+-The control character may be separated from the request/macro name by
+-white space (spaces and/or tabs) for esthetic reasons.
+-Names must be followed by either
+-space or newline.
+-Control lines with unrecognized names are ignored.
+-.pg
+-Various special functions may be introduced anywhere in the input by
+-means of an \fIescape\fR character, normally \fB\e\fR.
+-For example, the function
+-\fB\en\fIR\fR
+-causes the interpolation of the contents of the
+-\fInumber register R\fR
+-in place of the function;
+-here \fIR\fR is either a single character name
+-as in \fB\en\fIx\fR,
+-or left-parenthesis-introduced, two-character name as in \fB\en(\fIxx\fR.
+-.sc
+-Formatter and device resolution.
+-\*(TR internally uses 432 units\(slinch, corresponding to
+-the Graphic Systems phototypesetter
+-which has a horizontal resolution of
+-1\(sl432 inch and a vertical resolution
+-of 1\(sl144 inch.
+-\*(NR internally uses 240 units\(slinch,
+-corresponding to the least common multiple of the
+-horizontal and vertical resolutions of various
+-typewriter-like output devices.
+-\*(TR rounds horizontal\(slvertical numerical parameter input to the actual
+-horizontal\(slvertical resolution of the Graphic Systems typesetter.
+-\*(NR similarly rounds numerical input to the actual resolution
+-of the output device indicated by the \fB\(miT\fR option
+-(default Model 37 Teletype).
+-.sc
+-Numerical parameter input.
+-Both \*(NR and \*(TR
+-accept numerical input with the appended scale
+-indicators
+-shown in the following table,
+-where
+-\fIS\fR is the current type size in points,
+-\fIV\fR is the current vertical line spacing in
+-basic units,
+-and
+-\fIC\fR is a \fInominal character width\fR in basic units.
+-.TS
+-center box;
+-c|c|ls
+-c|c|ll
+-c|l|l|l.
+-Scale         Number of basic units
+-Indicator     Meaning \*(TR   \*(NR
+-_
+-\fBi\fR       Inch    432     240
+-\fBc\fR       Centimeter      432\(mu50\(sl127        240\(mu50\(sl127
+-\fBP\fR       Pica = 1\(sl6 inch      72      240\(sl6
+-\fBm\fR       Em = \fIS\fR points     6\(mu\fIS\fR    \fIC\fR
+-\fBn\fR       En = Em\(sl2    3\(mu\fIS\fR    \fIC, same as Em\fR
+-\fBp\fR       Point = 1\(sl72 inch    6       240\(sl72
+-\fBu\fR       Basic unit      1       1
+-\fBv\fR       Vertical line space     \fIV\fR \fIV\fR
+-none  Default, see below
+-.TE
+-In \*(NR, \fIboth\fR the em and the en are taken to be equal to the \fIC\fR,
+-which is output-device dependent;
+-common values are 1\(sl10 and 1\(sl12 inch.
+-Actual character widths in \*(NR need not be all the same and constructed characters
+-such as \(mi> (\(->) are often extra wide.
+-The default scaling is ems for the horizontally-oriented requests
+-and functions
+-\fBll\fR,
+-\fBin\fR,
+-\fBti\fR,
+-\fBta\fR,
+-\fBlt\fR,
+-\fBpo\fR,
+-\fBmc\fR,
+-\fB\eh\fR,
+-and
+-\fB\el\fR;
+-\fIV\^\fRs
+-for the vertically-oriented requests and functions
+-\fBpl\fR,
+-\fBwh\fR,
+-\fBch\fR,
+-\fBdt\fR,
+-\fBsp\fR,
+-\fBsv\fR,
+-\fBne\fR,
+-\fBrt\fR,
+-\fB\ev\fR,
+-\fB\ex\fR,
+-and
+-\fB\eL\fR;
+-\fBp\fR for the \fBvs\fR request;
+-and \fBu\fR for the requests
+-\fBnr\fR,
+-\fBif\fR,
+-and
+-\fBie\fR.
+-\fIAll\fR other requests ignore any scale indicators.
+-When a number register containing an already appropriately scaled number
+-is interpolated to provide numerical input,
+-the unit scale indicator
+-\fBu\fR may need to be appended to prevent
+-an additional inappropriate default scaling.
+-The number, \fIN\fR, may be specified in decimal-fraction form
+-but the parameter finally stored is rounded to an integer number of basic units.
+-.pg
+-The \fIabsolute position\fR indicator \fB~\fR may be prepended
+-to a number \fIN\fR
+-to generate the distance to the vertical or horizontal place \fIN\fR.
+-For vertically-oriented requests and functions, \fB~\|\fIN\fR
+-becomes the distance in basic units from the current vertical place on the page or in a \fIdiversion\fR (\(sc7.4)
+-to the the vertical place \fIN\fR.
+-For \fIall\fR other requests and functions,
+-\fB~\|\fIN\fR
+-becomes the distance from
+-the current horizontal place on the \fIinput\fR line to the horizontal place \fIN\fR.
+-For example,
+-.x1
+-\&\fB.sp  ~\|3.2c\fR
+-.x2
+-will space \fIin the required direction\fR to 3.2\|centimeters from the top of the page.
+-.sc
+-.tr &&
+-Numerical expressions.
+-Wherever numerical input is expected an expression involving parentheses,
+-the arithmetic operators \fB\(pl\fR, \fB\(mi\fR, \fB\(sl\fR, \fB\(**\fR, \fB%\fR (mod),
+-and the logical operators
+-\fB<\fR,
+-\fB>\fR,
+-\fB<\(eq\fR,
+-\fB>\(eq\fR,
+-\fB\(eq\fR (or \fB\(eq\(eq\fR),
+-\fB&\fR\ (and),
+-\fB:\fR\ (or)
+-may be used.
+-Except where controlled by parentheses, evaluation of expressions is left-to-right;
+-there is no operator precedence.
+-In the case of certain requests, an initial \fB\(pl\fR or \fB\(mi\fR is stripped
+-and interpreted as an increment or decrement indicator respectively.
+-In the presence of default scaling, the desired scale indicator must be
+-attached to \fIevery\fR number in an expression
+-for which the desired and default scaling differ.
+-For example,
+-if the number register \fBx\fR contains 2
+-and the current point size is 10,
+-then
+-.br
+-.tr &.
+-.x1
+-.ftB
+-\&.ll  (4.25i\(pl\enxP\(pl3)\(sl2u
+-.ftR
+-.x2
+-will set the line length to 1\(sl2 the sum of 4.25 inches \(pl 2 picas \(pl 30 points.
+-.sc
+-Notation.
+-Numerical parameters are indicated in this manual in two ways.
+-\(+-\fIN\fR means that the argument may take the forms \fIN\fR, \(pl\fIN\fR, or \(mi\fIN\fR and
+-that the corresponding effect is to set the affected parameter
+-to \fIN\fR, to increment it by \fIN\fR, or to decrement it by \fIN\fR respectively.
+-Plain \fIN\fR means that an initial algebraic sign is \fInot\fR
+-an increment indicator,
+-but merely the sign of \fIN\fR.
+-Generally, unreasonable numerical input is either ignored
+-or truncated to a reasonable value.
+-For example,
+-most requests expect to set parameters to non-negative
+-values;
+-exceptions are
+-\fBsp\fR,
+-\fBwh\fR,
+-\fBch\fR,
+-\fBnr\fR,
+-and
+-\fBif\fR.
+-The requests
+-\fBps\fR,
+-\fBft\fR,
+-\fBpo\fR,
+-\fBvs\fR,
+-\fBls\fR,
+-\fBll\fR,
+-\fBin\fR,
+-and
+-\fBlt\fR
+-restore the \fIprevious\fR parameter value in the \fIabsence\fR
+-of an argument.
+-.pg
+-Single character arguments are indicated by single lower case letters
+-and
+-one/two character arguments are indicated by a pair of lower case letters.
+-Character string arguments are indicated by multi-character mnemonics.
+-.mh
+-Font and Character Size Control
+-.sc
+-Character set.
+-The \*(TR character set consists of the Graphics Systems Commercial|II
+-character set plus a Special Mathematical Font character
+-set\(emeach having 102 characters.
+-These character sets are shown in the attached Table|I.
+-All \s-1ASCII\s+1 characters are included,
+-with some on the Special Font.
+-With three exceptions, the \s-1ASCII\s+1 characters are input as themselves,
+-and non-\s-1ASCII\s+1 characters are input in the form \fB\e(\fIxx\fR where
+-\fIxx\fR is a two-character name given in the attached Table|II.
+-The three \s-1ASCII\s+1 exceptions are mapped as follows:
+-.TS
+-center box;
+-cs|cs
+-cc|cc
+-cl|cl.
+-\s-1ASCII\s+1 Input   Printed by \*(TR
+-Character     Name    Character       Name
+-_
+-\'    acute accent    '       close quote
+-\`    grave accent    `       open quote
+-\(mi  minus   -       hyphen
+-.TE
+-.tr ~~
+-The characters
+-\fB\'\fR,
+-\fB\`\fR,
+-and
+-\fB\-\fR
+-may be input
+-by \fB\e\'\fR, \fB\e\`\fR, and \fB\e\-\fR respectively or by their names (Table II).
+-The \s-1ASCII\s+1 characters \fB@\fR, \fB#\fR, \fB"\fR, \fB\(aa\fR, \fB\(ga\fR, \fB<\fR, \fB>\fR, \fB\e\fR, \fB{\fR, \fB}\fR, \fB~\fR, \fB^\fR, and \fB\(ul\fR exist
+-only on the Special Font and are printed as a 1-em space if that Font
+-is not mounted.
+-.pg
+-.tr ~|
+-\*(NR understands the entire \*(TR character set,
+-but can in general print only \s-1ASCII\s+1
+-characters,
+-additional characters as may be available on
+-the output device,
+-such characters as may be able to be constructed
+-by overstriking or other combination,
+-and those that can reasonably be mapped
+-into other printable characters.
+-The exact behavior is determined by a driving
+-table prepared for each device.
+-The characters
+-\fB\'\fR,
+-\fB\`\fR,
+-and
+-\fB\(ul\fR
+-print
+-as themselves.
+-.sc
+-Fonts.
+-The default mounted fonts are
+-Times Roman (\fBR\fR),
+-Times Italic (\fBI\fR),
+-Times Bold (\fBB\fR),
+-and the Special Mathematical Font (\fBS\fR)
+-on physical typesetter positions 1, 2, 3, and 4 respectively.
+-These fonts are used in this document.
+-The \fIcurrent\fR font, initially Roman, may be changed
+-(among the mounted fonts)
+-by use of the \fBft\fR request,
+-or by imbedding at any desired point
+-either \fB\ef\fIx\fR, \fB\ef(\fIxx\fR, or \fB\ef\fIN\fR
+-where
+-\fIx\fR and \fIxx\fR are the name of a mounted font
+-and \fIN\fR is a numerical font position.
+-It is \fInot\fR necessary to change to the Special font;
+-characters on that font are automatically handled.
+-A request for a named but not-mounted font is \fIignored\fR.
+-\*(TR can be informed that any particular font is mounted
+-by use of the \fBfp\fR request.
+-The list of known fonts is installation dependent.
+-In the subsequent discussion of font-related requests,
+-\fIF\fR represents either a one\(sltwo-character
+-font name or the numerical font position, 1-4.
+-The current font is available (as numerical position) in the read-only number register \fB.f\fR.
+-.pg
+-\*(NR understands font control
+-and normally underlines Italic characters (see \(sc10.5).
+-.sc
+-Character size.
+-Character point sizes available on the Graphic Systems typesetter are
+-6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, and 36.
+-This is a range of 1\(sl12 inch to 1\(sl2 inch.
+-The \fBps\fR request is used to change or restore the point size.
+-Alternatively the point size may be changed between any two characters
+-by imbedding a \fB\es\fIN\fR
+-at the desired point
+-to set the size to \fIN\fR,
+-or a \fB\es\fI\(+-N\fR (1\(<=\fIN\fR\(<=9)
+-to increment\(sldecrement the size by \fIN\fR;
+-\fB\es0\fR restores the \fIprevious\fR size.
+-Requested point size values that are between two valid
+-sizes yield the larger of the two.
+-The current size is available in the \fB.s\fR register.
+-\*(NR ignores type size control.
+-.h1 *
+-.fn
+-.xx
+-*Notes are explained at the end of the Summary and Index above.
+-.ef
+-.bt
+-\fB&ps\fI|\(+-N\fR    10\|point       previous        E       Point size
+-set to \(+-\fIN\fR.
+-Alternatively imbed \fB\es\fIN\fR or \fB\es\fI\(+-N\fR.
+-Any positive size value may be requested;
+-if invalid, the next larger valid size will result, with a
+-maximum of 36.
+-A paired sequence
+-\(pl\fIN\fR,\|\(mi\fIN\fR
+-will work because the previous requested value is also remembered.
+-Ignored in \*(NR.
+-.bt
+-\fB&ss\fI|N\fR        12\(sl36\|em    ignored E       Space-character size
+-is set to \fIN\fR\(sl36\|ems.
+-This size is the minimum word spacing in adjusted text.
+-Ignored in \*(NR.
+-.bt
+-\fB&cs\|\fIF\|N\|M\fR off     -       P       Constant character space
+-(width) mode is
+-set on for font \fIF\fR (if mounted); the width of every character will be
+-taken to be \fIN\fR\(sl36 ems.
+-If \fIM\fR is absent,
+-the em is that of the character's point size;
+-if \fIM\fR is given,
+-the em is \fIM\fR-points.
+-All affected characters
+-are centered in this space, including those with an actual width
+-larger than this space.
+-Special Font characters occurring while the current font
+-is \fIF\fR are also so treated.
+-If \fIN\fR is absent, the mode is turned off.
+-The mode must be still or again in effect when the characters are physically printed.
+-Ignored in \*(NR.
+-.bt
+-\fB&bd\fI|F|N\fR      off     -       P       The characters in font \fIF\fR will be artificially
+-emboldened by printing each one twice, separated by \fIN\fR\^\(mi1 basic units.
+-A reasonable value for \fIN\fR is 3 when the character size is in the vicinity
+-of 10 points.
+-If \fIN\fR is missing the embolden mode is turned off.
+-The column heads above were printed with \fB.bd|I|3\fR.
+-The mode must be still or again in effect when the characters are physically printed.
+-Ignored in \*(NR.
+-.bt
+-\fB&bd|S|\fIF|N\fR    off     -       P       The characters in the Special Font
+-will be emboldened whenever the current font is \fIF\fR.
+-This manual was printed with \fB.bd\|S\|B\|3\fR.
+-The mode must be still or again in effect when the characters are physically printed.
+-.bt
+-\fB&ft|\fIF\fR        Roman   previous        E       Font changed to
+-\fIF\fR.
+-Alternatively, imbed \fB\ef\fIF\fR.
+-The font name \fBP\fR is reserved to mean the previous font.
+-.bt
+-\fB&fp|\fIN|F\fR      R,I,B,S ignored -       Font position.
+-This is a statement
+-that a font named \fIF\fR is mounted on position \fIN\fR (1-4).
+-It is a fatal error if \fIF\fR is not known.
+-The phototypesetter has four fonts physically mounted.
+-Each font consists of a film strip which can be mounted on a numbered
+-quadrant of a wheel.
+-The default mounting sequence assumed by \*(TR is
+-R, I, B, and S on positions 1, 2, 3 and 4.
+-.mh
+-Page control
+-.pg
+-Top and bottom margins are \fInot\fR automatically provided;
+-it is conventional to define two \fImacros\fR and to set \fItraps\fR
+-for them at vertical positions 0 (top) and \fI\(miN\fR (\fIN\fR from the bottom).
+-See \(sc7 and Tutorial Examples \(scT2.
+-A pseudo-page transition onto the \fIfirst\fR page occurs
+-either when the first \fIbreak\fR occurs or
+-when the first \fInon-diverted\fR text processing occurs.
+-Arrangements
+-for a trap to occur at the top of the first page
+-must be completed before this transition.
+-In the following, references to the \fIcurrent diversion\fR (\(sc7.4)
+-mean that the mechanism being described works during both
+-ordinary and diverted output (the former considered as the top diversion level).
+-.pg
+-The useable page width on the Graphic Systems phototypesetter
+-is about 7.54|inches,
+-beginning about 1\(sl27|inch from the left edge of the
+-8|inch wide, continuous roll paper.
+-The physical limitations on \*(NR output
+-are output-device dependent.
+-.h1
+-.bt
+-\fB&pl\fI|\(+-N\fR    11\|in  11\|in  \fBv\fR Page length set to \fI\(+-N\fR.
+-The internal limitation is about 75|inches in \*(TR and
+-about 136|inches in \*(NR.
+-The current page length is available in the \fB.p\fR register.
+-.bt
+-\fB&bp\fI|\(+-N\fR    \fIN\(eq\fR1    -       B*,\fBv\fR      Begin page.
+-.fn
+-.xx
+-*The use of "\ \fB\'\fR\ " as control character (instead of "\fB.\fR")
+-suppresses the break function.
+-.ef
+-The current page is ejected and a new page is begun.
+-If \fI\(+-N\fR is given, the new page number will be \fI\(+-N\fR.
+-Also see request \fBns\fR.
+-.bt
+-\fB&pn\fI|\(+-N\fR    \fIN\fR\(eq1    ignored -       Page number.
+-The next page (when it occurs) will have the page number \fI\(+-N\fR.
+-A \fBpn\fR must occur before the initial pseudo-page transition
+-to effect the page number of the first page.
+-The current page number is in the \fB%\fR register.
+-.bt
+-\fB&po\fI|\(+-N\fR    0;|26\(sl27\|in\(dg     previous        \fBv\fR Page offset.
+-.fn
+-.xx
+-\(dgValues separated by ";" are for \*(NR and \*(TR respectively.
+-.ef
+-The current \fIleft margin\fR is set to \fI\(+-N\fR.
+-The \*(TR initial value provides about 1|inch of paper margin
+-including the physical typesetter margin of 1\(sl27|inch.
+-In \*(TR the maximum (line-length)+(page-offset) is about 7.54 inches.
+-See \(sc6.
+-The current page offset is available in the \fB.o\fR register.
+-.bt
+-\fB&ne\fI|N\fR        -       \fIN\(eq\fR1\|\fIV\fR   D,\fBv\fR       Need \fIN\fR vertical space.
+-If the distance, \fID\fR, to the next trap position (see \(sc7.5) is less than \fIN\fR,
+-a forward vertical space of size \fID\fR occurs,
+-which will spring the trap.
+-If there are no remaining
+-traps on the page,
+-\fID\fR is the distance to the bottom of the page.
+-If \fID\|<\|V\fR, another line could still be output
+-and spring the trap.
+-In a diversion, \fID\fR is the distance to the \fIdiversion trap\fR, if any,
+-or is very large.
+-.bt
+-\fB&mk\fI|R\fR        none    internal        D       Mark the \fIcurrent\fR vertical place
+-in an internal register (both associated with the current diversion level),
+-or in register \fIR\fR, if given.
+-See \fBrt\fR request.
+-.bt
+-\fB&rt\fI|\(+-N\fR    none    internal        D,\fBv\fR       Return \fIupward only\fR to a marked vertical place
+-in the current diversion.
+-If \fI\(+-N\fR (w.r.t. current place) is given,
+-the place is \fI\(+-N\fR from the top of the page or diversion
+-or, if \fIN\fR is absent, to a
+-place marked by a previous \fBmk\fR.
+-Note that the \fBsp\fR request (\(sc5.3) may be used
+-in all cases instead of \fBrt\fR
+-by spacing to the absolute place stored in a explicit register;
+-e.|g. using the sequence \fB.mk|\fIR\fR ... \fB.sp|~\|\en\fIR\fBu\fR.
+-.mh
+-Text Filling, Adjusting, and Centering
+-.sc
+-Filling and adjusting.
+-Normally,
+-words are collected from input text lines
+-and assembled into a output text line
+-until some word doesn't fit.
+-An attempt is then made
+-the hyphenate the word in effort to assemble a part
+-of it into the output line.
+-The spaces between the words on the output line
+-are then increased to spread out the line
+-to the current \fIline length\fR
+-minus any current \fIindent\fR.
+-A \fIword\fR is any string of characters delimited by
+-the \fIspace\fR character or the beginning/end of the input line.
+-Any adjacent pair of words that must be kept together
+-(neither split across output lines nor spread apart
+-in the adjustment process)
+-can be tied together by separating them with the
+-\fIunpaddable space\fR character
+-"\fB\e\ \ \fR" (backslash-space).
+-The adjusted word spacings are uniform in \*(TR
+-and the minimum interword spacing can be controlled
+-with the \fBss\fR request (\(sc2).
+-In \*(NR, they are normally nonuniform because of
+-quantization to character-size spaces;
+-however,
+-the command line option \fB\-e\fR causes uniform
+-spacing with full output device resolution.
+-Filling, adjustment, and hyphenation (\(sc13) can all be
+-prevented or controlled.
+-The \fItext length\fR on the last line output is available in the \fB.n\fR register,
+-and text base-line position on the page for this line is in the \fBnl\fR register.
+-The text base-line high-water mark (lowest place) on the current page is in
+-the \fB.h\fR register.
+-.pg
+-An input text line ending with \fB.\fR\^, \fB?\fR, or \fB!\fR is taken
+-to be the end of a \fIsentence\fR, and an additional space character is
+-automatically provided during filling.
+-Multiple inter-word space characters found in the input are retained,
+-except for trailing spaces;
+-initial spaces also cause a \fIbreak\fR.
+-.pg
+-When filling is in effect, a \fB\ep\fR may be imbedded or attached to a word to
+-cause a \fIbreak\fR at the \fIend\fR of the word and have the resulting output
+-line \fIspread out\fR to fill the current line length.
+-.pg
+-.tr &&
+-A text input line that happens to begin
+-with a control character can
+-be made to not look like a control line
+-by prefacing it with
+-the non-printing, zero-width filler character \fB\e&\fR.
+-Still another way is to specify output translation of some
+-convenient character into the control character
+-using \fBtr\fR (\(sc10.5).
+-.tr &.
+-.sc
+-Interrupted text.
+-The copying of a input line in \fInofill\f (non-fill) mode can be \fIinterrupted\fR
+-by terminating
+-the partial line with a \fB\ec\fR.
+-The \fInext\fR encountered input text line will be considered to be a continuation
+-of the same line of input text.
+-Similarly,
+-a word within \fIfilled\fR text may be interrupted by terminating the
+-word (and line) with \fB\ec\fR;
+-the next encountered text will be taken as a continuation of the
+-interrupted word.
+-If the intervening control lines cause a break,
+-any partial line will be forced out along with any partial word.
+-.h1
+-.bt
+-\fB&br\fR     -       -       B       Break.
+-The filling of the line currently
+-being collected is stopped and
+-the line is output without adjustment.
+-Text lines beginning with space characters
+-and empty text lines (blank lines) also cause a break.
+-.bt
+-.lg0
+-\fB&fi\fR     \(fill|on       -       B,E     Fill subsequent output lines.
+-.lg
+-The register \fB.u\fR is 1 in fill mode and 0 in nofill mode.
+-.bt
+-\fB&nf\fR     fill|on -       B,E     Nofill.
+-Subsequent output lines are \fIneither\fR filled \fInor\fR adjusted.
+-Input text lines are copied directly to output lines
+-\fIwithout regard\fR for the current line length.
+-.bt
+-\fB&ad\fI|c\fR        adj,both        adjust  E       \
+-Line adjustment is begun.
+-If fill mode is not on, adjustment will be deferred until
+-fill mode is back on.
+-If the type indicator \fIc\fR is present,
+-the adjustment type is changed as shown in the following table.
+-.TS
+-center box;
+-c|c
+-c|l.
+-Indicator     Adjust Type
+-_
+-\fBl\fR       adjust left margin only
+-\fBr\fR       adjust right margin only
+-\fBc\fR       center
+-\fBb\fR or \fBn\fR    adjust both margins
+-absent        unchanged
+-.TE
+-.bt
+-\fB&na\fR     adjust  -       E       Noadjust.
+-Adjustment is turned off;
+-the right margin will be ragged.
+-The adjustment type for \fBad\fR is not changed.
+-Output line filling still occurs if fill mode is on.
+-.bt
+-\fB&ce\fI|N\fR        off     \fIN\fR\(eq1    B,E     Center the next \fIN\fR input text lines
+-within the current (line-length minus indent).
+-If \fIN\fR\(eq\^0, any residual count is cleared.
+-A break occurs after each of the \fIN\fR input lines.
+-If the input line is too long,
+-it will be left adjusted.
+-.mh
+-Vertical Spacing
+-.sc
+-Base-line spacing.
+-The vertical spacing \fI(V)\fR between the base-lines of successive
+-output lines can be set
+-using the \fBvs\fR request
+-with a resolution of 1\(sl144\|inch\|\(eq\|1\(sl2|point
+-in \*(TR,
+-and to the output device resolution in \*(NR.
+-\fIV\fR must be large enough to accommodate the character sizes
+-on the affected output lines.
+-For the common type sizes (9-12 points),
+-usual typesetting practice is to set \fIV\fR to 2\ points greater than the
+-point size;
+-\*(TR default is 10-point type on a 12-point spacing
+-(as in this document).
+-The current \fIV\fR is available in the \fB.v\fR register.
+-Multiple-\fIV\|\fR line separation (e.\|g. double spacing) may be requested
+-with \fBls\fR.
+-.sc
+-Extra line-space.
+-If a word contains a vertically tall construct requiring
+-the output line containing it to have extra vertical space
+-before and\(slor after it,
+-the \fIextra-line-space\fR function \fB\ex\fI\'N\|\|\'\fR
+-can be imbedded in or attached to that word.
+-In this and other functions having a pair of delimiters around
+-their parameter (here \fB\'\fR\|),
+-the delimiter choice is arbitrary,
+-except that it can't look like the continuation of a number expression for \fIN\fR.
+-If \fIN\fR is negative,
+-the output line containing the word will
+-be preceded by \fIN\fR extra vertical space;
+-if \fIN\fR is positive,
+-the output line containing the word
+-will be followed by \fIN\fR extra vertical space.
+-If successive requests for extra space apply to the same line,
+-the maximum values are used.
+-The most recently utilized post-line extra line-space is available in the \fB.a\fR register.
+-.sc
+-Blocks of vertical space.
+-A block of vertical space is ordinarily requested using \fBsp\fR,
+-which honors the \fIno-space\fR mode and which does
+-not space \fIpast\fR a trap.
+-A contiguous block of vertical space may be reserved using \fBsv\fR.
+-.h1
+-.bt
+-\fB&vs\fI\|N\fR       1\(sl6in;12pts  previous        E,\fBp\fR       Set vertical base-line spacing size \fIV\fR.
+-Transient \fIextra\fR vertical space available with \fB\ex\fI\'N\|\|\'\fR (see above).
+-.bt
+-\fB&ls\fI\|N\fR       \fIN\(eq\^\fR1  previous        E       \fILine\fR spacing
+-set to \fI\(+-N\fR.
+-\fIN\(mi\fR1 \fIV\fR\^s \fI(blank lines)\fR are
+-appended to each output text line.
+-Appended blank lines are omitted, if the text or previous appended blank line reached a trap position.
+-.bt
+-\fB&sp\fI|N\fR        -       \fIN\fR\(eq1\fIV\fR     B,\fBv\fR       Space vertically in \fIeither\fR direction.
+-If \fIN\fR is negative, the motion is \fIbackward\fR (upward)
+-and is limited to the distance to the top of the page.
+-Forward (downward) motion is truncated to the distance to the
+-nearest trap.
+-If the no-space mode is on,
+-no spacing occurs (see \fBns\fR, and \fBrs\fR below).
+-.bt
+-\fB&sv\fI|N\fR        -       \fIN\(eq\fR1\fIV\fR     \fBv\fR Save a contiguous vertical block of size \fIN\fR.
+-If the distance to the next trap is greater
+-than \fIN\fR, \fIN\fR vertical space is output.
+-No-space mode has \fIno\fR effect.
+-If this distance is less than \fIN\fR,
+-no vertical space is immediately output,
+-but \fIN\fR is remembered for later output (see \fBos\fR).
+-Subsequent \fBsv\fR requests will overwrite any still remembered \fIN\fR.
+-.bt
+-\fB&os\fR     -       -       -       Output saved vertical space.
+-No-space mode has \fIno\fR effect.
+-Used to finally output a block of vertical space requested
+-by an earlier \fBsv\fR request.
+-.bt
+-\fB&ns\fR     space   -       D       No-space mode turned on.
+-When on, the no-space mode inhibits \fBsp\fR requests and
+-\fBbp\fR requests \fIwithout\fR a next page number.
+-The no-space mode is turned off when a line of
+-output occurs, or with \fBrs\fR.
+-.bt
+-\fB&rs\fR     space   -       D       Restore spacing.
+-The no-space mode is turned off.
+-.bt
+-Blank|text|line.      -       B       Causes a break and
+-output of a blank line exactly like \fBsp|1\fR.
+//GO.SYSIN DD m1
+echo m2
+sed 's/.//' >m2 <<'//GO.SYSIN DD m2'
+-.tr |
+-.rm mx
+-.br
+-.mh
+-Line Length and Indenting
+-.pg
+-The maximum line length for fill mode may be set with \fBll\fR.
+-The indent may be set with \fBin\fR;
+-an indent applicable to \fIonly\fR the \fInext\fR output line may be set with \fBti\fR.
+-The line length includes indent space but \fInot\fR
+-page offset space.
+-The line-length minus the indent is the basis for centering with \fBce\fR.
+-The effect of \fBll\fR, \fBin\fR, or \fBti\fR
+-is delayed, if a partially collected line exists,
+-until after that line is output.
+-In fill mode the length of text on an output line is less than or equal to
+-the line length minus the indent.
+-The current line length and indent are available in registers \fB.l\fR and \fB.i\fR respectively.
+-The length of \fIthree-part titles\fR produced by \fBtl\fR
+-(see \(sc14) is \fIindependently\fR set by \fBlt\fR.
+-.h1
+-.bt
+-\fB&ll\fI|\(+-N\fR    6.5\|in previous        E,\fBm\fR       Line length is set to \(+-\fIN\fR.
+-In \*(TR the maximum (line-length)+(page-offset) is about 7.54 inches.
+-.bt
+-\fB&in\fI|\(+-N\fR    \fIN\(eq\^\fR0  previous        B,E,\fBm\fR     Indent is set to \fI\(+-N\fR.
+-The indent is prepended to each output line.
+-.bt
+-\fB&ti\fI|\(+-N\fR    -       ignored B,E,\fBm\fR     Temporary indent.
+-The \fInext\fR output text line will be indented a distance \fI\(+-N\fR
+-with respect to the current indent.
+-The resulting total indent may not be negative.
+-The current indent is not changed.
+-.mh
+-Macros, Strings, Diversion, and Position Traps
+-.sc
+-Macros and strings.
+-A \fImacro\fR is a named set of arbitrary \fIlines\fR that may be invoked by name or
+-with a \fItrap\fR.
+-A \fIstring\fR is a named string of \fIcharacters\fR,
+-\fInot\fR including a newline character,
+-that may be interpolated by name at any point.
+-Request, macro, and string names share the \fIsame\fR name list.
+-Macro and string names
+-may be one or two characters long and may usurp previously defined
+-request, macro, or string names.
+-Any of these entities may be renamed with \fBrn\fR
+-or removed with \fBrm\fR.
+-Macros are created by \fBde\fR and \fBdi\fR, and appended to by \fBam\fR and \fBda\fR;
+-\fBdi\fR and \fBda\fR cause normal output to be stored in a macro.
+-Strings are created by \fBds\fR and appended to by \fBas\fR.
+-A macro is invoked in the same way as a request;
+-a control line beginning \fB.\fIxx\fR will interpolate the contents of macro \fIxx\fR.
+-The remainder of the line may contain up to nine \fIarguments\fR.
+-The strings \fIx\fR and \fIxx\fR are interpolated at any desired point with
+-\fB\e\(**\fIx\fR and \fB\e\(**(\fIxx\fR respectively.
+-String references and macro invocations may be nested.
+-.sc
+-Copy mode input interpretation.
+-During the definition and extension
+-of strings and macros (not by diversion)
+-the input is read in \fIcopy mode\fR.
+-The input is copied without interpretation
+-\fIexcept\fR that:
+-.x1
+-.ds + \v'-.1m'\s-4\(bu\s+4\v'+.1m'
+-\*+ The contents of number registers indicated by \fB\en\fR are interpolated.
+-\*+ Strings indicated by \fB\e\(**\fR are interpolated.
+-\*+ Arguments indicated by \fB\e$\fR are interpolated.
+-\*+ Concealed newlines indicated by \fB\e\fR(newline) are eliminated.
+-\*+ Comments indicated by \fB\e"\fR are eliminated.
+-\*+ \fB\et\fR and \fB\ea\fR are interpreted as \s-1ASCII\s+1 horizontal tab and \s-1SOH\s+1 respectively (\(sc9).
+-\*+ \fB\e\e\fR is interpreted as \fB\e\fR.
+-\*+ \fB\e.\fR is interpreted as "\fB.\fR".
+-.x2
+-These interpretations can be suppressed by
+-prepending
+-a \fB\e\fR.
+-For example, since \fB\e\e\fR maps into a \fB\e\fR, \fB\e\en\fR will copy as \fB\en\fR which
+-will be interpreted as a number register indicator when the
+-macro or string is reread.
+-.sc
+-Arguments.
+-When a macro is invoked by name, the remainder of the line is
+-taken to contain up to nine arguments.
+-The argument separator is the space character, and arguments
+-may be surrounded by double-quotes to permit imbedded space characters.
+-Pairs of double-quotes may be imbedded in double-quoted arguments to
+-represent a single double-quote.
+-If the desired arguments won't fit on a line,
+-a concealed newline may be used to continue on the next line.
+-.pg
+-When a macro is invoked the \fIinput level\fR is \fIpushed down\fR and
+-any arguments available at the previous level become unavailable
+-until the macro is completely read and the previous level is restored.
+-A macro's own arguments can be interpolated at \fIany\fR point
+-within the macro with \fB\e$\fIN\fR, which interpolates the \fIN\fR\^th
+-argument
+-(1\(<=\fIN\fR\^\(<=9).
+-If an invoked argument doesn't exist,
+-a null string results.
+-For example, the macro \fIxx\fR may be defined by
+-.x1
+-.ftB
+-.ta .75i
+-&de xx        \e"begin definition
+-Today is \e\e$1 the \e\e$2.
+-&.    \e"end definition
+-.ftR
+-.x2
+-and called by
+-.x1
+-.ftB
+-&xx Monday 14th
+-.ftR
+-.x2
+-to produce the text
+-.x1
+-.ftB
+-Today is Monday the 14th.
+-.ftR
+-.x2
+-Note that the \fB\e$\fR
+-was concealed in the definition with a prepended \fB\e\fR.
+-The number of currently available
+-arguments is in the \fB.$\fR register.
+-.pg
+-No arguments are available at the top (non-macro) level
+-in this implementation.
+-Because string referencing is implemented
+-as a input-level push down,
+-no arguments are available from \fIwithin\fR a string.
+-No arguments are available within a trap-invoked macro.
+-.pg
+-Arguments are copied in \fIcopy mode\fR onto a stack
+-where they are available for reference.
+-The mechanism does not allow an argument to contain
+-a direct reference to a \fIlong\fR string
+-(interpolated at copy time) and it is advisable to
+-conceal string references (with an extra \fB\e\fR\|)
+-to delay interpolation until argument reference time.
+-.sc
+-Diversions.
+-Processed output may be diverted into a macro for purposes
+-such as footnote processing (see Tutorial \(scT5)
+-or determining the horizontal and vertical size of some text for
+-conditional changing of pages or columns.
+-A single diversion trap may be set at a specified vertical position.
+-The number registers \fBdn\fR and \fBdl\fR respectively contain the
+-vertical and horizontal size of the most
+-recently ended diversion.
+-Processed text that is diverted into a macro
+-retains the vertical size of each of its lines when reread
+-in \fInofill\fR mode
+-regardless of the current \fIV\fR.
+-Constant-spaced (\fBcs\fR) or emboldened (\fBbd\fR) text that is diverted
+-can be reread correctly only if these modes are again or still in effect
+-at reread time.
+-One way to do this is to imbed in the diversion the appropriate
+-\fBcs\fR or \fBbd\fR requests with the \fItransparent\fR
+-mechanism described in \(sc10.6.
+-.pg
+-Diversions may be nested
+-and certain parameters and registers
+-are associated
+-with the current diversion level
+-(the top non-diversion level may be thought of as the
+-0th diversion level).
+-These are the diversion trap and associated macro,
+-no-space mode,
+-the internally-saved marked place (see \fBmk\fR and \fBrt\fR),
+-the current vertical place (\fB.d\fR register),
+-the current high-water text base-line (\fB.h\fR register),
+-and the current diversion name (\fB.z\fR register).
+-.sc
+-Traps.
+-Three types of trap mechanisms are available\(empage traps, a diversion trap, and
+-an input-line-count trap.
+-Macro-invocation traps may be planted using \fBwh\fR at any page position including the top.
+-This trap position may be changed using \fBch\fR.
+-Trap positions at or below the bottom of the page
+-have no effect unless or until
+-moved to within the page or rendered effective by an increase in page length.
+-Two traps may be planted at the \fIsame\fR position only by first planting them at different
+-positions and then moving one of the traps;
+-the first planted trap will conceal the second unless and until the first one is moved
+-(see Tutorial Examples \(scT5).
+-If the first one is moved back, it again conceals the second trap.
+-The macro associated with a page trap is automatically
+-invoked when a line of text is output whose vertical size \fIreaches\fR
+-or \fIsweeps past\fR the trap position.
+-Reaching the bottom of a page springs the top-of-page trap, if any,
+-provided there is a next page.
+-The distance to the next trap position is available in the \fB.t\fR register;
+-if there are no traps between the current position and the bottom of the page,
+-the distance returned is the distance to the page bottom.
+-.pg
+-A macro-invocation trap effective in the current diversion may be planted using \fBdt\fR.
+-The \fB.t\fR register works in a diversion; if there is no subsequent trap a \fIlarge\fR
+-distance is returned.
+-For a description of input-line-count traps, see \fBit\fR below.
+-.h1
+-.bt
+-\fB&de\fI|xx|yy\fR    -       \fI.yy=\fB..\fR -       Define or redefine the macro \fIxx\fR.
+-The contents of the macro begin on the next input line.
+-Input lines are copied in \fIcopy mode\fR until the definition is terminated by a
+-line beginning with \fB.\fIyy\fR,
+-whereupon the macro \fIyy\fR is called.
+-In the absence of \fIyy\fR, the definition
+-is terminated by a
+-line beginning with "\fB..\fR".
+-A macro may contain \fBde\fR requests
+-provided the terminating macros differ
+-or the contained definition terminator is concealed.
+-\&"\fB..\fR" can be concealed as
+-\fB\e\e..\fR which will copy as \fB\e..\fR and be reread as "\fB..\fR".
+-.bt
+-\fB&am\fI|xx|yy\fR    -       \fI.yy=\fB..\fR -       Append to macro (append version of \fBde\fR).
+-.bt
+-\fB&ds\fI|xx|string\fR        -       ignored -       Define a string
+-\fIxx\fR containing \fIstring\fR.
+-Any initial double-quote in \fIstring\fR is stripped off to permit
+-initial blanks.
+-.bt
+-\fB&as\fI|xx|string\fR        -       ignored -       Append
+-\fIstring\fR to string \fIxx\fR
+-(append version of \fBds\fR).
+-.bt
+-\fB&rm\fI|xx\fR       -       ignored -       Remove
+-request, macro, or string.
+-The name \fIxx\fR is removed from the name list and
+-any related storage space is freed.
+-Subsequent references will have no effect.
+-.bt
+-\fB&rn\fI|xx|yy\fR    -       ignored -       Rename request, macro, or string
+-\fIxx\fR to \fIyy\fR.
+-If \fIyy\fR exists, it is first removed.
+-.bt
+-\fB&di|\fIxx\fR       -       end     D       Divert output to macro \fIxx\fR.
+-Normal text processing occurs during diversion
+-except that page offsetting is not done.
+-The diversion ends when the request \fBdi\fR or \fBda\fR is encountered without an argument;
+-extraneous
+-requests of this type should not appear when nested diversions are being used.
+-.bt
+-\fB&da|\fIxx\fR       -       end     D       Divert, appending to \fIxx\fR
+-(append version of \fBdi\fR).
+-.bt
+-\fB&wh\fI|N|xx\fR     -       -       \fBv\fR Install
+-a trap to invoke \fIxx\fR at page position \fIN;\fR
+-a \fInegative N\fR will be interpreted with respect to the
+-page \fIbottom\fR.
+-Any macro previously planted at \fIN\fR is replaced by \fIxx\fR.
+-A zero \fIN\fR refers to the \fItop\fR of a page.
+-In the absence of \fIxx\fR, the first found trap at \fIN\fR, if any, is removed.
+-.bt
+-\fB&ch\fI|xx|N\fR     -       -       \fBv\fR Change
+-the trap position for macro \fIxx\fR to be \fIN\fR.
+-In the absence of \fIN\fR, the trap, if any, is removed.
+-.bt
+-\fB&dt\fI|N|xx\fR     -       off     D,\fBv\fR       Install a diversion trap
+-at position \fIN\fR in the \fIcurrent\fR diversion to invoke
+-macro \fIxx\fR.
+-Another \fBdt\fR will redefine the diversion trap.
+-If no arguments are given, the diversion trap is removed.
+-.bt
+-\fB&it\fI|N|xx\fR     -       off     E       Set an input-line-count trap
+-to invoke the macro \fIxx\fR after \fIN\fR lines of \fItext\fR input
+-have been read
+-(control or request lines don't count).
+-The text may be in-line text or
+-text interpolated by inline or trap-invoked macros.
+-.bt
+-\fB&em\fI|xx\fR       none    none    -       The
+-macro \fIxx\fR will be invoked
+-when all input has ended.
+-The effect is the same as if the contents of \fIxx\fR had been at the end
+-of the last file processed.
+-.mh
+-Number Registers
+-.pg
+-A variety of parameters are available to the user as
+-predefined, named \fInumber registers\fR (see Summary and Index, page 7).
+-In addition, the user may define his own named registers.
+-Register names are one or two characters long and \fIdo not\fR conflict
+-with request, macro, or string names.
+-Except for certain predefined read-only registers,
+-a number register can be read, written, automatically
+-incremented or decremented, and interpolated
+-into the input in a variety of formats.
+-One common use of user-defined registers is to
+-automatically number sections, paragraphs, lines, etc.
+-A number register may be used any time numerical input is expected or desired
+-and may be used in numerical \fIexpressions\fR (\(sc1.4).
+-.pg
+-Number registers are created and modified using \fBnr\fR, which
+-specifies the name, numerical value, and the auto-increment size.
+-Registers are also modified, if accessed
+-with an auto-incrementing sequence.
+-If the registers \fIx\fR and \fIxx\fR both contain
+-\fIN\fR and have the auto-increment size \fIM\fR,
+-the following access sequences have the effect shown:
+-.TS
+-center box;
+-c2|c2|c
+-c2|c2|c2
+-l2|c2|c2
+-l2|c2|c2
+-l2|l2|c2.
+-      Effect on       Value
+-Sequence      Register        Interpolated
+-_
+-\fB\en\fIx\fR none    \fIN\fR
+-\fB\en(\fIxx\fR       none    \fIN\fR
+-\fB\en+\fIx\fR        \fIx\fR incremented by \fIM\fR  \fIN+M\fR
+-\fB\en\-\fIx\fR       \fIx\fR decremented by \fIM\fR  \fIN\-M\fR
+-\fB\en+(\fIxx\fR      \fIxx\fR incremented by \fIM\fR \fIN+M\fR
+-\fB\en\-(\fIxx\fR     \fIxx\fR decremented by \fIM\fR \fIN\-M\fR
+-.TE
+-When interpolated, a number register is converted to
+-decimal (default),
+-decimal with leading zeros,
+-lower-case Roman,
+-upper-case Roman,
+-lower-case sequential alphabetic,
+-or
+-upper-case sequential alphabetic
+-according to the format specified by \fBaf\fR.
+-.h1
+-.bt
+-\fB&nr\fI|R|\(+-N|M\fR        -       \fBu\fR \
+-The number register \fIR\fR is assigned the value \fI\(+-N\fR
+-with respect to the previous value, if any.
+-The increment for auto-incrementing is set to \fIM\fR.
+-.bt
+-\fB&af\fI|R|c\fR      arabic  -       -       Assign format \fIc\fR to register \fIR\fR.
+-The available formats are:
+-.TS
+-center box;
+-c2|c
+-c2|c
+-c2|l.
+-      Numbering
+-Format        Sequence
+-_
+-\fB1\fR       0,1,2,3,4,5,...
+-\fB001\fR     000,001,002,003,004,005,...
+-\fBi\fR       0,i,ii,iii,iv,v,...
+-\fBI\fR       0,I,II,III,IV,V,...
+-\fBa\fR       0,a,b,c,...,z,aa,ab,...,zz,aaa,...
+-\fBA\fR       0,A,B,C,...,Z,AA,AB,...,ZZ,AAA,...
+-.TE
+-An arabic format having \fIN\fR digits
+-specifies a field width of \fIN\fR digits (example 2 above).
+-The read-only registers and the \fIwidth\fR function (\(sc11.2)
+-are always arabic.
+-.bt
+-\fB&rr\fI|R\fR        -       ignored -       Remove register \fIR\fR.
+-If many registers are being created dynamically, it
+-may become necessary to remove no longer used registers
+-to recapture internal storage space for newer registers.
+//GO.SYSIN DD m2
+echo m3
+sed 's/.//' >m3 <<'//GO.SYSIN DD m3'
+-.tr |
+-.rm mx
+-.mh
+-Tabs, Leaders, and Fields
+-.sc
+-Tabs and leaders.
+-The \s-1ASCII\s+1 horizontal tab character and the \s-1ASCII\s+1
+-\s-1SOH\s+1 (hereafter known as the \fIleader\fR character)
+-can both be used to generate either horizontal motion or
+-a string of repeated characters.
+-The length of the generated entity is governed
+-by internal \fItab stops\fR specifiable
+-with \fBta\fR.
+-The default difference is that tabs generate motion and leaders generate
+-a string of periods;
+-\fBtc\fR and \fBlc\fR
+-offer the choice of repeated character or motion.
+-There are three types of internal tab stops\(em\
+-\fIleft\fR adjusting, \fIright\fR adjusting,
+-and \fIcentering\fR.
+-In the following table:
+-\fID\fR is the distance from the current position on the \fIinput\fR line
+-(where a tab or leader was found)
+-to the next tab stop;
+-\fInext-string\fR consists
+-of the input characters following the tab (or leader) up to the next tab (or leader) or end of line;
+-and
+-\fIW\fR is the width of \fInext-string\fR.
+-.TS
+-center box;
+-c2|c2|c
+-c2|c2|c
+-c2|c2|l.
+-Tab   Length of motion or     Location of
+-type  repeated characters     \fInext-string\fR
+-_
+-Left  \fID\fR Following \fID\fR
+-Right \fID\-W\fR      Right adjusted within \fID\fR
+-Centered      \fID\-W\(sl\fR2 Centered on right end of \fID\fR
+-.TE
+-The length of generated motion is allowed to be negative, but
+-that of a repeated character string cannot be.
+-Repeated character strings contain an integer number of characters, and
+-any residual distance is prepended as motion.
+-Tabs or leaders found after the last tab stop are ignored, but may be used
+-as \fInext-string\fR terminators.
+-.pg
+-Tabs and leaders are not interpreted in \fIcopy mode\fR.
+-\fB\et\fR and \fB\ea\fR always generate a non-interpreted
+-tab and leader respectively, and
+-are equivalent to actual tabs and leaders in \fIcopy mode\fR.
+-.sc
+-Fields.
+-A \fIfield\fR is contained between
+-a \fIpair\fR of \fIfield delimiter\fR characters,
+-and consists of sub-strings
+-separated by \fIpadding\fR indicator characters.
+-The field length is the distance on the
+-\fIinput\fR line from the position where the field begins to the next tab stop.
+-The difference between the total length of all the sub-strings
+-and the field length is incorporated as horizontal
+-padding space that is divided among the indicated
+-padding places.
+-The incorporated padding is allowed to be negative.
+-For example,
+-if the field delimiter is \fB#\fR and the padding indicator is \fB^\fR,
+-\fB#^\fIxxx\fB^\fIright\|\fB#\fR
+-specifies a right-adjusted string with the string \fIxxx\fR centered
+-in the remaining space.
+-.h1
+-.bt
+-\fB&ta\fI|Nt|...\fR   0.8;|0.5in      none    E,\fBm\fR       \
+-Set tab stops and types.
+-\fIt=\fBR\fR, right adjusting;
+-\fIt=\fBC\fR, centering;
+-\fIt\fR absent, left adjusting.
+-\*(TR tab stops are preset every 0.5in.;
+-\*(NR every 0.8in.
+-The stop values are separated by spaces, and
+-a value preceded by \fB+\fR
+-is treated as an increment to the previous stop value.
+-.bt
+-\fB&tc\fI|c\fR        none    none    E       \
+-The tab repetition character becomes \fIc\fR,
+-or is removed specifying motion.
+-.bt
+-\fB&lc\fI|c\fR        \fB.\fR none    E       \
+-The leader repetition character becomes \fIc\fR,
+-or is removed specifying motion.
+-.bt
+-\fB&fc\fI|a|b\fR      off     off     -       \
+-The field delimiter is set to \fIa\fR;
+-the padding indicator is set to the \fIspace\fR character or to
+-\fIb\fR, if given.
+-In the absence of arguments the field mechanism is turned off.
+-.mh
+-Input and Output Conventions and Character Translations
+-.sc
+-Input character translations.
+-Ways of inputting the graphic character set were
+-discussed in \(sc2.1.
+-The \s-1ASCII\s+1 control characters horizontal tab (\(sc9.1),
+-\s-1SOH\s+1 (\(sc9.1), and backspace (\(sc10.3) are discussed elsewhere.
+-The newline delimits input lines.
+-In addition,
+-\s-1STX\s+1, \s-1ETX\s+1, \s-1ENQ\s+1, \s-1ACK\s+1, and \s-1BEL\s+1
+-are accepted,
+-and may be used as delimiters or translated into a graphic with \fBtr\fR (\(sc10.5).
+-\fIAll\fR others are ignored.
+-.pg
+-The \fIescape\fR character \fB\e\fR
+-introduces \fIescape sequences\fR\(em\
+-causes the following character to mean
+-another character, or to indicate
+-some function.
+-A complete list of such sequences is given in the Summary and Index on page 6.
+-\fB\e\fR
+-should not be confused with the \s-1ASCII\s+1 control character \s-1ESC\s+1 of the
+-same name.
+-The escape character \fB\e\fR can be input with the sequence \fB\e\e\fR.
+-The escape character can be changed with \fBec\fR,
+-and all that has been said about the default \fB\e\fR becomes true
+-for the new escape character.
+-\fB\ee\fR can be used to print whatever the current escape character is.
+-If necessary or convenient, the escape mechanism may be turned off with \fBeo\fR,
+-and restored with \fBec\fR.
+-.h1
+-.bt
+-\fB&ec\fI|c\fR        \fB\e\fR        \fB\e\fR        -       \
+-Set escape character to \fB\e\fR, or to \fIc\fR, if given.
+-.bt
+-\fB&eo\fR     on      -       -       Turn escape mechanism off.
+-.sc
+-Ligatures.
+-.lg0
+-Five ligatures are available
+-in the current \*(TR character set \(em
+-\fB\(fi\fR, \fB\(fl\fR, \fB\(ff\fR, \fB\(Fi\fR, and \fB\(Fl\fR.
+-They may be input (even in \*(NR) by
+-\fB\e(fi\fR, \fB\e(fl\fR, \fB\e(ff\fR, \fB\e(Fi\fR, and \fB\e(Fl\fR respectively.
+-.lg
+-The ligature mode is normally on in \*(TR, and \fIautomatically\fR invokes 
+-ligatures during input.
+-.h1
+-.bt
+-\fB&lg\fI|N\fR        off;|on on      -       Ligature mode
+-is turned on if \fIN\fR is absent or non-zero,
+-and turned off if \fIN\(eq\^\fR0.
+-If \fIN\fR\(eq\^2, only the two-character ligatures are automatically invoked.
+-Ligature mode is inhibited for
+-request, macro, string, register, or file names,
+-and in \fIcopy mode\fR.
+-No effect in \*(NR.
+-.sc
+-Backspacing, underlining, overstriking, etc.
+-Unless in \fIcopy mode\fR, the \s-1ASCII\s+1 backspace character is replaced
+-by a backward horizontal motion having the width of the
+-space character.
+-Underlining as a form of line-drawing is discussed in \(sc12.4.
+-A generalized overstriking function is described in \(sc12.1.
+-.pg
+-\*(NR automatically underlines
+-characters in the \fIunderline\fR font,
+-specifiable with \fBuf\fR,
+-normally that on font position 2 (normally Times Italic, see \(sc2.2).
+-In addition to \fBft\fR and \fB\ef\fIF\fR,
+-the underline font may be selected by \fBul\fR and \fBcu\fR.
+-Underlining is restricted to an output-device-dependent
+-subset of \fIreasonable\fR characters.
+-.h1
+-.bt
+-\fB&ul\fI|N\fR        off     \fIN\(eq\fR1    E       \
+-Underline in \*(NR (italicize in \*(TR) the next \fIN\fR
+-input text lines.
+-Actually, switch to \fIunderline\fR font, saving the
+-current font for later restoration;
+-\fIother\fR font changes within the span of a \fBul\fR
+-will take effect,
+-but the restoration will undo the last change.
+-Output generated by \fBtl\fR (\(sc14) \fIis\fR affected by the
+-font change, but does \fInot\fR decrement \fIN\fR.
+-If \fIN\fR\^>\^1, there is the risk that
+-a trap interpolated macro may provide text
+-lines within the span;
+-environment switching can prevent this.
+-.bt
+-\fB&cu\fI|N\fR        off     \fIN\(eq\fR1    E       \
+-A variant of \fBul\fR that causes \fIevery\fR character to be underlined in \*(NR.
+-Identical to \fBul\fR in \*(TR.
+-.bt
+-\fB&uf\fI|F\fR        Italic  Italic  -       \
+-Underline font set to \fIF\fR.
+-In \*(NR,
+-\fIF\fR may \fInot\fR be on position 1 (initially Times Roman).
+-.sc
+-Control characters.
+-Both the control character \fB.\fR and the \fIno-break\fR
+-control character \fB\'\fR may be changed, if desired.
+-Such a change must be compatible with the design
+-of any macros used in the span of the change,
+-and
+-particularly of any trap-invoked macros.
+-.h1
+-.bt
+-\fB&cc\fI|c\fR        \fB.\fR \fB.\fR E       \
+-The basic control character is set to \fIc\fR,
+-or reset to "\fB.\fR".
+-.bt
+-\fB&c2\fI|c\fR        \fB\'   \'\fR   E       The \fInobreak\fR control character is set
+-to \fIc\fR, or reset to "\fB\'\fR".
+-.sc
+-Output translation.
+-One character can be made a stand-in for another character using \fBtr\fR.
+-All text processing (e. g. character comparisons) takes place
+-with the input (stand-in) character which appears to have the width of the final
+-character.
+-The graphic translation occurs at the moment of output
+-(including diversion).
+-.h1
+-.bt
+-\fB&tr\fI|abcd....\fR none    -       O       Translate \
+-\fIa\fR into \fIb\fR, \fIc\fR into \fId\fR, etc.
+-If an odd number of characters is given,
+-the last one will be mapped into the space character.
+-To be consistent, a particular translation
+-must stay in effect from \fIinput\fR to \fIoutput\fR time.
+-.sc
+-Transparent throughput.
+-An input line beginning with a \fB\e!\fR is read in \fIcopy mode\fR and \fItransparently\fR output
+-(without the initial \fB\e!\fR);
+-the text processor is otherwise unaware of the line's presence.
+-This mechanism may be used to pass control information to a post-processor
+-or to imbed control lines in a macro created by a diversion.
+-.sc
+-Comments and concealed newlines.
+-An uncomfortably long input line that must stay
+-one line (e. g. a string definition, or nofilled text)
+-can be split into many physical lines by ending all but
+-the last one with the escape \fB\e\fR.
+-The sequence \fB\e\fR(newline) is \fIalways\fR ignored\(em\
+-except in a comment.
+-Comments may be imbedded at the \fIend\fR of any line by
+-prefacing them with \fB\e"\fR.
+-The newline at the end of a comment cannot be concealed.
+-A line beginning with \fB\e"\fR will appear as a blank line and
+-behave like \fB.sp|1\fR;
+-a comment can be on a line by itself by beginning the line with \fB.\e"\fR.
+-.mh
+-Local Horizontal and Vertical Motions, and the Width Function
+-.sc
+-Local Motions.
+-The functions \fB\ev\'\fIN\fB\|\'\fR and
+-\fB\eh\'\fIN\fB\|\'\fR
+-can be used for \fIlocal\fR vertical and horizontal motion respectively.
+-The distance \fIN\fR may be negative; the \fIpositive\fR directions
+-are \fIrightward\fR and \fIdownward\fR.
+-A \fIlocal\fR motion is one contained \fIwithin\fR a line.
+-To avoid unexpected vertical dislocations, it is necessary that
+-the \fInet\fR vertical local motion within a word in filled text
+-and otherwise within a line balance to zero.
+-The above and certain other escape sequences providing local motion are
+-summarized in the following table.
+-.tr ||
+-.ds X \0\0\0
+-.TS
+-center box;
+-c2|cs2||c2|cs2
+-c1|c2c2||c2|c2c2.
+-Vertical      Effect in       Horizontal      Effect in
+-Local Motion  \*(TR   \*(NR   Local Motion    \*(TR   \*(NR
+-_
+-.sp.4
+-.TC
+-l2|ls2||l2|ls2.
+-\fB\*X\ev\'\fIN\|\^\fB\'\fR   Move distance \fIN\fR   \
+-\fB\*X\eh\'\fIN\|\^\fB\'\fR   Move distance \fIN\fR
+-.TC
+-_2|_2_2||l2|ls2.
+-x     x       x       \fB\*X\e\fR(space)      Unpaddable space-size space
+-.TC
+-l2|l2|l2||l2|ls2.
+-\fB\*X\eu\fR  \(12 em up      \(12 line up    \fB\*X\e0\fR    Digit-size space
+-.TC
+-l2|l2|l2||_2|_2_2.
+-\fB\*X\ed\fR  \(12 em down    \(12 line down  x       x       x
+-.TC
+-l2|l2|l2||l2|l2|l2.
+-\fB\*X\er\fR  1 em up 1 line up       \fB\*X\e\||\fR  1\(sl6 em space ignored
+-                      \fB\*X\e^\fR    1\(sl12 em space        ignored
+-.sp.4
+-.TE
+-.rm X
+-.tr |
+-As an example,
+-\fBE\s-2\v'-.4m'2\v'.4m'\s+2\fR
+-could be generated by the sequence
+-\fBE\es\-2\ev\'\-0.4m\'2\ev\'0.4m\'\es+2\fR;
+-it should be noted in this example that
+-the 0.4|em vertical motions are at the smaller size.
+-.sc
+-Width Function.
+-The \fIwidth\fR function \fB\ew\'\fIstring\fB\|\'\fR
+-generates the numerical width of \fIstring\fR (in basic units).
+-Size and font changes may be safely imbedded in \fIstring\fR,
+-and will not affect the current environment.
+-For example,
+-\&\fB.ti|\-\\w\'1.|\'u\fR could be used to
+-temporarily indent leftward a distance equal to the
+-size of the string "\fB1.|\fR".
+-.pg
+-The width function also sets three number registers.
+-The registers \fBst\fR and \fBsb\fR are set respectively to the highest and
+-lowest extent of \fIstring\fR relative to the baseline;
+-then, for example,
+-the total \fIheight\fR of the string is \fB\en(stu\-\en(sbu\fR.
+-In \*(TR the number register \fBct\fR is set to a value
+-between 0|and|3:
+-0 means that all of the characters in \fIstring\fR were short lower
+-case characters without descenders (like \fBe\fR);
+-1 means that at least one character has a descender (like \fBy\fR);
+-2 means that at least one character is tall (like \fBH\fR);
+-and 3 means that both tall characters and characters with
+-descenders are present.
+-.sc
+-Mark horizontal place.
+-The escape sequence \fB\ek\fIx\fR will cause the \fIcurrent\fR horizontal
+-position in the \fIinput line\fR to be stored in register \fIx\fR.
+-As an example,
+-the construction \fB\ekx\fIword\|\fB\eh\'\|~\|\enxu+2u\'\fIword\fB\fR
+-will embolden \fIword\fR by backing up to almost its beginning and overprinting it,
+-resulting in \kz\fIword\fR\h'|\nzu+2u'\fIword\fR.
+-.mh
+-Overstrike, Bracket, Line-drawing, and Zero-width Functions
+-.sc
+-Overstriking.
+-Automatically centered overstriking of up to nine characters
+-is provided by the \fIoverstrike\fR function
+-\fB\eo\'\fIstring\fB\|\'\fR.
+-The characters in \fIstring\fR overprinted with centers aligned; the total width
+-is that of the widest character.
+-\fIstring\fR should \fInot\fR contain local vertical motion.
+-As examples,
+-\fB\eo\'e\e\'\'\fR produces \fB\o'e\''\fR, and
+-\fB\eo\'\e(mo\e(sl\'\fR produces \fB\o'\(mo\(sl'\fR.
+-.sc
+-Zero-width characters.
+-The function \fB\ez\fIc\fR will output \fIc\fR without spacing over
+-it, and can be used to produce left-aligned overstruck
+-combinations.
+-As examples,
+-\fB\ez\e(ci\e(pl\fR will produce \fB\z\(ci\(pl\fR, and
+-\fB\e(br\ez\e(rn\e(ul\e(br\fR will produce the smallest possible
+-constructed box \fB\(br\z\(rn\(ul\(br\fR\|.
+-.sc
+-Large Brackets.
+-The Special Mathematical Font contains a number of bracket construction pieces
+-(\|\|\(lt\|\|\(lb\|\|\(rt\|\|\(rb\|\|\(lk\|\|\(rk\|\|\(bv\|\|\(lf\|\|\(rf\|\|\(lc\|\|\(rc\|\|)
+-that can be combined into various bracket styles.
+-The function \fB\eb\'\fIstring\fB\|\'\fR may be used to pile
+-up vertically the characters in \fIstring\fR
+-(the first character on top and the last at the bottom);
+-the characters are vertically separated by 1|em and the total
+-pile is centered 1\(sl2\|em above the current baseline
+-(\(12 line in \*(NR).
+-For example,
+-\fB\eb\'\|\e(lc\e(lf\|\'E\e\|~\|\eb\'\|\e(rc\e(rf\|\'\|\ex\'\|\-0.5m\'\|\ex\'0.5m\'\|\fR
+-produces
+-\x'-.5m'\x'.5m'\fB\b'\(lc\(lf'E\|\b'\(rc\(rf'\fR.
+-.sc
+-Line drawing.
+-.tr &&
+-The function \fB\e\|l\|\'\fINc\fB\|\'\fR will draw a string of repeated \fIc\fR\|'s towards the right for a distance \fIN\fR.
+-(\|\fB\el\fR is \fB\e\fR(lower case L).
+-If \fIc\fR looks like a continuation of
+-an expression for \fIN\fR, it may insulated from \fIN\fR with a \fB\e&\fR.
+-If \fIc\fR is not specified, the \fB\(ru\fR (baseline rule) is used
+-(underline character in \*(NR).
+-If \fIN\fR is negative, a backward horizontal motion
+-of size \fIN\fR is made \fIbefore\fR drawing the string.
+-Any space resulting from \fIN\fR\|\(sl(size of \fIc\fR) having a remainder is put at the beginning (left end)
+-of the string.
+-In the case of characters
+-that are designed to be connected such as
+-baseline-rule\ \fB\(ru\fR\|,
+-underrule\ \fB\(ul\fR\|,
+-and
+-root-en\ \fB\(rn\fR\|,
+-the remainder space is covered by over-lapping.
+-If \fIN\fR is \fIless\fR than the width of \fIc\fR,
+-a single \fIc\fR is centered on a distance \fIN\fR.
+-As an example, a macro to underscore a string can be written
+-.br
+-.tr &.
+-.x1
+-.ftB
+-.ne 2.1
+-&de us
+-\e\e$1\e\|l\|\'\|~\|0\e(ul\'
+-&&
+-.ftR
+-.x2
+-.ne2.1
+-.de xu
+-\\$1\l'|0\(ul'
+-..
+-or one to draw a box around a string
+-.x1
+-.ftB
+-&de bx
+-\e(br\e\|~\|\e\e$1\e\|~\|\e(br\e\|l\|\'\|~\|0\e(rn\'\e\|l\|\'\|~\|0\e(ul\'
+-&&
+-.ftR
+-.x2
+-.de bx
+-\(br\|\\$1\|\(br\l'|0\(rn'\l'|0\(ul'
+-..
+-such that
+-.x1
+-.ftB
+-&ul "underlined words"
+-.ftR
+-.x2
+-and
+-.x1
+-.ftB
+-&bx "words in a box"
+-.ftR
+-.x2
+-yield
+-.xu "underlined words"
+-and
+-.bx "words in a box"
+-\h'-\w'.'u'.
+-.pg
+-The function \fB\eL\'\|\fINc\fB\|\'\fR will draw a vertical line consisting
+-of the (optional) character \fIc\fR stacked vertically apart 1\|em
+-(1 line in \*(NR),
+-with the first two characters overlapped,
+-if necessary, to form a continuous line.
+-The default character is the \fIbox rule\fR |\(br| (\fB\|\e(br\fR);
+-the other suitable character is the \fIbold vertical\fR \|\(bv\| (\fB\|\e(bv\fR).
+-The line is begun without any initial motion relative to the
+-current base line.
+-A positive \fIN\fR specifies a line drawn downward and
+-a negative \fIN\fR specifies a line drawn upward.
+-After the line is drawn \fIno\fR compensating
+-motions are made;
+-the instantaneous baseline is at the \fIend\fR of the line.
+-.pg
+-.de eb
+-.sp -1
+-.nf
+-\h'-.5n'\L'|\\nzu-1'\l'\\n(.lu+1n\(ul'\L'-|\\nzu+1'\l'|0u-.5n\(ul'
+-.fi
+-..
+-.ne 2i
+-.mk z
+-The horizontal and vertical line drawing functions may be used
+-in combination to produce large boxes.
+-The zero-width \fIbox-rule\fR and the \(12-em wide \fIunderrule\fR
+-were \fIdesigned\fR to form corners when using 1-em vertical
+-spacings.
+-For example the macro
+-.x1
+-.ftB
+-\&.de eb
+-\&.sp \-1     \e"compensate for next automatic base-line spacing
+-\&.nf \e"avoid possibly overflowing word buffer
+-.tr ||
+-\&\eh\'\-.5n\'\eL\'\||\|\e\enau\-1\'\el\'\e\en(.lu+1n\e(ul\'\eL\'\-\||\|\e\enau+1\'\el\'\||\|0u\-.5n\e(ul\'    \e"draw box
+-.tr |
+-.lg0
+-\&.fi
+-.lg
+-\&..
+-.ftR
+-.x2
+-will draw a box around some text whose beginning vertical place was
+-saved in number register \fIa\fR
+-(e. g. using \fB.mk|a\fR)
+-as done for this paragraph.
+-.eb
+//GO.SYSIN DD m3
+echo m4
+sed 's/.//' >m4 <<'//GO.SYSIN DD m4'
+-.tr |
+-.mh
+-Hyphenation.
+-.pg
+-The automatic hyphenation may be switched off and on.
+-When switched on with \fBhy\fR,
+-several variants may be set.
+-A \fIhyphenation indicator\fR character may be imbedded in a word to
+-specify desired hyphenation points,
+-or may be prepended to suppress hyphenation.
+-In addition,
+-the user may specify a small exception word list.
+-.pg
+-Only words that consist of a central alphabetic string
+-surrounded by (usually null) non-alphabetic strings
+-are considered candidates for automatic hyphenation.
+-Words that were input containing hyphens
+-(minus),
+-em-dashes (\fB\e(em\fR),
+-or hyphenation indicator characters\
+-\(emsuch as mother-in-law\(em\
+-are \fIalways\fR subject to splitting after those characters,
+-whether or not automatic hyphenation is on or off.
+-.h1
+-.bt
+-\fB&nh\fR     hyphenate       -       E       \
+-Automatic hyphenation is turned off.
+-.bt
+-\fB&hy\fIN\fR on,\fIN=\fR1    on,\fIN=\fR1    E       \
+-Automatic hyphenation is turned on
+-for \fIN\fR\|\(>=1, or off for \fIN=\fR\|0.
+-If \fIN=\fR\|2, \fIlast\fR lines (ones that will cause a trap)
+-are not hyphenated.
+-For \fIN=\fR\|4 and 8, the last and first two characters
+-respectively of a word are not split off.
+-These values are additive;
+-i.|e. \fIN=\fR\|14 will invoke all three restrictions.
+-.bt
+-\fB&hc\fI|c\fR        \fB\e%  \e%\fR  E       Hyphenation indicator character is set
+-to \fIc\fR or to the default \fB\e%\fR.
+-The indicator does not appear in the output.
+-.bt
+-\fB&hw\fI|word1|...\fR        ignored -       Specify hyphenation points in words
+-with imbedded minus signs.
+-Versions of a word with terminal \fIs\fR are implied;
+-i.|e. \fIdig\-it\fR implies \fIdig\-its\fR.
+-This list is examined initially \fIand\fR after
+-each suffix stripping.
+-The space available is small\(emabout 128 characters.
+-.mh
+-Three Part Titles.
+-.pg
+-The titling function \fBtl\fR provides for automatic placement
+-of three fields at the left, center, and right of a line
+-with a title-length
+-specifiable with \fBlt\fR.
+-\fBtl\fR may be used anywhere, and is independent of the
+-normal text collecting process.
+-A common use is in header and footer macros.
+-.h1
+-.bt
+-\fB&tl\fI|\'left\|\'center\|\'right\|\'\fR    -       -       \
+-The strings \fIleft\fR, \fIcenter\fR, and \fIright\fR are
+-respectively left-adjusted, centered, and right-adjusted
+-in the current title-length.
+-Any of the strings may be empty,
+-and overlapping is permitted.
+-If the page-number character (initially \fB%\fR) is found within any of the fields it is replaced
+-by the current page number having the format assigned to register \fB%\fR.
+-Any character may be used as the string delimiter.
+-.bt
+-\fB&pc\fI|c\fR        \fB%\fR off     -       The page number character is set to \fIc\fR,
+-or removed.
+-The page-number register remains \fB%\fR.
+-.bt
+-\fB&lt\fI|\(+-N\fR    6.5\|in previous        E,\fBm\fR       Length of title set to \fI\(+-N\fR.
+-The line-length and the title-length are \fIindependent\fR.
+-Indents do not apply to titles; page-offsets do.
+-.mh
+-Output Line Numbering.
+-.pg
+-.ll -\w'0000'u
+-.nm 1 3
+-Automatic sequence numbering of output lines may be
+-requested with \fBnm\fR.
+-When in effect,
+-a three-digit, arabic number plus a digit-space
+-is prepended to output text lines.
+-The text lines are thus offset by four digit-spaces,
+-and otherwise retain their line length;
+-a reduction in line length may be desired to keep the right margin
+-aligned with an earlier margin.
+-Blank lines, other vertical spaces, and lines generated by \fBtl\fR
+-are \fInot\fR numbered.
+-Numbering can be temporarily suspended with \fBnn\fR,
+-or with an \fB.nm\fR followed by a later \fB.nm|+0\fR.
+-In addition,
+-a line number indent \fII\fR, and the number-text separation \fIS\fR
+-may be specified in digit-spaces.
+-Further, it can be specified that only those line numbers that are
+-multiples of some number \fIM\fR are to be printed (the others will appear
+-as blank number fields).
+-.br
+-.nm
+-.ll
+-.h1
+-.bt
+-\fB&nm\fI|\(+-N|M|S|I\fR      off     E       \
+-Line number mode.
+-If \fI\(+-N\fR is given,
+-line numbering is turned on,
+-and the next output line numbered is numbered \fI\(+-N\fR.
+-Default values are \fIM=\fR\|1, \fIS=\fR\|1, and \fII=\fR\|0.
+-Parameters corresponding to missing arguments are unaffected;
+-a non-numeric argument is considered missing.
+-In the absence of all arguments, numbering is turned off;
+-the next line number is preserved for possible further use
+-in number register \fBln\fR.
+-.bt
+-\fB&nn\fI|N\fR        -       \fIN=\fR1       E       The next \fIN\fR text output lines are not
+-numbered.
+-.pg
+-.ll -\w'0000'u
+-.nm +0
+-As an example, the paragraph portions of this section
+-are numbered with \fIM=\fR\|3:
+-\&\fB.nm|1|3\fR was placed at the beginning;
+-\&\fB.nm\fR was placed at the end of the first paragraph;
+-and \fB.nm|+0\fR was placed in front of this paragraph;
+-and \fB.nm\fR finally placed at the end.
+-Line lengths were also changed (by \fB\ew\'0000\'u\fR) to keep the right side aligned.
+-Another example is
+-\&\fB.nm|+5|5|x|3\fR which turns on numbering with the line number of the next
+-line to be 5 greater than the last numbered line,
+-with \fIM=\fR\|5, with spacing \fIS\fR untouched, and with the indent \fII\fR set to 3.
+-.br
+-.ll
+-.nm
+-.mh
+-Conditional Acceptance of Input
+-.pg
+-In the following,
+-\fIc\fR is a one-character, built-in \fIcondition\fR name,
+-\fB!\fR signifies \fInot\fR,
+-\fIN\fR is a numerical expression,
+-\fIstring1\fR and \fIstring2\fR are strings delimited by any non-blank, non-numeric character \fInot\fR in the strings,
+-and
+-\fIanything\fR represents what is conditionally accepted.
+-.h1
+-.bt
+-\fB&if\fI|c|anything\fR               -       -       If condition \fIc\fR true, accept \fIanything\fR as input;
+-in multi-line case use \fI\e{anything\|\e}\fR.
+-.bt
+-\fB&if|!\fIc|anything\fR      -       -       If condition \fIc\fR false, accept \fIanything\fR.
+-.bt
+-\fB&if\fI|N|anything\fR       -       \fBu\fR If expression \fIN\fR > 0, accept \fIanything\fR.
+-.bt
+-\fB&if|!\fIN|anything\fR      -       \fBu\fR If expression \fIN\fR \(<= 0, accept \fIanything\fR.
+-.bt
+-\fB&if\fI|\|\'string1\|\'string2\|\'|anything\fR      -       If \fIstring1\fR identical to \fIstring2\fR,
+-accept \fIanything\fR.
+-.bt
+-\fB&if|!\fI\|\'string1\|\'string2\|\'|anything\fR     -       If \fIstring1\fR not identical to \fIstring2\fR,
+-accept \fIanything\fR.
+-.bt
+-\fB&ie\fI|c|anything\fR       -       \fBu\fR If portion of if-else; all above forms (like \fBif\fR).
+-.bt
+-\fB&el\fI|anything\fR         -       -       Else portion of if-else.
+-.pg
+-The built-in condition names are:
+-.TS
+-center box;
+-c2|c2
+-c2|c2
+-c2|l2.
+-Condition
+-Name  True If
+-_
+-\fBo\fR       Current page number is odd
+-\fBe\fR       Current page number is even
+-\fBt\fR       Formatter is \*(TR
+-\fBn\fR       Formatter is \*(NR
+-.TE
+-If the condition \fIc\fR is \fItrue\fR, or if the number \fIN\fR is greater than zero,
+-or if the strings compare identically (including motions and character size and font),
+-\fIanything\fR is accepted as input.
+-If a \fB!\fR precedes the condition, number, or string comparison,
+-the sense of the acceptance is reversed.
+-.pg
+-Any spaces between the condition and the beginning of \fIanything\fR are skipped over.
+-The \fIanything\fR can be either a single input line (text, macro, or whatever)
+-or a number of input lines.
+-In the multi-line case,
+-the first line must begin with a left delimiter \fB\e{\fR and
+-the last line must end with a right delimiter \fB\e}\fR.
+-.pg
+-The request \fBie\fR (if-else) is identical to \fBif\fR
+-except that the acceptance state is remembered.
+-A subsequent and matching \fBel\fR (else) request then uses the reverse sense of that state.
+-\fBie\fR|-|\fBel\fR pairs may be nested.
+-.pg
+-Some examples are:
+-.x1
+-.ftB
+-.ne 1
+-&if e .tl \'\|Even Page %\'\'\'
+-.ftR
+-.x2
+-which outputs a title if the page number is even; and
+-.x1
+-.ftB
+-.ne 3.1
+-&ie \en%>1 \e{\e
+-\&\'sp 0.5i
+-&tl \'\|Page %\'\'\'
+-\&\'sp ~\|1.2i|\e}
+-&el .sp ~\|2.5i
+-.ftR
+-.x2
+-which treats page 1 differently from other pages.
+-.mh
+-Environment Switching.
+-.pg
+-A number of the parameters that
+-control the text processing are gathered together into an
+-\fIenvironment\fR, which can be switched by the user.
+-The environment parameters are those associated
+-with requests noting E in their \fINotes\fR column;
+-in addition, partially collected lines and words are in the environment.
+-Everything else is global; examples are page-oriented parameters,
+-diversion-oriented parameters, number registers, and macro and string definitions.
+-All environments are initialized with default parameter values.
+-.h1
+-.bt
+-\fB&ev\fI|N\fR        \fIN\(eq\fR0    previous        -       Environment switched to
+-environment 0\(<=\fIN\fR\(<=2.
+-Switching is done in push-down fashion so that
+-restoring a previous environment \fImust\fR be done with \fB.ev\fR
+-rather than specific reference.
+-.mh
+-Insertions from the Standard Input
+-.pg
+-The input can be temporarily switched to the system \fIstandard input\fR
+-with \fBrd\fR,
+-which will switch back when \fItwo\fR newlines
+-in a row are found (the \fIextra\fR blank line is not used).
+-This mechanism is intended for insertions in form-letter-like documentation.
+-On \s-1UNIX\s+1, the \fIstandard input\fR can be the user's keyboard,
+-a \fIpipe\fR, or a \fIfile\fR.
+-.h1
+-.bt
+-\fB&rd\fI|prompt\fR   -       \fIprompt=\fR\s-1BEL\s+1        -       \
+-Read insertion from the standard input until two newlines in a row are found.
+-If the standard input is the user's keyboard, \fIprompt\fR (or a \s-1BEL\s+1)
+-is written onto the user's terminal.
+-\fBrd\fR behaves like a macro,
+-and arguments may be placed after \fIprompt\fR.
+-.bt
+-\fB&ex\fR     -       -       -       Exit from \*(NR\(sl\*(TR.
+-Text processing is terminated exactly as if all input had ended.
+-.pg
+-If insertions are to be
+-taken from the terminal keyboard \fIwhile\fR output is being printed
+-on the terminal, the command line option \fB\-q\fR will turn off the echoing
+-of keyboard input and prompt only with \s-1BEL\s+1.
+-The regular input and insertion input \fIcannot\fR
+-simultaneously come from the standard input.
+-.pg
+-As an example,
+-multiple copies of a form letter may be prepared by entering the insertions
+-for all the copies in one file to be used as the standard input,
+-and causing the file containing the letter to reinvoke itself using \fBnx\fR (\(sc19);
+-the process would ultimately be ended by an \fBex\fR in the insertion file.
+-.mh
+-Input\(slOutput File Switching
+-.h1
+-.bt
+-\fB&so\fI|filename\fR         -       -       Switch source file.
+-The top input (file reading) level is switched to \fIfilename\fR.
+-The effect of an \fBso\fR encountered in a macro
+-is not felt until the input level returns to the file level.
+-When the new file ends,
+-input is again taken from the original file.
+-\fBso\fR's may be nested.
+-.bt
+-\fB&nx\fI|filename\fR         end-of-file     -       Next file is \fIfilename\fR.
+-The current file is considered ended, and the input is immediately switched
+-to \fIfilename\fR.
+-.bt
+-\fB&pi\fI|program\fR          -       -       Pipe output to \fIprogram\fR (\*(NR only).
+-This request must occur \fIbefore\fR any printing occurs.
+-No arguments are transmitted to \fIprogram\fR.
+-.mh
+-Miscellaneous
+-.pg
+-.h1
+-.bt
+-.mc \s12\(br\s0
+-\fB&mc\fI|c|N\fR      -       off     E,\fBm\fR       \
+-Specifies that a \fImargin\fR character \fIc\fR appear a distance
+-\fIN\fR to the right of the right margin
+-after each non-empty text line (except those produced by \fBtl\fR).
+-If the output line is too-long (as can happen in nofill mode)
+-the character will be appended to the line.
+-If \fIN\fR is not given, the previous \fIN\fR is used; the initial \fIN\fR is
+-0.2|inches in \*(NR and 1\|em in \*(TR.
+-The margin character used with this paragraph was a 12-point box-rule.
+-.br
+-.mc
+-.bt
+-\fB&tm\fI|string\fR   -       newline -       \
+-After skipping initial blanks, \fIstring\fR (rest of the line) is read in \fIcopy mode\fR
+-and written on the user's terminal.
+-.bt
+-\fB&ig\fI|yy\fR       -       \fI.yy=\fB..\fR -       Ignore \
+-input lines.
+-\fBig\fR behaves exactly like \fBde\fR (\(sc7) except that the
+-input is discarded.
+-The input is read in \fIcopy mode\fR, and any auto-incremented
+-registers will be affected.
+-.bt
+-\fB&pm\fI|t\fR        -       all     -       \
+-Print macros.
+-The names and sizes of all of the defined macros and strings are printed
+-on the user's terminal;
+-if \fIt\fR is given, only the total of the sizes is printed.
+-The sizes is given in \fIblocks\fR
+-of 128 characters.
+-.bt
+-.lg0
+-\fB&fl\fR     -       -       B       \c
+-.lg
+-Flush output buffer.
+-Used in interactive debugging to force output.
+-.mh
+-Output and Error Messages.
+-.pg
+-The output from \fBtm\fR, \fBpm\fR, and the prompt from \fBrd\fR,
+-as well as various \fIerror\fR messages are written onto
+-\s-1UNIX\s+1's \fIstandard message\fR output.
+-The latter is different from the \fIstandard output\fR,
+-where \*(NR formatted output goes.
+-By default, both are written onto the user's terminal,
+-but they can be independently redirected.
+-.pg
+-Various \fIerror\fR conditions may occur during
+-the operation of \*(NR and \*(TR.
+-Certain less serious errors having only local impact do not
+-cause processing to terminate.
+-Two examples are \fIword overflow\fR, caused by a word that is too large
+-to fit into the word buffer (in fill mode), and
+-\fIline overflow\fR, caused by an output line that grew too large
+-to fit in the line buffer;
+-in both cases, a message is printed, the offending excess
+-is discarded,
+-and the affected word or line is marked at the point of truncation
+-with a \(** in \*(NR and a \(lh in \*(TR.
+-The philosophy is to continue processing, if possible,
+-on the grounds that output useful for debugging may be produced.
+-If a serious error occurs, processing terminates,
+-and an appropriate message is printed.
+-Examples are the inability to create, read, or write files,
+-and the exceeding of certain internal limits that
+-make future output unlikely to be useful.
+-.pg
+-.bp
+//GO.SYSIN DD m4
+echo m5
+sed 's/.//' >m5 <<'//GO.SYSIN DD m5'
+-.pn 27
+-.ds H T
+-.tr |
+-.tr ~|
+-.de x1
+-.xx
+-.ftB
+-.in .2i
+-.nf
+-.ne 2.1
+-.ta 1i
+-..
+-.de x2
+-.fi
+-.in0
+-.ftR
+-.xx
+-..
+-.br
+-.ce
+-.ftB
+-.rs
+-.sp 0.5i
+-TUTORIAL EXAMPLES
+-.ftR
+-.sp2
+-.nr p 0
+-.2C
+-.ns
+-.mh
+-.mk
+-Introduction
+-.pg
+-Although \*(NR and \*(TR
+-have by design a syntax reminiscent
+-of earlier text processors*
+-.fn
+-.xx
+-*For example:
+-P.|A.|Crisman, Ed.,
+-.ul
+-The Compatible Time-Sharing System,
+-MIT Press, 1965, Section|AH9.01
+-(Description of RUNOFF program on MIT's CTSS system).
+-.ef
+-with the intent of easing their use,
+-it is almost always necessary to
+-prepare at least a small set of macro definitions
+-to describe most documents.
+-Such common formatting needs
+-as page margins and footnotes
+-are deliberately not built into \*(NR and \*(TR.
+-Instead,
+-the macro and string definition, number register, diversion,
+-environment switching, page-position trap, and conditional input mechanisms
+-provide the basis for user-defined implementations.
+-.pg
+-The examples to be discussed are intended to be useful and somewhat realistic,
+-but won't necessarily cover all relevant contingencies.
+-Explicit numerical parameters are used
+-in the examples
+-to make them easier to read and to
+-illustrate typical values.
+-In many cases, number registers would really be used
+-to reduce the number of places where numerical
+-information is kept,
+-and to concentrate conditional parameter initialization
+-like that which depends on whether \*(TR or \*(NR is being used.
+-.mh
+-Page Margins
+-.pg
+-As discussed in \(sc3,
+-\fIheader\fR and \fIfooter\fR macros are usually defined
+-to describe the top and bottom page margin areas respectively.
+-A trap is planted at page position 0 for the header, and at
+-\fI\-N\fR (\fIN\fR from the page bottom) for the footer.
+-The simplest such definitions might be
+-.x1
+-&de hd        \e"define header
+-\'sp 1i
+-&&    \e"end definition
+-&de fo        \e"define footer
+-\'bp
+-&&    \e"end definition
+-&wh 0 hd
+-&wh \-1i fo
+-.x2
+-which provide blank 1|inch top and bottom margins.
+-The header will occur on the \fIfirst\fR page,
+-only if the definition and trap exist prior to
+-the initial pseudo-page transition (\(sc3).
+-In fill mode, the output line that springs the footer trap
+-was typically forced out because some part or whole word didn't fit on it.
+-If anything in the footer and header that follows causes a \fIbreak\fR,
+-that word or part word will be forced out.
+-In this and other examples,
+-requests like \fBbp\fR and \fBsp\fR that normally cause breaks are invoked using
+-the \fIno-break\fR control character \fB\'\fR
+-to avoid this.
+-When the header\(slfooter design contains material
+-requiring independent text processing, the
+-environment may be switched, avoiding
+-most interaction with the running text.
+-.pg
+-A more realistic example would be
+-.x1
+-&de hd        \e"header
+-&if t .tl \'\|\e(rn\'\'\e(rn\'  \e"troff cut mark
+-&if \e\en%>1 \e{\e
+-\'sp ~\|0.5i\-1       \e"tl base at 0.5i
+-&tl \'\'\- % \-\'\'   \e"centered page number
+-&ps   \e"restore size
+-&ft   \e"restore font
+-&vs  \e}      \e"restore vs
+-\'sp ~\|1.0i          \e"space to 1.0i
+-&ns   \e"turn on no-space mode
+-&&
+-&de fo        \e"footer
+-&ps 10        \e"set footer\(slheader size
+-&ft R \e"set font
+-&vs 12p       \e"set base-line spacing
+-&if \e\en%=1 \e{\e
+-\'sp ~\|\e\en(.pu\-0.5i\-1  \e"tl base 0.5i up
+-&tl \'\'\- % \-\'\' \e}  \e"first page number
+-\'bp
+-&&
+-&wh 0 hd
+-&wh \-1i fo
+-.x2
+-which sets the size, font, and base-line spacing for the
+-header\(slfooter material, and ultimately restores them.
+-The material in this case is a page number at the bottom of the
+-first page and at the top of the remaining pages.
+-If \*(TR is used, a \fIcut mark\fR is drawn in the form
+-of \fIroot-en\fR's at each margin.
+-The \fBsp\fR's refer to absolute positions to avoid
+-dependence on the base-line spacing.
+-Another reason for this in the footer
+-is that the footer is invoked by printing a line whose
+-vertical spacing swept past the trap position by possibly
+-as much as the base-line spacing.
+-The \fIno-space\fR mode is turned on at the end of \fBhd\fR
+-to render ineffective
+-accidental occurrences of \fBsp\fR at the top of the running text.
+-.pg
+-The above method of restoring size, font, etc. presupposes
+-that such requests (that set \fIprevious\fR value) are \fInot\fR
+-used in the running text.
+-A better scheme is save and restore both the current \fIand\fR
+-previous values as shown for size in the following:
+-.x1
+-&de fo
+-&nr s1 \e\en(.s       \e"current size
+-&ps
+-&nr s2 \e\en(.s       \e"previous size
+-&  ---        \e"rest of footer
+-&&
+-&de hd
+-&  ---        \e"header stuff
+-&ps \e\en(s2  \e"restore previous size
+-&ps \e\en(s1  \e"restore current size
+-&&
+-.x2
+-Page numbers may be printed in the bottom margin
+-by a separate macro triggered during the footer's
+-page ejection:
+-.x1
+-&de bn        \e"bottom number
+-&tl \'\'\- % \-\'\'   \e"centered page number
+-&&
+-&wh \-0.5i\-1v bn      \e"tl base 0.5i up
+-.x2
+-.mh
+-Paragraphs and Headings
+-.pg
+-The housekeeping
+-associated with starting a new paragraph should be collected
+-in a paragraph macro
+-that, for example,
+-does the desired preparagraph spacing,
+-forces the correct font, size, base-line spacing, and indent,
+-checks that enough space remains for \fImore than one\fR line,
+-and
+-requests a temporary indent.
+-.x1
+-&de pg        \e"paragraph
+-&br   \e"break
+-&ft R \e"force font,
+-&ps 10        \e"size,
+-&vs 12p       \e"spacing,
+-&in 0 \e"and indent
+-&sp 0.4       \e"prespace
+-&ne 1+\e\en(.Vu       \e"want more than 1 line
+-&ti 0.2i      \e"temp indent
+-&&
+-.x2
+-The first break in \fBpg\fR
+-will force out any previous partial lines,
+-and must occur before the \fBvs\fR.
+-The forcing of font, etc. is
+-partly a defense against prior error and
+-partly to permit
+-things like section heading macros to
+-set parameters only once.
+-The prespacing parameter is suitable for \*(TR;
+-a larger space, at least as big as the output device vertical resolution, would be
+-more suitable in \*(NR.
+-The choice of remaining space to test for in the \fBne\fR
+-is the smallest amount greater than one line
+-(the \fB.V\fR is the available vertical resolution).
+-.pg
+-A macro to automatically number section headings
+-might look like:
+-.x1
+-&de sc        \e"section
+-&  ---        \e"force font, etc.
+-&sp 0.4       \e"prespace
+-&ne 2.4+\e\en(.Vu \e"want 2.4+ lines
+-.lg 0
+-&fi
+-.lg
+-\e\en+S.
+-&&
+-&nr S 0 1     \e"init S
+-.x2
+-The usage is \fB.sc\fR,
+-followed by the section heading text,
+-followed by \fB.pg\fR.
+-The \fBne\fR test value includes one line of heading,
+-0.4 line in the following \fBpg\fR, and
+-one line of the paragraph text.
+-A word consisting of the next section number and a period is
+-produced to begin the heading line.
+-The format of the number may be set by \fBaf\fR (\(sc8).
+-.pg
+-Another common form is the labeled, indented paragraph,
+-where the label protrudes left into the indent space.
+-.x1
+-&de lp        \e"labeled paragraph
+-&pg
+-&in 0.5i      \e"paragraph indent
+-&ta 0.2i 0.5i \e"label, paragraph
+-&ti 0
+-\et\e\e$1\et\ec       \e"flow into paragraph
+-&&
+-.x2
+-The intended usage is "\fB.lp\fR \fIlabel\fR\|";
+-\fIlabel\fR will begin at 0.2\|inch, and
+-cannot exceed a length of 0.3\|inch without intruding into
+-the paragraph.
+-The label could be right adjusted against 0.4\|inch by
+-setting the tabs instead with \fB.ta|0.4iR|0.5i\fR.
+-The last line of \fBlp\fR ends with \fB\ec\fR so that
+-it will become a part of the first line of the text
+-that follows.
+-.mh
+-Multiple Column Output
+-.pg
+-The production of multiple column pages requires
+-the footer macro to decide whether it was
+-invoked by other than the last column,
+-so that it will begin a new column rather than
+-produce the bottom margin.
+-The header can initialize a column register that
+-the footer will increment and test.
+-The following is arranged for two columns, but
+-is easily modified for more.
+-.x1
+-&de hd        \e"header
+-&  ---
+-&nr cl 0 1    \e"init column count
+-&mk   \e"mark top of text
+-&&
+-&de fo        \e"footer
+-&ie \e\en+(cl<2 \e{\e
+-&po +3.4i     \e"next column; 3.1+0.3
+-&rt   \e"back to mark
+-&ns \e}       \e"no-space mode
+-&el \e{\e
+-&po \e\enMu   \e"restore left margin
+-&  ---
+-\'bp \e}
+-&&
+-&ll 3.1i      \e"column width
+-&nr M \e\en(.o        \e"save left margin
+-.x2
+-Typically a portion of the top of the first page
+-contains full width text;
+-the request for the narrower line length,
+-as well as another \fB.mk\fR would
+-be made where the two column output was to begin.
+-.mh
+-Footnote Processing
+-.pg
+-The footnote mechanism to be described is used by
+-imbedding the footnotes in the input text at the
+-point of reference,
+-demarcated by an initial \fB.fn\fR and a terminal \fB.ef\fR:
+-.x1
+-&fn
+-\fIFootnote text and control lines...\fP
+-&ef
+-.x2
+-In the following,
+-footnotes are processed in a separate environment and diverted
+-for later printing in the space immediately prior to the bottom
+-margin.
+-There is provision for the case where the last collected
+-footnote doesn't completely fit in the available space.
+-.x1
+-&de hd        \e"header
+-&  ---
+-&nr x 0 1     \e"init footnote count
+-&nr y 0\-\e\enb       \e"current footer place
+-&ch fo \-\e\enbu      \e"reset footer trap
+-&if \e\en(dn .fz      \e"leftover footnote
+-&&
+-&de fo        \e"footer
+-&nr dn 0      \e"zero last diversion size
+-&if \e\enx \e{\e
+-&ev 1 \e"expand footnotes in ev1
+-&nf   \e"retain vertical size
+-&FN   \e"footnotes
+-&rm FN        \e"delete it
+-&if "\e\en(.z"fy" .di  \e"end overflow diversion
+-&nr x 0       \e"disable fx
+-&ev  \e}      \e"pop environment
+-&  ---
+-\'bp
+-&&
+-&de fx        \e"process footnote overflow
+-&if \e\enx .di fy     \e"divert overflow
+-&&
+-&de fn        \e"start footnote
+-&da FN        \e"divert (append) footnote
+-&ev 1 \e"in environment 1
+-&if \e\en+x=1 .fs      \e"if first, include separator
+-.lg0
+-&fi   \e"fill mode
+-.lg
+-&&
+-&de ef        \e"end footnote
+-&br   \e"finish output
+-&nr z \e\en(.v        \e"save spacing
+-&ev   \e"pop ev
+-&di   \e"end diversion
+-&nr y \-\e\en(dn      \e"new footer position,
+-&if \e\enx=1 .nr y \-(\e\en(.v\-\e\enz) \e
+-      \e"uncertainty correction
+-&ch fo \e\enyu        \e"y is negative
+-&if (\|\e\en(nl+1v)>(\|\e\en(.p+\e\eny) \e
+-&ch fo \e\en(nlu+1v    \e"it didn't fit
+-&&
+-&de fs        \e"separator
+-\el\'\|1i\'   \e"1 inch rule
+-&br
+-&&
+-&de fz        \e"get leftover footnote
+-&fn
+-&nf   \e"retain vertical size
+-&fy   \e"where fx put it
+-&ef
+-&&
+-&nr b 1.0i    \e"bottom margin size
+-&wh 0 hd      \e"header trap
+-&wh 12i fo    \e"footer trap, temp position
+-&wh \-\e\enbu fx      \e"fx at footer position
+-&ch fo \-\e\enbu      \e"conceal fx with fo
+-.x2
+-The header \fBhd\fR initializes a footnote count register \fBx\fR,
+-and sets both the current footer trap position register \fBy\fR and
+-the footer trap itself to a nominal position specified in
+-register \fBb\fR.
+-In addition, if the register \fBdn\fR indicates a leftover footnote,
+-\fBfz\fR is invoked to reprocess it.
+-The footnote start macro \fBfn\fR begins a diversion (append) in environment 1,
+-and increments the count \fBx\fR; if the count is one, the footnote separator \fBfs\fR
+-is interpolated.
+-The separator is kept in a separate macro to permit user redefinition.
+-The footnote end macro \fBef\fR restores
+-the previous environment and ends the diversion after saving the spacing size in register \fBz\fR.
+-\fBy\fR is then decremented by the size of the footnote, available in \fBdn\fR;
+-then on the first footnote, \fBy\fR is further decremented by the difference
+-in vertical base-line spacings of the two environments, to
+-prevent the late triggering the footer trap from causing the last
+-line of the combined footnotes to overflow.
+-The footer trap is then set to the lower (on the page) of \fBy\fR or the current page position (\fBnl\fR)
+-plus one line, to allow for printing the reference line.
+-If indicated by \fBx\fR, the footer \fBfo\fR rereads the footnotes from \fBFN\fR in nofill mode
+-in environment 1,
+-and deletes \fBFN\fR.
+-If the footnotes were too large to fit, the macro \fBfx\fR will be trap-invoked to redivert
+-the overflow into \fBfy\fR,
+-and the register \fBdn\fR will later indicate to the header whether \fBfy\fR is empty.
+-Both \fBfo\fR and \fBfx\fR are planted in the nominal footer trap position in an order
+-that causes \fBfx\fR to be concealed unless the \fBfo\fR trap is moved.
+-The footer then terminates the overflow diversion, if necessary, and
+-zeros \fBx\fR to disable \fBfx\fR,
+-because the uncertainty correction
+-together with a not-too-late triggering of the footer can result
+-in the footnote rereading finishing before reaching the \fBfx\fR trap.
+-.pg
+-A good exercise for the student is to combine the multiple-column and footnote mechanisms.
+-.mh
+-The Last Page
+-.pg
+-After the last input file has ended, \*(NR and \*(TR
+-invoke the \fIend macro\fR (\(sc7), if any,
+-and when it finishes, eject the remainder of the page.
+-During the eject, any traps encountered are processed normally.
+-At the \fIend\fR of this last page, processing terminates
+-\fIunless\fR a partial line, word, or partial word remains.
+-If it is desired that another page be started, the end-macro
+-.x1
+-&de en        \e"end-macro
+-\ec
+-\'bp
+-&&
+-&em en
+-.x2
+-will deposit a null partial word,
+-and effect another last page.
+//GO.SYSIN DD m5
+echo table1
+sed 's/.//' >table1 <<'//GO.SYSIN DD table1'
+-.pn 31
+-.rm mx
+-.br
+-.tr &&
+-.tr ||
+-.tr ~~
+-.de aa
+-.nf
+-abcdefghijklmnopqrstuvwxyz
+-ABCDEFGHIJKLMNOPQRSTUVWXYZ
+-1234567890
+-.ss9
+-! $ % & ( ) ` ' * + \- . , / : ; = ? [ ] |
+-.fi
+-\(bu \(sq \(em \(hy \(ru \(14 \(12 \(34 \(fi \(fl \(ff
+-\(Fi \(Fl
+-\(de \(dg \(fm
+-\(ct \(rg \(co
+-.ss12
+-..
+-.de bb
+-.ss9
+-.fi
+-.ll5i
+-" \' \e ^ \_ \` ~ \(sl < > { } # @ \(pl \(mi \(eq \(**
+-.br
+-\(*a \(*b \(*g \(*d \(*e \(*z \(*y \(*h \(*i \(*k \(*l \(*m
+-\(*n \(*c \(*o \(*p \(*r \(*s \(ts \(*t \(*u \(*f \(*x \(*q \(*w
+-.br
+-\(*G \(*D \(*H \(*L \(*C \(*P \(*S \(*U \(*F \(*Q \(*W
+-.br
+-\(sr \(rn \(>= \(<= \(== \(ap \(~= \(!=
+-\(-> \(<- \(ua \(da \(mu
+-\(di \(+- \(cu \(ca \(sb \(sp \(ib \(ip \(if \(pd
+-.br
+-\(sc \(gr \(no \(is \(pt \(es \(mo
+-\(dd \(rh \(lh \(bs \(or \(ci
+-\(lt \(lb \(rt \(rb \(lk \(rk \(bv \(lf \(rf \(lc \(rc
+-\(br
+-.br
+-.ss12
+-.nf
+-..
+-.nf
+-.ps12
+-.vs 14p
+-.ft B
+-.ce
+-.sp 3
+-Table I
+-.sp
+-.ce
+-Font Style Examples
+-.sp .5i
+-.ftR
+-.ps 10
+-.fi
+-.vs 12p
+-.na
+-The following fonts are printed in 12-point, with a vertical spacing of 14-point,
+-and with
+-non-alphanumeric characters separated by \(14\|em space.
+-The Special Mathematical Font was specially prepared for Bell Laboratories
+-by Graphic Systems, Inc. of Hudson, New Hampshire.
+-The Times Roman, Italic, and Bold are
+-among the many standard fonts available from that company.
+-.sp.5i
+-.ps12
+-.vs14p
+-.ftR
+-Times Roman
+-.sp.5
+-.aa
+-.sp
+-.ftI
+-Times Italic
+-.sp.5
+-.aa
+-.sp
+-.ftB
+-Times Bold
+-.sp.5
+-.aa
+-.sp
+-.ftR
+-Special Mathematical Font
+-.sp.5
+-.fi
+-.ll 5i
+-.bb
+//GO.SYSIN DD table1
+echo table2
+sed 's/.//' >table2 <<'//GO.SYSIN DD table2'
+-.pn32
+-.sp 100
+-.br
+-.de mx
+-.nf
+-.ftI
+-.ta .25iC .5i +.45i 3.25iC +.25i +.45i
+-              Input   Character               Input   Character
+-      Char    Name    Name    Char    Name    Name
+-.ftR
+-.sp.2
+-.nr cl 0
+-.mk
+-..
+-.br
+-.tr ~~
+-.nf
+-.ps12
+-.vs 14p
+-.ft B
+-.ce
+-Table II
+-.sp
+-.ce2
+-Input Naming Conventions for \', \`,and  \-
+-and for Non-ASCII Special Characters
+-.sp .5i
+-.ftR
+-.ps10
+-.vs12p
+-.ftB
+-.bd I 3
+-Non-\s-1ASCII\s+1 characters and \fIminus\fP on the standard fonts.
+-.sp
+-.ftR
+-.de cl
+-.ie \\n+(cl<2 \{.po +3.0i
+-.rt \}
+-.el .sc
+-..
+-.de sc
+-.po 26i/27u
+-.nr cl 0
+-..
+-.nr cl 0 1
+-.de qq
+-      \&'     \'      close quote
+-      `       \`      open quote
+-      \(em    \e(em   3\(sl4 Em dash
+-      -       \-      hyphen or
+-      \(hy    \e(hy   hyphen
+-      \-      \e\-    current font minus
+-      \(bu    \e(bu   bullet
+-      \(sq    \e(sq   square
+-      \(ru    \e(ru   rule
+-      \(14    \e(14   1\(sl4
+-      \(12    \e(12   1\(sl2
+-      \(34    \e(34   3\(sl4
+-      \(fi    \e(fi   fi
+-      \(fl    \e(fl   fl
+-      \(ff    \e(ff   ff
+-      \(Fi    \e(Fi   ffi
+-      \(Fl    \e(Fl   ffl
+-      \(de    \e(de   degree
+-      \(dg    \e(dg   dagger
+-      \(fm    \e(fm   foot mark
+-      \(ct    \e(ct   cent sign
+-      \(rg    \e(rg   registered
+-      \(co    \e(co   copyright
+-..
+-.di zz
+-.lg0
+-.qq
+-.di
+-.lg
+-.mx
+-.nr aa \n(dn/2
+-.ne \n(aau+1
+-.nr bb \n(nl+\n(aa
+-.wh \n(bbu cl
+-.qq
+-.sp |\n(bbu
+-.ch cl 12i
+-.fi
+-.sp2
+-.ftB
+-.bd I
+-Non-\s-1ASCII\s+1 characters and \', \`, \_\|, \(pl, \(mi, \(eq, and \(** on the special font.
+-.sp.4
+-.ftR
+-.fi
+-.ps10
+-The ASCII characters @, #, ", \', \`, <, >, \\, {, }, ~, ^, and \(ul exist
+-\fIonly\fR on the special font and are printed as a 1-em space if that font
+-is not mounted.
+-The following characters exist only on the special font except
+-for the upper case Greek letter names followed by \(dg which are mapped into
+-upper case English letters in
+-whatever font is mounted on font position one (default Times Roman).
+-The special math plus, minus, and equals are provided to
+-insulate the appearance of equations from the choice of standard fonts.
+-.bd I 3
+-.nf
+-.ps10
+-.sp
+-.de sc
+-.po 26i/27u
+-.nr cl 0
+-'bp
+-..
+-.ch cl \nmu-\n(.vu-1u
+-.mx
+-.lg 0
+-      \(pl    \e(pl   math plus
+-      \(mi    \e(mi   math minus
+-      \(eq    \e(eq   math equals
+-      \(**    \e(**   math star
+-      \(sc    \e(sc   section
+-      \(aa    \\(aa   acute accent
+-      \(ga    \\(ga   grave accent
+-      \(ul    \\(ul   underrule
+-      \(sl    \\(sl   slash (matching backslash)
+-      \(*a    \\(*a   alpha
+-      \(*b    \\(*b   beta
+-      \(*g    \\(*g   gamma
+-      \(*d    \\(*d   delta
+-      \(*e    \\(*e   epsilon
+-      \(*z    \\(*z   zeta
+-      \(*y    \\(*y   eta
+-      \(*h    \\(*h   theta
+-      \(*i    \\(*i   iota
+-      \(*k    \\(*k   kappa
+-      \(*l    \\(*l   lambda
+-      \(*m    \\(*m   mu
+-      \(*n    \\(*n   nu
+-      \(*c    \\(*c   xi
+-      \(*o    \\(*o   omicron
+-      \(*p    \\(*p   pi
+-      \(*r    \\(*r   rho
+-      \(*s    \\(*s   sigma
+-      \(ts    \\(ts   terminal sigma
+-      \(*t    \\(*t   tau
+-      \(*u    \\(*u   upsilon
+-      \(*f    \\(*f   phi
+-      \(*x    \\(*x   chi
+-      \(*q    \\(*q   psi
+-      \(*w    \\(*w   omega
+-      \(*A    \\(*A   Alpha\(dg
+-      \(*B    \\(*B   Beta\(dg
+-      \(*G    \\(*G   Gamma
+-      \(*D    \\(*D   Delta
+-      \(*E    \\(*E   Epsilon\(dg
+-      \(*Z    \\(*Z   Zeta\(dg
+-      \(*Y    \\(*Y   Eta\(dg
+-      \(*H    \\(*H   Theta
+-      \(*I    \\(*I   Iota\(dg
+-      \(*K    \\(*K   Kappa\(dg
+-      \(*L    \\(*L   Lambda
+-      \(*M    \\(*M   Mu\(dg
+-      \(*N    \\(*N   Nu\(dg
+-      \(*C    \\(*C   Xi
+-      \(*O    \\(*O   Omicron\(dg
+-      \(*P    \\(*P   Pi
+-      \(*R    \\(*R   Rho\(dg
+-      \(*S    \\(*S   Sigma
+-      \(*T    \\(*T   Tau\(dg
+-      \(*U    \\(*U   Upsilon
+-      \(*F    \\(*F   Phi
+-      \(*X    \\(*X   Chi\(dg
+-      \(*Q    \\(*Q   Psi
+-      \(*W    \\(*W   Omega
+-      \(sr    \\(sr   square root
+-      \(rn    \\(rn   root en extender
+-      \(>=    \\(>=   >=
+-      \(<=    \\(<=   <=
+-      \(==    \\(==   identically equal
+-      \(~=    \\(~=   approx =
+-      \(ap    \\(ap   approximates
+-      \(!=    \\(!=   not equal
+-      \(->    \\(\(mi>        right arrow
+-      \(<-    \\(<\(mi        left arrow
+-      \(ua    \\(ua   up arrow
+-      \(da    \\(da   down arrow
+-      \(mu    \\(mu   multiply
+-      \(di    \\(di   divide
+-      \(+-    \\(+\(mi        plus-minus
+-      \(cu    \\(cu   cup (union)
+-      \(ca    \\(ca   cap (intersection)
+-      \(sb    \\(sb   subset of
+-      \(sp    \\(sp   superset of
+-      \(ib    \\(ib   improper subset
+-      \(ip    \\(ip   improper superset
+-      \(if    \\(if   infinity
+-      \(pd    \\(pd   partial derivative
+-      \(gr    \\(gr   gradient
+-      \(no    \\(no   not
+-      \(is    \\(is   integral sign
+-      \(pt    \\(pt   proportional to
+-      \(es    \\(es   empty set
+-      \(mo    \\(mo   member of
+-      \(br    \\(br   box vertical rule
+-      \(dd    \\(dd   double dagger
+-      \(rh    \\(rh   right hand
+-      \(lh    \\(lh   left hand
+-      \(bs    \\(bs   Bell System logo
+-      \(or    \\(or   or
+-      \(ci    \\(ci   circle
+-      \(lt    \\(lt   left top of big curly bracket
+-      \(lb    \\(lb   left bottom
+-      \(rt    \\(rt   right top
+-      \(rb    \\(rb   right bot
+-      \(lk    \\(lk   left center of big curly bracket
+-      \(rk    \\(rk   right center of big curly bracket
+-      \(bv    \\(bv   bold vertical
+-      \(lf    \\(lf   left floor (left bottom of big
+-                      square bracket)
+-      \(rf    \\(rf   right floor (right bottom)
+-      \(lc    \\(lc   left ceiling (left top)
+-      \(rc    \\(rc   right ceiling (right top)
+//GO.SYSIN DD table2
+echo tprint
+sed 's/.//' >tprint <<'//GO.SYSIN DD tprint'
+-troff   $* m.mac m0
+-tbl m0a | troff   $* m.mac -
+-tbl m[1234] | troff   $* m.mac -
+-troff   $* m.mac m5
+-troff   $* m.mac table1
+-troff   $* m.mac table2
+-troff  $* m.mac add
+//GO.SYSIN DD tprint
diff --git a/doc/7thEdMan/vol2/trofftut.bun b/doc/7thEdMan/vol2/trofftut.bun
new file mode 100644 (file)
index 0000000..3c8776b
--- /dev/null
@@ -0,0 +1,2822 @@
+# To unbundle, run this file
+echo tt.mac
+sed 's/.//' >tt.mac <<'//GO.SYSIN DD tt.mac'
+-.tr _\(em
+-.tr *\(**
+-.de UL
+-.if n .ul
+-.if n \\$3\\$1\\$2
+-.if t \\$3\f3\\$1\fP\\$2
+-..
+-.de UC
+-\\$3\s-1\\$1\s+1\\$2
+-..
+-.de C
+-.if n .ul
+-.if n \\$3\\$1\\$2
+-.if t \\$3\f3\\$1\fP\\$2
+-..
+-.de IT
+-.if t \\$3\f2\\$1\fP\\$2
+-.if n .ul
+-.if n \\$3\\$1\\$2
+-..
+-.de UI
+-\f3\\$1\fI\\$2\fR\\$3
+-..
+-.de P1
+-.if n .ls 1
+-.nf
+-.             use first argument as indent if present
+-.if \\n(.$ .DS I \\$1
+-.if !\\n(.$ .DS I 5
+-.ta .75i 1.5i 2.25i 3i 3.75i
+-.tr '\'
+-..
+-.de P2
+-.tr ''
+-.DE
+-.if n .ls 2
+-.lg
+-..
+-.if t .ds m \(mi
+-.if n .ds m -
+-.if t .ds n \(no
+-.if n .ds n -
+-.if t .ds s \v'.41m'\s+4*\s-4\v'-.41m'
+-.if n .ds s *
+-.if t .ds S \(sl
+-.if n .ds S /
+-.if t .ds d \s+4\&.\&\s-4
+-.if n .ds d \&.\&
+-.if t .ds a \z@@
+-.if n .ds a @
+-.hy 14
+-.     2=not last lines; 4= no -xx; 8=no xx-
+-.de WS
+-.sp \\$1
+-..
+-.   ACCENTS  say \*'e or \*`e to get e acute or e grave
+-.ds ' \h'\w'e'u*4/10'\z\(aa\h'-\w'e'u*4/10'
+-.ds e \o"e\'"
+-.ds ` \h'\w'e'u*4/10'\z\(ga\h'-\w'e'u*4/10'
+-.   UMLAUT  \*:u, etc.
+-.ds : \v'-0.6m'\h'(1u-(\\n(.fu%2u))*0.13m+0.06m'\z.\h'0.2m'\z.\h'-((1u-(\\n(.fu%2u))*0.13m+0.26m)'\v'0.6m'
+-.  TILDE and CIRCUMFLEX
+-.ds ^ \\k:\h'-\\n(.fu+1u/2u*2u+\\n(.fu-1u*0.13m+0.06m'\z^\h'|\\n:u'
+-.ds ~ \\k:\h'-\\n(.fu+1u/2u*2u+\\n(.fu-1u*0.13m+0.06m'\z~\h'|\\n:u'
+-.de BD
+-\&\\$3\f1\\$1\h\(ts-\w\(ts\\$1\(tsu+1u\(ts\\$1\fP\\$2\&
+-..
+-.hw semi-colon
+//GO.SYSIN DD tt.mac
+echo tt00
+sed 's/.//' >tt00 <<'//GO.SYSIN DD tt00'
+-.RP
+-.....TM 76-1273-7 39199 39199-11
+-.TL
+-A TROFF Tutorial
+-.AU "MH 2C-518" 6021
+-Brian W. Kernighan
+-.AI
+-.MH
+-.OK
+-Typesetting
+-Text formatting
+-NROFF
+-.AB
+-.PP
+-.UL troff
+-is a text-formatting program for driving the Graphic Systems
+-phototypesetter on the
+-.UX
+-and
+-.UC GCOS
+-operating systems.
+-This device is capable of producing high quality
+-text;
+-this paper is an example of
+-.UL troff
+-output.
+-.PP
+-The phototypesetter itself normally runs with four fonts,
+-containing roman, italic and bold letters 
+-(as on this page),
+-a full greek alphabet, and a substantial number of
+-special characters and mathematical symbols.
+-Characters can be printed in a range of sizes,
+-and placed anywhere on the page.
+-.PP
+-.UL troff
+-allows the user full control over fonts,
+-sizes, and character positions,
+-as well as the usual features of a formatter _
+-right-margin justification, automatic hyphenation,
+-page titling and numbering, and so on.
+-It also provides macros, arithmetic variables and operations,
+-and conditional testing, for complicated formatting tasks.
+-.PP
+-This document is an introduction to the most basic use of
+-.UL troff .
+-It presents just enough information to enable the user
+-to do simple formatting
+-tasks like making viewgraphs,
+-and to make incremental changes to existing packages
+-of
+-.UL troff
+-commands.
+-In most respects, the 
+-.UC UNIX
+-formatter
+-.UL nroff
+-is identical to
+-.UL troff ,
+-so this document also serves as a tutorial on
+-.UL nroff .
+-.AE
+-.CS 13 1 14 0 0 5
+-.if t .2C
+-.nr PS 9
+-.nr VS 11
+//GO.SYSIN DD tt00
+echo tt01
+sed 's/.//' >tt01 <<'//GO.SYSIN DD tt01'
+-.NH
+-Introduction
+-.tr ^.
+-.PP
+-.UL troff
+-[1]
+-is a text-formatting program,
+-written by J. F. Ossanna,
+-for producing
+-high-quality printed output from the phototypesetter
+-on the
+-.UC UNIX
+-and
+-.UC GCOS
+-operating systems.
+-This document is an example of
+-.UL troff
+-output.
+-.PP
+-The single most important rule
+-of using
+-.UL troff
+-is
+-not to use it directly, but through some intermediary.
+-In many ways,
+-.UL troff
+-resembles an assembly language _
+-a remarkably powerful and flexible one _
+-but nonetheless such that many operations must be specified
+-at a level of detail and in a form that is too hard 
+-for most people to use effectively.
+-.PP
+-For two special applications, there are programs that provide
+-an interface to
+-.UL troff
+-for the majority of users.
+-.UL eqn 
+-[2]
+-provides an easy to learn language for typesetting mathematics;
+-the 
+-.UL eqn
+-user
+-need know no 
+-.UL troff
+-whatsoever
+-to typeset mathematics.
+-.UL tbl
+-[3]
+-provides the same convenience for producing tables of arbitrary
+-complexity.
+-.PP
+-For producing straight text (which may well contain mathematics or tables), there are a number of `macro packages'
+-that define formatting rules and operations for specific styles
+-of documents,
+-and reduce the amount of
+-direct contact with 
+-.UL troff .
+-In particular, the `\-ms'
+-[4]
+-and PWB/MM [5]
+-packages
+-for Bell Labs internal memoranda and external papers
+-provide most of the facilities needed
+-for a wide range of document preparation.
+-(This memo was prepared with `\-ms'.)
+-There are also packages for viewgraphs,
+-for simulating the older
+-.UL roff
+-formatters on
+-.UC UNIX
+-and
+-.UC GCOS ,
+-and for other special applications.
+-Typically you will find these packages easier to use
+-than
+-.UL troff
+-once you get beyond the most trivial operations;
+-you should always consider them first.
+-.PP
+-In the few cases where existing packages don't do the whole job,
+-the solution is
+-.ul
+-not
+-to write an entirely new set of
+-.UL troff
+-instructions from scratch, but to make small changes
+-to adapt packages that already exist.
+-.WS
+-.PP
+-In accordance with this philosophy of letting someone else
+-do the work,
+-the part of
+-.UL troff
+-described here is only a small part of the whole,
+-although it tries to concentrate on the more useful parts.
+-In any case, there is no attempt to be complete.
+-Rather, the emphasis is on showing how to do simple things,
+-and how to make incremental changes to what already exists.
+-The contents of the remaining sections are:
+-.sp
+-.nf
+-.in .1i
+-.ta .3i
+-\02.  Point sizes and line spacing
+-\03.  Fonts and special characters
+-\04.  Indents and line length
+-\05.  Tabs
+-\06.  Local motions: Drawing lines and characters
+-\07.  Strings
+-\08.  Introduction to macros
+-\09.  Titles, pages and numbering
+-10.   Number registers and arithmetic
+-11.   Macros with arguments
+-12.   Conditionals
+-13.   Environments
+-14.   Diversions
+-      Appendix: Typesetter character set
+-.sp
+-.in 0
+-.fi
+-The
+-.UL troff
+-described here is the C-language version running on
+-.UC UNIX
+-at
+-Murray Hill,
+-as documented in [1].
+-.WS
+-.PP
+-To use
+-.UL troff
+-you have to prepare not only the actual text you want printed,
+-but some information that tells
+-.ul
+-how
+-you want it printed.
+-(Readers who use
+-.UL roff
+-will find the approach familiar.)
+-For
+-.UL troff
+-the text
+-and
+-the formatting information are often intertwined quite intimately.
+-Most commands to
+-.UL troff
+-are placed on a line separate from the text itself,
+-beginning with a period (one command per line).
+-For example,
+-.P1
+-Some text.
+-^ps 14
+-Some more text.
+-.P2
+-will change the `point size',
+-that is,
+-the size of the letters being printed,
+-to `14 point' (one point is 1/72 inch) like this:
+-.P1
+-.fi
+-Some text.
+-.ps 14
+-Some more text.
+-.ps 10
+-.P2
+-.PP
+-Occasionally, though,
+-something special occurs in the middle of a line _
+-to produce
+-.P1
+-Area = \(*p\fIr\fR\|\s8\u2\d\s0
+-.P2
+-you have to type
+-.P1
+-Area = \e(*p\efIr\efR\e\^|\^\es8\eu2\ed\es0
+-.P2
+-(which we will explain shortly).
+-The backslash character
+-.BD  \e 
+-is used 
+-to introduce
+-.UL troff
+-commands and special characters within a line of text.
+//GO.SYSIN DD tt01
+echo tt02
+sed 's/.//' >tt02 <<'//GO.SYSIN DD tt02'
+-.NH
+-Point Sizes; Line Spacing
+-.PP
+-As mentioned above,
+-the command
+-.BD .ps
+-sets the point size.
+-One point is 1/72 inch,
+-so 6-point characters are at most 1/12 inch high,
+-and 36-point characters are \(12 inch.
+-There are 15 point sizes, listed below.
+-.P1 1
+-.ps 6
+-6 point: Pack my box with five dozen liquor jugs.
+-.ps 7
+-.vs 8p
+-7 point: Pack my box with five dozen liquor jugs.
+-.vs 9p
+-.ps 8
+-8 point: Pack my box with five dozen liquor jugs.
+-.vs 10p
+-.ps 9
+-9 point: Pack my box with five dozen liquor jugs.
+-.vs 11p
+-.ps 10
+-10 point: Pack my box with five dozen liquor
+-.vs 12p
+-.ps 11
+-11 point: Pack my box with five dozen 
+-.vs 14p
+-.ps 12
+-12 point: Pack my box with five dozen
+-.vs 16p
+-.ps 14
+-14 point: Pack my box with five
+-.vs 24p
+-\s1616 point\s18 18 point\s20 20 point
+-.vs 40p
+-\s2222\s24 24\s28 28\s36 36
+-.ps 10
+-.vs 12p
+-.P2
+-.PP
+-If the number after
+-.BD .ps 
+-is not one of these
+-legal sizes,
+-it is rounded up to the next valid value,
+-with a maximum of 36.
+-If no number follows
+-.BD .ps ,
+-.UL troff
+-reverts to the previous size, whatever it was.
+-.UL troff
+-begins with point size 10,
+-which is usually fine.
+-This document is in 9 point.
+-.PP
+-The point size can also be changed in the middle of a line
+-or even a word
+-with the in-line command
+-.BD \es .
+-To produce
+-.P1
+-\s8UNIX\s10 runs on a \s8PDP-\s1011/45
+-.P2
+-type
+-.P1
+-\es8UNIX\es10 runs on a \es8PDP-\es1011/45
+-.P2
+-As above,
+-.BD \es 
+-should be followed by a legal point size,
+-except that
+-.BD \es0 
+-causes the size to revert to
+-its previous value.
+-Notice that
+-.BD \es1011
+-can be understood correctly as `size 10, followed by an 11', if the size is legal,
+-but not otherwise.
+-Be cautious with similar constructions.
+-.PP
+-Relative size changes are also legal and useful:
+-.P1
+-\es\-2UNIX\es+2
+-.P2
+-temporarily decreases the size, whatever it is, by two points, then
+-restores it.
+-Relative size changes have the advantage that the size difference
+-is independent of the starting size of the document.
+-The amount of the relative change is restricted
+-to a single digit.
+-.WS
+-.PP
+-The other parameter that determines what the type looks like
+-is the spacing between lines,
+-which is set independently of the point size.
+-Vertical spacing is measured from the bottom of one line to
+-the bottom of the next.
+-The command to control vertical spacing is
+-.BD .vs .
+-For running text, it is usually best to set the vertical spacing
+-about 20% bigger than the character size.
+-For example, so far in this document, we have used
+-``9 on 11'', that is,
+-.P1
+-^ps 9
+-^vs 11p
+-.P2
+-If we changed to
+-.P1
+-^ps 9
+-^vs 9p
+-.P2
+-.vs 9p
+-.ne 3
+-the running text would look like this.
+-After a few lines, you will agree it looks a little cramped.
+-The right vertical spacing is partly a matter of taste, depending on how
+-much text you want to squeeze into a given space,
+-and partly a matter of traditional printing style.
+-By default,
+-.UL troff
+-uses 10 on 12.
+-.PP
+-.vs 14p
+-.ps 12
+-Point size and vertical spacing make a substantial difference in the amount of text
+-per square inch.
+-This is 12 on 14.
+-.ne 2
+-.PP
+-.ne 2
+-.ps 6
+-.vs 7p
+-Point size and vertical spacing make a substantial difference in the amount of text
+-per square inch.
+-For example,
+-10 on 12 uses about twice as much space as 7 on 8.
+-This is 6 on 7, which is even smaller.
+-It packs a lot more words per line,
+-but you can go blind trying to read it.
+-.PP
+-When used without arguments,
+-.BD .ps
+-and
+-.BD .vs
+-revert to the previous size and vertical spacing
+-respectively.
+-.WS
+-.PP
+-The command
+-.BD .sp
+-is used to get extra vertical space.
+-Unadorned, 
+-it gives you one extra blank line (one
+-.BD .vs ,
+-whatever that has been set to).
+-Typically, that's more or less than you want,
+-so
+-.BD .sp
+-can be followed by
+-information about how much space you want _
+-.P1
+-^sp 2i
+-.P2
+-means `two inches of vertical space'.
+-.P1
+-^sp 2p
+-.P2
+-means `two points of vertical space';
+-and
+-.P1
+-^sp 2
+-.P2
+-means `two vertical spaces' _ two of whatever
+-.BD .vs
+-is set to
+-(this can also be made explicit with
+-.BD .sp\ 2v );
+-.UL troff
+-also understands decimal fractions in most places,
+-so
+-.P1
+-^sp 1.5i
+-.P2
+-is a space of 1.5 inches.
+-These same scale factors can be used after
+-.BD .vs
+-to define line spacing, and in fact after most commands
+-that deal with physical dimensions.
+-.PP
+-It should be noted that all size numbers are converted internally
+-to `machine units', which are 1/432 inch
+-(1/6 point).
+-For most purposes, this is enough resolution
+-that you don't have to worry about the accuracy of the representation.
+-The situation is not quite so good vertically,
+-where resolution is 1/144 inch
+-(1/2 point).
+//GO.SYSIN DD tt02
+echo tt03
+sed 's/.//' >tt03 <<'//GO.SYSIN DD tt03'
+-.NH
+-Fonts and Special Characters
+-.PP
+-.UL troff
+-and the typesetter allow four different fonts at any one time.
+-Normally three fonts (Times roman, italic and bold) and one collection of special characters
+-are permanently
+-mounted.
+-.P1 2
+-.ft R
+-abcdefghijklmnopqrstuvwxyz 0123456789
+-ABCDEFGHIJKLMNOPQRSTUVWXYZ
+-.ft I
+-abcdefghijklmnopqrstuvwxyz 0123456789
+-ABCDEFGHIJKLMNOPQRSTUVWXYZ
+-.ft B
+-abcdefghijklmnopqrstuvwxyz 0123456789
+-ABCDEFGHIJKLMNOPQRSTUVWXYZ
+-.ft R
+-.P2
+-The
+-greek, mathematical symbols and miscellany
+-of the special font are
+-listed in Appendix A.
+-.PP
+-.UL troff
+-prints in roman unless told otherwise.
+-To switch into bold, use
+-the
+-.BD .ft
+-command
+-.P1
+-^ft B
+-.P2
+-and for italics,
+-.P1
+-^ft I
+-.P2
+-To return to roman, use
+-.BD .ft\ R ;
+-to return to the previous font,
+-whatever it was,
+-use either
+-.BD .ft\ P
+-or just
+-.BD .ft  .
+-The `underline' command
+-.P1
+-^ul
+-.P2
+-causes the next input line to print in italics.
+-.BD .ul
+-can be followed by a count to
+-indicate that more than one line is to be italicized.
+-.PP
+-Fonts can also be changed within a line or word
+-with the in-line command
+-.BD \ef :
+-.P1
+-\fBbold\fIface\fR text
+-.P2
+-is produced by
+-.P1
+-\efBbold\efIface\efR text
+-.P2
+-If you want to do this so the previous font, whatever it was,
+-is left undisturbed, insert extra
+-.BD \efP
+-commands, like this:
+-.P1
+-\efBbold\efP\efIface\efP\efR text\efP
+-.P2
+-Because only the immediately previous font is remembered,
+-you have to restore the previous font after each change
+-or you can lose it.
+-The same is true of 
+-.BD .ps
+-and
+-.BD .vs
+-when used without an argument.
+-.PP
+-There are other fonts available besides the standard set,
+-although you can still use only four at any given time.
+-The command
+-.BD .fp
+-tells
+-.UL troff
+-what fonts are physically mounted on the typesetter:
+-.P1
+-^fp 3 H
+-.P2
+-says that the Helvetica font is mounted on position 3.
+-(For a complete list of fonts and what they look like,
+-see the 
+-.UL troff 
+-manual.)
+-Appropriate
+-.BD .fp
+-commands should appear at the beginning of your document
+-if you do not use the standard fonts.
+-.PP
+-It is possible to make a document relatively independent
+-of the actual fonts used to print it
+-by using font numbers instead of names;
+-for example,
+-.BD \ef3
+-and
+-.BD .ft~3
+-mean `whatever font is mounted at position 3',
+-and thus work for any setting.
+-Normal settings are roman font on 1, italic on 2,
+-bold on 3,
+-and special on 4.
+-.PP
+-There is also a way to get `synthetic' bold fonts
+-by overstriking letters with a slight offset.
+-Look at the
+-.BD .bd
+-command in [1].
+-.WS
+-.PP
+-Special characters have four-character names beginning with
+-.BD \e( ,
+-and they may be inserted anywhere.
+-For example,
+-.P1
+-\(14 + \(12 = \(34
+-.P2
+-is produced by
+-.P1
+-\e(14 + \e(12 = \e(34
+-.P2
+-In particular,
+-greek letters are all of the form
+-.BD  \e(*\- ,
+-where
+-.BD \-
+-is an upper or lower case roman letter
+-reminiscent of the greek.
+-Thus
+-to get
+-.P1
+-\(*S(\(*a\(mu\(*b) \(-> \(if
+-.P2
+-in bare
+-.UL troff
+-we have to type
+-.P1
+-\e(*S(\e(*a\e(mu\e(*b) \e(\(mi> \e(if
+-.P2
+-That line is unscrambled as follows:
+-.P1
+-.ta 1i 2i 3i
+-\e(*S \(*S
+-(     (
+-\e(*a \(*a
+-\e(mu \(mu
+-\e(*b \(*b
+-)     )
+-\e(\(mi>      \(->
+-\e(if \(if
+-.P2
+-A complete list of these special names occurs in Appendix A.
+-.PP
+-In
+-.UL eqn 
+-[2]
+-the same effect can be achieved with the input
+-.P1
+-SIGMA ( alpha times beta ) \-> inf
+-.P2
+-which is less concise, but clearer to the uninitiated.
+-.PP
+-Notice that
+-each
+-four-character name is a single character
+-as far as
+-.UL troff
+-is concerned _
+-the
+-`translate' command
+-.P1
+-^tr \e(mi\e(em
+-.P2
+-is perfectly clear, meaning
+-.P1
+-^tr \(mi\(em
+-.P2
+-that is, to translate \(mi into \(em.
+-.PP
+-Some characters are automatically translated into others:
+-grave  \(ga  and acute  \(aa  accents (apostrophes) become open and close single quotes
+-`~';
+-the combination of ``...'' is generally preferable to the double quotes "...".
+-Similarly a typed minus sign becomes a hyphen -.
+-To print an explicit \- sign, use
+-.BD \e- .
+-To get a backslash printed, use
+-.BD \ee .
+//GO.SYSIN DD tt03
+echo tt04
+sed 's/.//' >tt04 <<'//GO.SYSIN DD tt04'
+-.NH
+-Indents and Line Lengths
+-.PP
+-.UL troff
+-starts with a line length of 6.5 inches,
+-too wide for 8\(12\(mu11 paper.
+-To reset the line length,
+-use
+-the
+-.BD .ll
+-command, as in
+-.P1
+-^ll 6i
+-.P2
+-As with
+-.BD .sp ,
+-the actual length can be specified in several ways;
+-inches are probably the most intuitive.
+-.PP
+-The maximum line length provided by the typesetter is 7.5 inches, by the way.
+-To use the full width, you will have to reset the default physical left margin (``page offset''),
+-which is normally slightly less than one inch from the left edge
+-of the paper.
+-This is done by the
+-.BD .po
+-command.
+-.P1
+-^po 0
+-.P2
+-sets the offset as far to the left as it will go.
+-.WS
+-.PP
+-The indent command
+-.BD .in
+-causes the left margin to be indented
+-by some specified amount from the page offset.
+-If we use
+-.BD .in
+-to move the left margin in,
+-and
+-.BD .ll
+-to move the right margin to the left,
+-we can
+-make offset blocks of text:
+-.P1
+-^in 0.3i
+-^ll \(mi0.3i
+-text to be set into a block
+-^ll +0.3i
+-^in \(mi0.3i
+-.P2
+-will create a block that looks like this:
+-.P1
+-.fi
+-.ll -0.3i
+-Pater noster qui est in caelis sanctificetur nomen tuum;
+-adveniat regnum tuum; fiat voluntas tua, sicut in caelo,
+-et in terra. ...
+-Amen.
+-.ll +0.3i
+-.P2
+-Notice the use of `+' and `\(mi'
+-to specify the amount of change.
+-These change the previous setting by the specified amount,
+-rather than just overriding it.
+-The distinction is quite important:
+-.BD .ll\ +1i
+-makes lines one inch longer;
+-.BD .ll\ 1i
+-makes them one inch
+-.ul
+-long.
+-.PP
+-With 
+-.BD .in ,
+-.BD .ll
+-and
+-.BD .po ,
+-the previous value is used if no argument is specified.
+-.PP
+-To indent a single line, use the `temporary indent'
+-command
+-.BD .ti .
+-For example, all paragraphs in this memo
+-effectively begin with the command
+-.P1
+-^ti 3
+-.P2
+-Three of what?
+-The default unit for
+-.BD .ti ,
+-as for most horizontally oriented commands
+-.BD .ll , (
+-.BD .in ,
+-.BD .po ),
+-is ems;
+-an em is roughly the width of the letter `m'
+-in the current point size.
+-(Precisely, a em in size
+-.ul
+-p
+-is
+-.ul
+-p
+-points.)
+-Although inches are usually clearer than ems to people who don't set type
+-for a living,
+-ems have a place:
+-they are a measure of size that is proportional to the current point size.
+-If you want to make text that keeps its proportions
+-regardless of point size,
+-you should use ems for all dimensions.
+-Ems can be specified as scale factors directly,
+-as in
+-.BD .ti\ 2.5m .
+-.PP
+-Lines can also be indented negatively
+-if the indent is already positive:
+-.P1
+-^ti \(mi0.3i
+-.P2
+-causes the next line to be moved back three tenths of an inch.
+-Thus to make a decorative initial capital,
+-we indent the whole paragraph, then move the letter `P' back with
+-a
+-.BD .ti
+-command:
+-.P1
+-.ll -0.3i
+-.fi
+-.in +.3i
+-.ti -0.3i
+-\s36\v'2'P\v'-2'\s0ater noster qui est in caelis sanctificetur
+-nomen tuum;
+-adveniat regnum tuum;
+-'in -.3i
+-fiat voluntas tua,
+-sicut in caelo, et in terra. ...
+-Amen.
+-.ll +0.3i
+-.P2
+-Of course, there is also some trickery to make the `P'
+-bigger (just a `\es36P\es0'),
+-and to move it
+-down from its normal position
+-(see the section on local motions).
+//GO.SYSIN DD tt04
+echo tt05
+sed 's/.//' >tt05 <<'//GO.SYSIN DD tt05'
+-.NH
+-Tabs
+-.PP
+-Tabs
+-(the \s8ASCII\s0 `horizontal tab' character)
+-can be used to produce output in columns,
+-or to set the horizontal position of output.
+-Typically
+-tabs are used only in unfilled text.
+-Tab stops are set by default every half inch from the
+-current indent,
+-but
+-can be changed by the
+-.BD .ta
+-command.
+-To set stops every inch, for example,
+-.P1
+-^ta 1i 2i 3i 4i 5i 6i
+-.P2
+-.PP
+-Unfortunately the stops are left-justified only
+-(as on a typewriter),
+-so lining up columns of right-justified numbers can be painful.
+-If you have many numbers,
+-or if you need more complicated table layout,
+-.ul
+-don't
+-use
+-.UL troff 
+-directly;
+-use the
+-.UL tbl
+-program described in [3].
+-.PP
+-For a handful of numeric columns, you can do it this way:
+-Precede every number by enough blanks to make it line up
+-when typed.
+-.P1
+-^nf
+-^ta 1i 2i 3i
+-\0\01\0\fItab\fR\0\0\02\0\fItab\fR\0\0\03
+-\040\0\fItab\fR\0\050\0\fItab\fR\0\060
+-700\0\fItab\fR\0800\0\fItab\fR\0900
+-^fi
+-.P2
+-Then change each leading blank into the string
+-.BD \e0 .
+-This is a character that does not print, but that has
+-the same width as a digit.
+-When printed, this will produce
+-.P1
+-.ta 1i 2i 3i
+-\0\01 \0\02   \0\03
+-\040  \050    \060
+-700   800     900
+-.P2
+-.PP
+-It is also possible to fill up tabbed-over space with
+-some character other than blanks by setting the `tab replacement character'
+-with the
+-.BD .tc
+-command:
+-.P1
+-^ta 1.5i 2.5i
+-^tc \e(ru     (\e(ru is "\(ru")
+-Name \fItab\fR Age \fItab\fR 
+-.P2
+-produces
+-.P1 3
+-.ta 1.5i 2.5i
+-.tc \(ru
+-Name   Age    
+-.tc
+-.P2
+-To reset the tab replacement character to a blank, use
+-.BD .tc
+-with no argument.
+-(Lines can also be drawn with the
+-.BD \el
+-command, described in Section 6.)
+-.PP
+-.UL troff
+-also provides a very general mechanism called `fields'
+-for setting up complicated columns.
+-(This is used by
+-.UL tbl ).
+-We will not go into it in this paper.
+//GO.SYSIN DD tt05
+echo tt06
+sed 's/.//' >tt06 <<'//GO.SYSIN DD tt06'
+-.NH
+-Local Motions: Drawing lines and characters
+-.PP
+-Remember `Area = \(*pr\u2\d' and the big `P'
+-in the Paternoster.
+-How are they done?
+-.UL troff
+-provides a host of commands for placing characters of any size
+-at any place.
+-You can use them to draw special characters 
+-or to tune your output for a particular appearance.
+-Most of these commands are straightforward, but messy to read
+-and tough to type correctly.
+-.PP
+-If you won't use 
+-.UL eqn ,
+-subscripts and superscripts are most easily done with
+-the half-line local motions
+-.BD \eu
+-and
+-.BD \ed .
+-To go back up the page half a point-size, insert a
+-.BD \eu
+-at the desired place;
+-to go down, insert a
+-.BD \ed .
+-.BD \eu \& (
+-and
+-.BD \ed
+-should always
+-be used in pairs, as explained below.)
+-Thus
+-.P1
+-Area = \e(*pr\eu2\ed
+-.P2
+-produces
+-.P1
+-Area = \(*pr\u2\d
+-.P2
+-To make the `2' smaller, bracket it with
+-.BD \es\-2...\es0 .
+-Since
+-.BD \eu
+-and
+-.BD \ed
+-refer to the current point size,
+-be sure to put them either both inside or both outside
+-the size changes,
+-or you will get an unbalanced vertical motion.
+-.PP
+-Sometimes the space given by
+-.BD \eu
+-and
+-.BD \ed
+-isn't the right amount.
+-The 
+-.BD \ev
+-command can be used to request an arbitrary amount of vertical motion.
+-The in-line command
+-.P1
+-\ev'(amount)'
+-.P2
+-causes motion up or down the page by the amount specified in
+-`(amount)'.
+-For example, to move the `P' down, we used
+-.P1 2
+-.ta 1i
+-^in +0.6i     (move paragraph in)
+-^ll \-0.3i    (shorten lines)
+-^ti \-0.3i    (move P back)
+-\ev'2'\es36P\es0\ev'\-2'ater noster qui est
+-in caelis ...
+-.P2
+-A minus sign causes upward motion, while
+-no sign or a plus sign means down the page.
+-Thus
+-.BD \ev\(fm\-2\(fm
+-causes an upward vertical motion 
+-of two line spaces.
+-.PP
+-There are many other ways to specify the amount of motion _
+-.P1
+-\ev'0.1i'
+-\ev'3p'
+-\ev'\-0.5m'
+-.P2
+-and so on are all legal.
+-Notice that the scale specifier
+-.BD i
+-or
+-.BD p
+-or
+-.BD m
+-goes inside the quotes.
+-Any character can be used in place of the quotes;
+-this is also true of all other
+-.UL troff
+-commands described in this section.
+-.PP
+-Since
+-.UL troff
+-does not take within-the-line vertical motions into account
+-when figuring out where it is on the page,
+-output lines can have unexpected positions
+-if the left and right ends aren't at the same
+-vertical position.
+-Thus
+-.BD \ev ,
+-like
+-.BD \eu
+-and
+-.BD \ed ,
+-should always balance upward vertical motion in a line with
+-the same amount in the downward direction.
+-.PP
+-Arbitrary horizontal motions are also available _
+-.BD \eh
+-is quite analogous to
+-.BD \ev ,
+-except that the default scale factor is ems instead of line spaces.
+-As an example,
+-.P1
+-\eh'\-0.1i'
+-.P2
+-causes a backwards motion of a tenth of an inch.
+-As a practical matter, consider printing the mathematical symbol
+-`>>'.
+-The default spacing is too wide, so
+-.UL eqn
+-replaces this by
+-.P1
+->\eh'\-0.3m'>
+-.P2
+-to produce >\h'-.3m'>.
+-.PP
+-Frequently
+-.BD \eh
+-is used with the `width function'
+-.BD \ew
+-to generate motions equal to the width
+-of some character string.
+-The construction
+-.P1
+-\ew'thing'
+-.P2
+-is a number equal to the width of `thing' in machine units
+-(1/432 inch).
+-All
+-.UL troff
+-computations are ultimately done in these units.
+-To move horizontally the width of an `x',
+-we can say
+-.P1
+-\eh'\ew'x'u'
+-.P2
+-As we mentioned above,
+-the default scale factor for
+-all horizontal dimensions is
+-.BD m ,
+-ems, so here we must have the
+-.BD u
+-for machine units,
+-or the motion produced will be far too large.
+-.UL troff
+-is quite happy with the nested quotes, by the way,
+-so long as you don't leave any out.
+-.PP
+-As a live example of this kind of construction,
+-all of the command names in the text, like
+-.BD .sp ,
+-were done by overstriking with a slight offset.
+-The commands for
+-.BD .sp
+-are
+-.P1
+-^sp\eh'\-\ew'.sp'u'\eh'1u'.sp
+-.P2
+-That is, put out `.sp', move left by the width of `.sp',
+-move right 1 unit, and print
+-`.sp' again.
+-(Of course there is a way to avoid typing that much input
+-for each command name, which we will discuss in Section 11.)
+-.WS
+-.PP
+-There are also several special-purpose
+-.UL troff
+-commands for local motion.
+-We have already seen
+-.BD \e0 ,
+-which is an unpaddable white space
+-of the same width as a digit.
+-`Unpaddable' means that it will never be widened
+-or split across a line by line justification and filling.
+-There is also
+-.BD \e (blank),
+-.tr ^^
+-which is an unpaddable character the width of a space,
+-.BD \e| ,
+-which is half that width,
+-.BD \e^ ,
+-which is one quarter of the width of a space,
+-and
+-.BD \e& ,
+-which has zero width.
+-.tr ^.
+-(This last one is useful, for example, in entering
+-a text line which would otherwise begin with a `.'.)
+-.PP
+-The command
+-.BD \eo ,
+-used like
+-.P1
+-\eo'set of characters'
+-.P2
+-causes (up to 9)
+-characters to be overstruck,
+-centered on the widest.
+-This is nice for accents, as in
+-.P1 2
+-syst\eo"e\e(ga"me t\eo"e\e(aa"l\eo"e\e(aa"phonique
+-.P2
+-which makes
+-.P1
+-syst\o"e\(ga"me t\o"e\(aa"l\o"e\(aa"phonique
+-.P2
+-The accents are
+-.BD \e(ga
+-and
+-.BD \e(aa ,
+-or
+-.BD \e\` 
+-and
+-.BD \e\' ;
+-remember that each is just one character to
+-.UL troff .
+-.PP
+-You can make your own overstrikes with another special convention,
+-.BD \ez ,
+-the zero-motion command.
+-.BD \ezx
+-suppresses the normal horizontal motion
+-after printing the single character
+-.BD x ,
+-so another character can be laid on top of it.
+-Although sizes can be changed within
+-.BD \eo ,
+-it centers the characters on the widest,
+-and
+-there can be no horizontal or vertical motions,
+-so
+-.BD \ez
+-may be the only way to get what you want:
+-.P1
+-.sp 2
+-\s8\z\(sq\s14\z\(sq\s22\z\(sq\s36\(sq
+-.P2
+-is produced by
+-.P1
+-^sp 2
+-\es8\ez\e(sq\es14\ez\e(sq\es22\ez\e(sq\es36\e(sq
+-.P2
+-The
+-.BD .sp
+-is needed to leave room for the result.
+-.PP
+-As another example, an extra-heavy semicolon
+-that looks like
+-.P1
+-\s+6\z,\v'-0.25m'.\v'0.25m'\s0  instead of  ;  or  \s+6;\s0
+-.P2
+-can be constructed with a big comma and a big period above it:
+-.P1
+-\es+6\ez,\ev'\(mi0.25m'.\ev'0.25m'\es0 
+-.P2
+-`0.25m' is an empirical constant.
+-.PP
+-A more ornate overstrike is given by the bracketing function
+-.BD \eb ,
+-which piles up characters vertically,
+-centered on the current baseline.
+-Thus we can get big brackets,
+-constructing them with piled-up smaller pieces:
+-.P1
+-.sp
+-.ne 3
+-\b'\(lt\(lk\(lb' \b'\(lc\(lf' x \b'\(rc\(rf' \b'\(rt\(rk\(rb'
+-.sp
+-.P2
+-by typing in only this:
+-.P1 0
+-\&^sp
+-\eb\(fm\e(lt\e(lk\e(lb\(fm \eb\(fm\e(lc\e(lf\(fm x \eb\(fm\e(rc\e(rf\(fm \eb\(fm\e(rt\e(rk\e(rb\(fm
+-.P2
+-.PP
+-.UL troff
+-also provides a convenient facility for drawing horizontal and vertical
+-lines of arbitrary length with arbitrary characters.
+-.BD \el\(fm1i\(fm
+-draws a line one inch long, like this:
+-\l'1i'\|.
+-The length can be followed by
+-the character to use if the \(ru isn't appropriate;
+-.BD \el\(fm0.5i.\(fm
+-draws a half-inch line of dots: \l'.5i.'.
+-The construction
+-.BD \eL
+-is entirely analogous,
+-except that it draws a vertical line instead of horizontal.
+//GO.SYSIN DD tt06
+echo tt07
+sed 's/.//' >tt07 <<'//GO.SYSIN DD tt07'
+-.NH
+-Strings
+-.PP
+-Obviously if a paper contains a large number of occurrences
+-of an acute accent over a letter `e',
+-typing
+-.BD \eo"e\e\'"
+-for each \*e
+-would be a great nuisance.
+-.PP
+-Fortunately,
+-.UL troff
+-provides a way in which you can store an arbitrary
+-collection of text in a `string',
+-and thereafter use the string name as a shorthand
+-for its contents.
+-Strings are one of several
+-.UL troff
+-mechanisms whose judicious use
+-lets you type a document
+-with less effort and organize
+-it
+-so that extensive format changes
+-can be made with few editing changes.
+-.PP
+-A reference to a string is replaced by whatever
+-text
+-the string was defined as.
+-Strings are defined with the command
+-.BD .ds .
+-The line
+-.P1
+-\&^ds e \eo"e\e'"
+-.P2
+-defines the string
+-.BD e
+-to have the value
+-.BD \eo"e\e\'"
+-.PP
+-String names may be either one or two characters long,
+-and are referred to by
+-.BD \e*x
+-for one character names or
+-.BD \e*(xy
+-for two character names.
+-Thus to get
+-t\*el\*ephone,
+-given the definition of the string
+-.BD e
+-as above,
+-we can say
+-t\e*el\e*ephone.
+-.PP
+-If a string must begin with blanks, define it as
+-.P1
+-\&.ds xx "      text
+-.P2
+-The double quote signals the beginning of the definition.
+-There is no trailing quote;
+-the end of the line terminates the string.
+-.PP
+-A string may actually be several lines long;
+-if
+-.UL troff
+-encounters a 
+-.BD \e
+-at the end of
+-.ul
+-any
+-line, it is thrown away and the next line
+-added to the current one.
+-So you can make a long string simply by ending each line
+-but the last with a backslash:
+-.P1
+-\&^ds xx this \e
+-is a very \e
+-long string
+-.P2
+-.PP
+-Strings may be defined in terms of other strings, or even in terms of themselves;
+-we will discuss some of these possibilities later.
+//GO.SYSIN DD tt07
+echo tt08
+sed 's/.//' >tt08 <<'//GO.SYSIN DD tt08'
+-.NH
+-Introduction to Macros
+-.PP
+-Before we can go much further in
+-.UL troff ,
+-we need to learn a bit about the
+-macro
+-facility.
+-In its simplest form, a macro is just a shorthand notation
+-quite similar to a string.
+-Suppose we want every paragraph to start
+-in exactly the same way _
+-with a space and a temporary indent of two ems:
+-.P1
+-^sp
+-^ti +2m
+-.P2
+-Then to save typing, we would like to collapse these into
+-one shorthand line,
+-a
+-.UL troff
+-`command' like
+-.P1
+-^PP
+-.P2
+-that would be treated by
+-.UL troff
+-exactly as
+-.P1
+-^sp
+-^ti +2m
+-.P2
+-.BD .PP
+-is called a
+-.ul
+-macro.
+-The way we tell
+-.UL troff
+-what
+-.BD .PP
+-means is to
+-.ul
+-define
+-it with the
+-.BD .de
+-command:
+-.P1
+-^de PP
+-^sp
+-^ti +2m
+-^^
+-.P2
+-The first line names the macro
+-(we used
+-.BD .PP ' `
+-for `paragraph',
+-and upper case so it wouldn't conflict with
+-any name that
+-.UL troff
+-might
+-already know about).
+-The last line
+-.BD ..
+-marks the end of the definition.
+-In between is the text,
+-which is simply inserted whenever
+-.UL troff
+-sees the `command'
+-or macro call
+-.P1
+-^PP
+-.P2
+-A macro
+-can contain any mixture of text and formatting commands.
+-.PP
+-The definition of
+-.BD .PP
+-has to precede its first use;
+-undefined macros are simply ignored.
+-Names are restricted to one or two characters.
+-.PP
+-Using macros for commonly occurring sequences of commands
+-is critically important.
+-Not only does it save typing,
+-but it makes later changes much easier.
+-Suppose we decide that the paragraph indent is too small,
+-the vertical space is much too big,
+-and roman font should be forced.
+-Instead of changing the whole document,
+-we need only change the definition of
+-.BD .PP
+-to
+-something like
+-.P1
+-^de PP        \e" paragraph macro
+-^sp 2p
+-^ti +3m
+-^ft R
+-^^
+-.P2
+-and the change takes
+-effect everywhere we used
+-.BD .PP .
+-.PP
+-.BD \e"
+-is a
+-.UL troff
+-command that causes the rest of the line to be ignored.
+-We use it here to add comments to the macro
+-definition
+-(a wise idea once definitions get complicated).
+-.PP
+-As another example of macros,
+-consider these two which start and end a block of offset,
+-unfilled text, like most of the examples in this paper:
+-.P1
+-^de BS        \e" start indented block
+-^sp
+-^nf
+-^in +0.3i
+-^^
+-^de BE        \e" end indented block
+-^sp
+-^fi
+-^in \(mi0.3i
+-^^
+-.P2
+-Now we can surround text like
+-.P1
+-Copy to
+-John Doe
+-Richard Roberts
+-Stanley Smith
+-.P2
+-by the commands
+-.BD .BS
+-and
+-.BD .BE ,
+-and it will come out as it did above.
+-Notice that we indented by
+-.BD .in\ +0.3i
+-instead of
+-.BD .in\ 0.3i .
+-This way we can nest our uses of
+-.BD .BS
+-and
+-.BD BE
+-to get blocks within blocks.
+-.PP
+-If later on we decide that the indent
+-should be 0.5i, then it is only necessary to
+-change the definitions of
+-.BD .BS
+-and
+-.BD .BE ,
+-not the whole paper.
+//GO.SYSIN DD tt08
+echo tt09
+sed 's/.//' >tt09 <<'//GO.SYSIN DD tt09'
+-.NH
+-Titles, Pages and Numbering
+-.PP
+-This is an area where things get tougher,
+-because nothing is done for you automatically.
+-Of necessity, some of this section is a cookbook,
+-to be copied literally until you get some experience.
+-.PP
+-Suppose you want a title at the top of each page,
+-saying just
+-.sp 3p
+-.lt 2.8i
+-.tl '~~~~left top'center top'right top~~~~'
+-.lt
+-.sp 3p
+-In
+-.UL roff ,
+-one can say
+-.P1 2
+-^he 'left top'center top'right top'
+-^fo 'left bottom'center bottom'right bottom'
+-.P2
+-to get headers and footers automatically on every page.
+-Alas, this doesn't work in
+-.UL troff ,
+-a serious hardship for the novice.
+-Instead you have to do a lot of specification.
+-.PP
+-You have to say what the actual title is (easy);
+-when to print it (easy enough);
+-and what to do at and around the title line (harder).
+-Taking these in reverse order,
+-first we define a macro
+-.BD .NP
+-(for `new page') to process
+-titles and the like at the end of one page
+-and the beginning of the next:
+-.P1
+-^de NP
+-\(fmbp
+-\(fmsp 0.5i
+-\&.tl 'left top'center top'right top'
+-\(fmsp 0.3i
+-^^
+-.P2
+-To make sure we're at the top of a page,
+-we issue a `begin page' command
+-.BD \(fmbp ,
+-which causes a skip to top-of-page
+-(we'll explain the
+-.BD \(fm
+-shortly).
+-Then we space down half an inch,
+-print the title
+-(the use of
+-.BD .tl
+-should be self explanatory; later we will discuss parameterizing the titles),
+-space another 0.3 inches,
+-and we're done.
+-.PP
+-To ask for
+-.BD .NP
+-at the bottom of each page,
+-we have to say something like
+-`when the text is within an inch
+-of the bottom of the page,
+-start the processing
+-for a new page.'
+-This is done with a `when' command
+-.BD .wh :
+-.P1
+-^wh  \-1i  NP
+-.P2
+-(No `.' is used before NP;
+-this is simply the name of a macro, not a macro call.)
+-The minus sign means
+-`measure up from the bottom of the page',
+-so
+-`\-1i' means `one inch from the bottom'.
+-.PP
+-The
+-.BD .wh
+-command appears in the input outside the definition of
+-.BD .NP ;
+-typically the input would be
+-.P1
+-^de NP
+-^^^
+-^^
+-^wh \-1i NP
+-.P2
+-.PP
+-Now what happens?
+-As text is actually being output,
+-.UL troff 
+-keeps track of its vertical position on the page,
+-and after a line is printed within one inch from the bottom,
+-the
+-.BD .NP
+-macro is activated.
+-(In the jargon, the
+-.BD .wh
+-command sets a
+-.ul
+-trap
+-at the specified place,
+-which is `sprung' when that point is passed.)
+-.BD .NP
+-causes a skip to the top of the next page
+-(that's what the
+-.BD \(fmbp
+-was for),
+-then prints the title with the appropriate margins.
+-.PP
+-Why
+-.BD \(fmbp
+-and
+-.BD \(fmsp 
+-instead of
+-.BD .bp
+-and
+-.BD .sp ?
+-The answer is that
+-.BD .sp
+-and
+-.BD .bp ,
+-like several other commands,
+-cause a
+-.ul
+-break
+-to take place.
+-That is, all the input text collected but not yet printed
+-is flushed out as soon as possible,
+-and the next input line is guaranteed to start
+-a new line of output.
+-If we had used
+-.BD .sp
+-or
+-.BD .bp
+-in the
+-.BD .NP
+-macro,
+-this would cause a break in the middle
+-of the current output line when a new page is started.
+-The effect would be to print the left-over part of that line
+-at the top of the page, followed by the next input line on a new output line.
+-This is
+-.ul
+-not
+-what we want.
+-Using
+-.BD \(fm
+-instead of
+-.BD . 
+-for a command
+-tells
+-.UL troff 
+-that
+-no break is to take place _
+-the output line
+-currently being filled
+-should
+-.ul
+-not
+-be forced out before the space or new page.
+-.PP
+-The list of commands that cause a break 
+-is short and natural:
+-.P1
+-^bp   ^br   ^ce   ^fi   ^nf   ^sp   ^in   ^ti
+-.P2
+-All others cause
+-.ul
+-no
+-break,
+-regardless of whether you use a
+-.BD .
+-or a 
+-.BD \(fm .
+-If you really need a break, add a
+-.BD .br 
+-command at the appropriate place.
+-.PP
+-One other thing to beware of _
+-if you're changing fonts or point sizes a lot,
+-you may find that
+-if you cross a page boundary
+-in an unexpected font or size,
+-your titles come out in that size and font
+-instead of what you intended.
+-Furthermore, the length of a title is independent of the current line length,
+-so titles will come out at the default length of 6.5 inches
+-unless you change it,
+-which is done with the
+-.BD .lt
+-command.
+-.PP
+-There are several ways to fix the problems of point sizes
+-and fonts in titles.
+-For the simplest applications, we can change
+-.BD .NP 
+-to set the proper size and font for the title,
+-then restore the previous values, like this:
+-.P1 2
+-.ta .8i
+-^de NP
+-\(fmbp
+-\(fmsp 0.5i
+-^ft R \e" set title font to roman
+-^ps 10        \e" and size to 10 point
+-^lt 6i        \e" and length to 6 inches
+-^tl 'left'center'right'
+-^ps   \e" revert to previous size
+-^ft P \e" and to previous font
+-\(fmsp 0.3i
+-^^
+-.P2
+-.PP
+-This version of
+-.BD .NP
+-does
+-.ul
+-not
+-work if the fields in the
+-.BD .tl
+-command contain size or font changes.
+-To cope with that
+-requires
+-.UL troff 's
+-`environment' mechanism,
+-which we will discuss in Section 13.
+-.PP
+-To get a footer at the bottom of a page,
+-you can modify
+-.BD .NP
+-so it does
+-some processing before
+-the
+-.BD \(fmbp
+-command,
+-or split the job into a footer macro invoked
+-at the bottom margin and a header macro invoked
+-at the top of the page.
+-These variations are left as exercises.
+-.WS
+-.PP
+-Output page numbers are computed automatically
+-as each page is produced (starting at 1),
+-but no numbers are printed unless you ask for them explicitly.
+-To get page numbers printed,
+-include the character
+-.BD %
+-in the
+-.BD .tl
+-line at
+-the position where you want the number to appear.
+-For example
+-.P1
+-^tl ''- % -''
+-.P2
+-centers the page number inside hyphens, as on this page.
+-You can set the page number at any time
+-with either
+-.BD .bp\ n ,
+-which immediately starts a new page numbered
+-.BD n ,
+-or with
+-.BD .pn\ n ,
+-which sets the page number for the next page
+-but doesn't cause a skip to the new page.
+-Again,
+-.BD .bp\ +n
+-sets the page number to
+-.BD n
+-more than its current value;
+-.BD .bp
+-means
+-.BD .bp\ +1 .
+//GO.SYSIN DD tt09
+echo tt10
+sed 's/.//' >tt10 <<'//GO.SYSIN DD tt10'
+-.NH
+-Number Registers and Arithmetic
+-.PP
+-.UL troff
+-has a facility for doing arithmetic,
+-and for defining and using variables with numeric values,
+-called
+-.ul
+-number registers.
+-Number registers, like strings and macros, can be useful in setting up a document
+-so it is easy to change later.
+-And of course they serve for any sort of arithmetic computation.
+-.PP
+-Like strings, number registers have one or two character names.
+-They are set by the
+-.BD .nr
+-command,
+-and are referenced anywhere by
+-.BD \enx
+-(one character name) or
+-.BD \en(xy
+-(two character name).
+-.PP
+-There are quite a few pre-defined number registers maintained by
+-.UL troff ,
+-among them
+-.BD %
+-for the current page number;
+-.BD nl
+-for the current vertical position on the page;
+-.BD dy ,
+-.BD mo
+-and
+-.BD yr
+-for the current day, month and year; and
+-.BD .s
+-and
+-.BD .f
+-for the current size and font.
+-(The font is a number from 1 to 4.)
+-Any of these can be used in computations like any other register,
+-but some, like
+-.BD .s
+-and
+-.BD .f ,
+-cannot be changed with
+-.BD .nr .
+-.PP
+-As an example of the use of number registers,
+-in the
+-.BD \-ms
+-macro package [4],
+-most significant parameters are defined in terms of the values
+-of a handful of number registers.
+-These include the point size for text, the vertical spacing,
+-and the line and title lengths.
+-To set the point size and vertical spacing for the following paragraphs, for example, a user may say
+-.P1
+-^nr PS 9
+-^nr VS 11
+-.P2
+-The paragraph macro
+-.BD .PP
+-is defined (roughly) as follows:
+-.P1
+-.ta  1i
+-^de PP
+-^ps \e\en(PS  \e" reset size
+-^vs \e\en(VSp \e" spacing
+-^ft R \e" font
+-^sp 0.5v      \e" half a line
+-^ti +3m
+-^^
+-.P2
+-This sets the font to Roman and the point size and line spacing
+-to whatever values are stored in the number registers
+-.BD PS
+-and
+-.BD VS .
+-.PP
+-Why are there two backslashes?
+-This is the eternal problem of how to quote a quote.
+-When
+-.UL troff
+-originally reads the macro definition,
+-it peels off one backslash
+-to see what's coming next.
+-To ensure that another is left in the definition when the 
+-macro is
+-.ul
+-used,
+-we have to put in two backslashes in the definition.
+-If only one backslash is used, 
+-point size and vertical spacing will be frozen at the time the macro
+-is defined, not when it is used.
+-.PP
+-Protecting by an extra layer of backslashes
+-is only needed for
+-.BD \en ,
+-.BD \e* ,
+-.BD \e$
+-(which we haven't come to yet),
+-and
+-.BD \e
+-itself.
+-Things like
+-.BD \es ,
+-.BD \ef ,
+-.BD \eh ,
+-.BD \ev ,
+-and so on do not need an extra backslash,
+-since they are converted by
+-.UL troff
+-to an internal code immediately upon being seen.
+-.WS
+-.PP
+-Arithmetic expressions can appear anywhere that
+-a number is expected.
+-As a trivial example,
+-.P1
+-^nr PS \e\en(PS\-2
+-.P2
+-decrements PS by 2.
+-Expressions can use the arithmetic operators +, \-, *, /, % (mod),
+-the relational operators >, >=, <, <=, =, and != (not equal),
+-and parentheses.
+-.PP
+-Although the arithmetic we have done so far
+-has been straightforward,
+-more complicated things are somewhat tricky.
+-First,
+-number registers hold only integers.
+-.UL troff
+-arithmetic uses truncating integer division, just like Fortran.
+-Second, in the absence of parentheses,
+-evaluation is done left-to-right
+-without any operator precedence
+-(including relational operators).
+-Thus
+-.P1
+-7*\-4+3/13
+-.P2
+-becomes `\-1'.
+-Number registers can occur anywhere in an expression,
+-and so can scale indicators like
+-.BD p ,
+-.BD i ,
+-.BD m ,
+-and so on (but no spaces).
+-Although integer division causes truncation,
+-each number and its scale indicator is converted
+-to machine units (1/432 inch) before any arithmetic is done,
+-so
+-1i/2u
+-evaluates to
+-0.5i
+-correctly.
+-.PP
+-The scale indicator
+-.BD u
+-often has to appear
+-when you wouldn't expect it _
+-in particular, when arithmetic is being done
+-in a context that implies horizontal or vertical dimensions.
+-For example,
+-.P1
+-^ll 7/2i
+-.P2
+-would seem obvious enough _
+-3\(12 inches.
+-Sorry.
+-Remember that the default units for horizontal parameters like
+-.BD .ll
+-are ems.
+-That's really `7 ems / 2 inches',
+-and when translated into machine units, it becomes zero.
+-How about
+-.P1
+-^ll 7i/2
+-.P2
+-Sorry, still no good _
+-the `2' is `2 ems', so `7i/2' is small,
+-although not zero.
+-You
+-.ul
+-must
+-use
+-.P1
+-^ll 7i/2u
+-.P2
+-So again, a safe rule is to
+-attach a scale indicator to every number,
+-even constants.
+-.PP
+-For arithmetic done within a
+-.BD .nr
+-command,
+-there is no implication of horizontal or vertical dimension,
+-so the default units are `units',
+-and 7i/2 and 7i/2u
+-mean the same thing.
+-Thus
+-.P1
+-^nr ll 7i/2
+-^ll \e\en(llu
+-.P2
+-does just what you want,
+-so long as you
+-don't forget the
+-.BD u
+-on the
+-.BD .ll
+-command.
+//GO.SYSIN DD tt10
+echo tt11
+sed 's/.//' >tt11 <<'//GO.SYSIN DD tt11'
+-.NH
+-Macros with arguments
+-.PP
+-The next step is to define macros that can change from one
+-use to the next
+-according to parameters supplied as arguments.
+-To make this work, we need two things:
+-first, when we define the macro, we have to indicate that some
+-parts of it will be provided as arguments when the macro is called.
+-Then when the macro is 
+-called
+-we have to provide actual arguments
+-to be plugged into the definition.
+-.PP
+-Let us illustrate by defining a macro
+-.BD .SM
+-that will print its argument two points
+-smaller than the surrounding text.
+-That is, the macro call
+-.P1
+-^SM TROFF
+-.P2
+-will produce
+-.UC TROFF .
+-.PP
+-The definition of
+-.BD .SM
+-is
+-.P1
+-^de SM
+-\es\-2\e\e$1\es+2
+-^^
+-.P2
+-Within a macro definition,
+-the symbol
+-.BD \e\e$n
+-refers to the
+-.BD n th
+-argument
+-that the macro was called with.
+-Thus
+-.BD \e\e$1
+-is the string to be placed in a smaller point
+-size when
+-.BD .SM
+-is called.
+-.PP
+-As a slightly more complicated version, the following definition of
+-.BD .SM
+-permits optional second and third arguments
+-that will be printed in the normal size:
+-.P1
+-^de SM
+-\e\e$3\es\-2\e\e$1\es+2\e\e$2
+-^^
+-.P2
+-Arguments not provided when the macro is called are treated
+-as empty,
+-so
+-.P1
+-^SM  TROFF  ),
+-.P2
+-produces
+-.UC TROFF ),
+-while
+-.P1
+-^SM  TROFF  ).  (
+-.P2
+-produces
+-.UC TROFF ). (
+-It is convenient to reverse 
+-the order of arguments because trailing punctuation
+-is much more common than leading.
+-.PP
+-By the way, the number of arguments that a macro was called with
+-is available in number register
+-.BD .$ .
+-.PP
+-The following macro
+-.BD ^BD
+-is the one used to make the
+-`bold roman' we have been using for
+-.UL troff
+-command names in text.
+-It combines horizontal motions, width computations,
+-and argument rearrangement.
+-.P1 2
+-\&.de BD
+-\e&\e\e$3\ef1\e\e$1\eh'\-\ew'\e\e$1'u+1u'\e\e$1\efP\e\e$2
+-\&..
+-.P2
+-The
+-.BD \eh
+-and
+-.BD \ew
+-commands need no extra backslash, as we discussed above.
+-The
+-.BD \e&
+-is there in case the argument begins with a period.
+-.WS
+-.PP
+-Two backslashes are needed with the
+-.BD \e\e$n
+-commands, though,
+-to protect one of them when the macro is
+-being defined.
+-Perhaps a second example will make this clearer.
+-Consider a macro called
+-.BD .SH
+-which
+-produces section headings rather like those in this paper,
+-with the sections numbered automatically,
+-and the title in bold in a smaller size.
+-The use is
+-.P1
+-^SH  "Section title ..."
+-.P2
+-(If the argument to a macro is to contain blanks,
+-then it must be
+-.ul
+-surrounded
+-by double quotes,
+-unlike a string, where only one leading quote is permitted.)
+-.PP
+-Here is the definition of the
+-.BD .SH
+-macro:
+-.P1
+-.ta .75i 1.15i
+-^nr SH 0      \e" initialize section number
+-^de SH
+-^sp 0.3i
+-^ft B
+-^nr SH \e\en(SH+1     \e" increment number
+-^ps \e\en(PS\-1       \e" decrease PS
+-\e\en(SH.  \e\e$1     \e" number. title
+-^ps \e\en(PS          \e" restore PS
+-^sp 0.3i
+-^ft R
+-^^
+-.P2
+-The section number is kept in number register SH, which is incremented each
+-time just before it is used.
+-(A number register may have the same name as a macro
+-without conflict but a string may not.)
+-.PP
+-We used
+-.BD \e\en(SH
+-instead of
+-.BD \en(SH
+-and
+-.BD \e\en(PS
+-instead of
+-.BD \en(PS .
+-If we had used
+-.BD \en(SH ,
+-we would get the value of the register at the time the macro was
+-.ul
+-defined,
+-not at the time it was
+-.ul
+-used.
+-If that's what you want, fine,
+-but not here.
+-Similarly,
+-by using
+-.BD \e\en(PS ,
+-we get the point size at the time the macro is called.
+-.WS
+-.PP
+-As an example that does not involve numbers,
+-recall our
+-.BD .NP
+-macro which had a
+-.P1
+-^tl 'left'center'right'
+-.P2
+-We could make these into parameters by using instead
+-.P1
+-^tl '\e\e*(LT'\e\e*(CT'\e\e*(RT'
+-.P2
+-so the title comes from three strings called LT, CT and RT.
+-If these are empty, then the title will be a blank line.
+-Normally CT would be set with something like
+-.P1
+-\&^ds  CT  - % -
+-.P2
+-to give just the page number between hyphens (as on the top of this page),
+-but a user could supply private definitions for
+-any of the strings.
+//GO.SYSIN DD tt11
+echo tt12
+sed 's/.//' >tt12 <<'//GO.SYSIN DD tt12'
+-.NH
+-Conditionals
+-.PP
+-Suppose we want the
+-.BD .SH
+-macro to leave two extra inches of space just before section 1,
+-but nowhere else.
+-The cleanest way to do that is to test inside the
+-.BD .SH
+-macro
+-whether
+-the section number is 1,
+-and add some space if it is.
+-The
+-.BD .if
+-command provides the conditional test
+-that we can add
+-just before the heading line is output:
+-.P1 4
+-^if \e\en(SH=1 ^sp 2i \e" first section only
+-.P2
+-.PP
+-The condition after the
+-.BD .if
+-can be any arithmetic or logical expression.
+-If the condition is logically true, or arithmetically greater than zero,
+-the rest of the line is treated as if
+-it were text _
+-here a command.
+-If the condition is false, or zero or negative,
+-the rest of the line is skipped.
+-.PP
+-It is possible to do more than one command if a condition is true.
+-Suppose several operations are to be done before section 1.
+-One possibility is to define a macro 
+-.BD .S1
+-and invoke it
+-if we are about to do section 1
+-(as determined by an
+-.BD .if ).
+-.P1
+-^de S1
+----  processing for section 1 ---
+-^^
+-^de SH
+-^^^
+-^if \e\en(SH=1 ^S1
+-^^^
+-^^
+-.P2
+-.PP
+-An alternate way is to use the
+-extended form of the
+-.BD .if ,
+-like this:
+-.P1
+-^if \e\en(SH=1 \e{--- processing
+-for section 1 ----\e}
+-.P2
+-The braces
+-.BD \e{
+-and
+-.BD \e}
+-must occur in the positions shown
+-or you will get unexpected extra lines in your output.
+-.UL troff
+-also provides
+-an `if-else' construction,
+-which we will not go into here.
+-.PP
+-A condition can be negated by preceding it with
+-.BD ! ;
+-we get the same effect as above (but less clearly) by using
+-.P1
+-^if !\e\en(SH>1 ^S1
+-.P2
+-.PP
+-There are a handful of 
+-other conditions that can be tested with
+-.BD .if .
+-For example, is the current page even or odd?
+-.P1
+-^if e ^tl ''even page title''
+-^if o ^tl ''odd page title''
+-.P2
+-gives facing pages different titles
+-when used inside an appropriate new page macro.
+-.PP
+-Two other conditions
+-are
+-.BD t
+-and
+-.BD n ,
+-which tell you whether the formatter is
+-.UL troff
+-or
+-.UL nroff . 
+-.P1
+-^if t troff stuff ...
+-^if n nroff stuff ...
+-.P2
+-.PP
+-Finally, string comparisons may be made in an
+-.BD .if :
+-.P1
+-^if  'string1'string2'  stuff
+-.P2
+-does `stuff' if
+-.ul
+-string1
+-is the same as
+-.ul
+-string2.
+-The character separating the strings can be anything
+-reasonable that is
+-not contained in either string.
+-The strings themselves can reference strings with
+-.BD \e* ,
+-arguments with 
+-.BD \e$ ,
+-and so on.
+//GO.SYSIN DD tt12
+echo tt13
+sed 's/.//' >tt13 <<'//GO.SYSIN DD tt13'
+-.NH
+-Environments
+-.PP
+-As we mentioned, there is a potential problem
+-when going across a page boundary:
+-parameters like size and font
+-for a page title may well be different from those
+-in effect in the text when the page boundary occurs.
+-.UL troff
+-provides a very general way to deal with this and
+-similar situations.
+-There are three `environments',
+-each of which has independently settable versions of
+-many of the parameters associated with processing,
+-including size, font, line and title lengths,
+-fill/nofill mode, tab stops, and even partially collected lines.
+-Thus the titling problem may be readily solved by processing the main text
+-in one environment and titles in a separate one
+-with its own suitable parameters.
+-.PP
+-The command
+-.BD .ev\ n
+-shifts to environment
+-.BD n ;
+-.BD n
+-must be 0, 1 or 2.
+-The command
+-.BD .ev
+-with no argument returns to the
+-previous environment.
+-Environment names are maintained in a stack, so calls
+-for different environments may be nested and unwound consistently.
+-.PP
+-Suppose we say that the main text is processed in environment 0,
+-which is where 
+-.UL troff
+-begins by default.
+-Then we can modify the new page macro
+-.BD .NP
+-to process titles in environment 1 like this:
+-.P1 2
+-^de NP
+-^ev 1 \e" shift to new environment
+-^lt 6i        \e" set parameters here
+-^ft R
+-^ps 10
+-\&... any other processing ...
+-^ev   \e" return to previous environment
+-^^
+-.P2
+-It is also possible to initialize the parameters for an environment
+-outside the
+-.BD .NP
+-macro,
+-but the version shown keeps all the processing in one place
+-and is thus easier to understand and change.
+//GO.SYSIN DD tt13
+echo tt14
+sed 's/.//' >tt14 <<'//GO.SYSIN DD tt14'
+-.NH
+-Diversions
+-.PP
+-There are numerous occasions in page layout when it is necessary to store some text
+-for a period of time without actually printing it.
+-Footnotes are the most obvious example:
+-the text of the footnote usually appears in the input well before the place
+-on the page where it is to be printed is reached.
+-In fact,
+-the place where it is output normally depends on how big it is,
+-which implies that there must be a way
+-to process the footnote at least
+-enough to decide its size
+-without printing it.
+-.PP
+-.UL troff
+-provides a mechanism called a diversion
+-for doing this processing.
+-Any part of the output may be diverted into a macro instead
+-of being printed,
+-and then at some convenient time the macro may be put back into
+-the input.
+-.PP
+-The command
+-.BD .di\ xy
+-begins a diversion _ all subsequent output is collected into the macro
+-.BD xy
+-until the command
+-.BD .di
+-with no arguments is encountered.
+-This terminates the diversion.
+-The processed text is available at any time thereafter, simply
+-by giving the command
+-.P1
+-^xy
+-.P2
+-The vertical size of the last finished diversion is contained in
+-the built-in number register
+-.BD dn .
+-.PP
+-As a simple example,
+-suppose we want to implement a `keep-release'
+-operation,
+-so that text between the commands
+-.BD .KS 
+-and
+-.BD .KE
+-will not be split across a page boundary
+-(as for a figure or table).
+-Clearly, when a
+-.BD .KS
+-is encountered, we have to begin diverting
+-the output so we can find out how big it is.
+-Then when a
+-.BD .KE
+-is seen, we decide
+-whether the diverted text will fit on the current page,
+-and print it either there if it fits, or at the top of the next page if it doesn't.
+-So:
+-.P1 2
+-.ta .6i
+-^de KS        \e" start keep
+-^br   \e" start fresh line
+-^ev 1 \e" collect in new environment
+-^fi   \e" make it filled text
+-^di XX        \e" collect in XX
+-^^
+-.P2
+-.P1 2
+-.ta .6i
+-^de KE        \e" end keep
+-^br   \e" get last partial line
+-^di   \e" end diversion
+-^if \e\en(dn>=\e\en(.t .bp   \e" bp if doesn't fit
+-^nf   \e" bring it back in no-fill
+-^XX   \e" text
+-^ev   \e" return to normal environment
+-^^
+-.P2
+-Recall that number register
+-.BD nl
+-is the current position
+-on the output page.
+-Since output was being diverted, this remains
+-at its value when the diversion started.
+-.BD dn
+-is the amount of text in the diversion;
+-.BD .t
+-(another built-in register)
+-is the distance to the next trap,
+-which we assume is at the bottom margin of the page.
+-If the diversion is large enough to go past the trap,
+-the
+-.BD .if
+-is satisfied, and
+-a
+-.BD .bp
+-is issued.
+-In either case, the diverted output is then brought back with
+-.BD .XX .
+-It is essential to bring it back in no-fill mode so
+-.UL troff
+-will do no further processing on it.
+-.PP
+-This is not the most general keep-release,
+-nor is it robust in the face of all conceivable inputs,
+-but it would require more space than we have here to write it
+-in full generality.
+-This section is not intended
+-to teach everything about diversions,
+-but to sketch out enough that you can read
+-existing macro packages with some comprehension.
+//GO.SYSIN DD tt14
+echo ttack
+sed 's/.//' >ttack <<'//GO.SYSIN DD ttack'
+-.SH
+-Acknowledgements
+-.PP
+-I am deeply indebted to J. F. Ossanna,
+-the author of
+-.UL troff ,
+-for his repeated patient explanations
+-of
+-fine points,
+-and for his continuing willingness to
+-adapt
+-.UL troff
+-to make other uses easier.
+-I am also grateful to Jim Blinn, Ted Dolotta,
+-Doug McIlroy, Mike Lesk and Joel Sturman
+-for helpful comments on this paper.
+-.SH
+-References
+-.LP
+-.IP [1]
+-J. F. Ossanna,
+-.ul
+-.UC NROFF/TROFF
+-User's Manual,
+-Bell Laboratories
+-Computing Science Technical Report 54, 1976.
+-.IP [2]
+-B. W. Kernighan,
+-.ul
+-A System for Typesetting Mathematics _ User's Guide
+-.ul
+-(Second Edition),
+-Bell Laboratories
+-Computing Science Technical Report 17, 1977.
+-.IP [3]
+-M. E. Lesk,
+-.ul
+-TBL _ A Program to Format Tables,
+-Bell Laboratories
+-Computing Science Technical Report 49, 1976.
+-.IP [4]
+-M. E. Lesk,
+-.ul
+-Typing Documents on UNIX,
+-Bell Laboratories, 1978.
+-.IP [5]
+-J. R. Mashey and D. W. Smith,
+-.ul
+-PWB/MM _
+-.ul
+-Programmer's Workbench Memorandum Macros,
+-Bell Laboratories internal memorandum.
+//GO.SYSIN DD ttack
+echo ttcharset
+sed 's/.//' >ttcharset <<'//GO.SYSIN DD ttcharset'
+-.bp
+-.tr __
+-.nr VS 12
+-.vs 12p
+-.1C
+-.SH
+-Appendix A: Phototypesetter Character Set
+-.LP
+-These characters exist in roman, italic, and bold.
+-To get the one on the left, type the
+-four-character name on the right.
+-.sp
+-.ta .2i .8i 1i 1.6i 1.8i 2.4i 2.6i 3.2i 3.4i 4.0i 4.2i 4.8i 5i 5.6i 5.8i
+-.nf
+-.in 0.5i
+-\(ff  \\(ff   \(fi    \\(fi   \(fl    \\(fl   \(Fi    \\(Fi   \(Fl    \\(Fl
+-\(ru  \\(ru   \(em    \\(em   \(14    \\(14   \(12    \\(12   \(34    \\(34
+-\(co  \\(co   \(de    \\(de   \(dg    \\(dg   \(fm    \\(fm   \(ct    \\(ct   
+-\(rg  \\(rg   \(bu    \\(bu   \(sq    \\(sq   \(hy    \\(hy
+-                              (In bold, \e(sq is \fB\(sq\fP.)
+-.sp
+-.in 0
+-.tr ~~
+-.ps 9
+-.fi
+-The following are special-font characters:
+-.sp
+-.in 0.5i
+-.tr ~~
+-.nf
+-.ta .3i 1i 1.3i 2i 2.3i 3i 3.3i
+-\(pl  \\(pl   \(mi    \\(mi   \(mu    \\(mu   \(di    \\(di   
+-\(eq  \\(eq   \(==    \\(==   \(>=    \\(>=   \(<=    \\(<=   
+-\(!=  \\(!=   \(+-    \\(+-   \(no    \\(no   \(sl    \\(sl   
+-\(ap  \\(ap   \(~=    \\(~=   \(pt    \\(pt   \(gr    \\(gr   
+-\(->  \\(->   \(<-    \\(<-   \(ua    \\(ua   \(da    \\(da   
+-\(is  \\(is   \(pd    \\(pd   \(if    \\(if   \(sr    \\(sr   
+-\(sb  \\(sb   \(sp    \\(sp   \(cu    \\(cu   \(ca    \\(ca   
+-\(ib  \\(ib   \(ip    \\(ip   \(mo    \\(mo   \(es    \\(es   
+-\(aa  \\(aa   \(ga    \\(ga   \(ci    \\(ci   \(bs    \\(bs   
+-\(sc  \\(sc   \(dd    \\(dd   \(lh    \\(lh   \(rh    \\(rh   
+-\(lt  \\(lt   \(rt    \\(rt   \(lc    \\(lc   \(rc    \\(rc   
+-\(lb  \\(lb   \(rb    \\(rb   \(lf    \\(lf   \(rf    \\(rf   
+-\(lk  \\(lk   \(rk    \\(rk   \(bv    \\(bv   \(ts    \\(ts   
+-\(br  \\(br   \(or    \\(or   \(ul    \\(ul   \(rn    \\(rn   
+-\(**  \\(**
+-.sp
+-.in0
+-.ps 9
+-.fi
+-These
+-four
+-characters also have two-character names. 
+-The \' is the apostrophe on terminals;
+-the \` is the other quote mark.
+-.sp
+-.in .5i
+-\'    \e\(aa  \`      \e\(ga  \(mi    \e\(mi  \_      \e\_
+-.sp
+-.in 0
+-These
+-characters exist only on the special font,
+-but they do not have four-character names:
+-.sp
+-.in .5i
+-.nf
+-.tr ^^
+-"      {      }      <      >      ~      ^      \e      #      @
+-.sp
+-.in 0
+-.fi
+-For greek, precede the roman letter by
+-.BD \e(*
+-to get the corresponding greek;
+-for example, 
+-.BD \e(*a
+-is
+-\(*a.
+-.sp
+-.in 0.5i
+-.nf
+-.cs R 36
+-abgdezyhiklmncoprstufxqw
+-\(*a\(*b\(*g\(*d\(*e\(*z\(*y\(*h\(*i\(*k\(*l\(*m\(*n\(*c\(*o\(*p\(*r\(*s\(*t\(*u\(*f\(*x\(*q\(*w
+-.sp
+-ABGDEZYHIKLMNCOPRSTUFXQW
+-\(*A\(*B\(*G\(*D\(*E\(*Z\(*Y\(*H\(*I\(*K\(*L\(*M\(*N\(*C\(*O\(*P\(*R\(*S\(*T\(*U\(*F\(*X\(*Q\(*W
+-.ps 9
+-.cs R
+-.in 0
+-.fi
+//GO.SYSIN DD ttcharset
+echo ttindex
+sed 's/.//' >ttindex <<'//GO.SYSIN DD ttindex'
+-.bp
+-.2C
+-.SH
+-Index
+-.LP
+-.ps 8
+-.vs 9p
+-! (negating conditionals)~17
+-#$ (macro argument)~16
+-#*x, #(xy (invoke string macro)~14
+-#b (bracketing function)~13
+-#d (subscript)~11
+-#f (font change)~5
+-#h (horizontal motion)~12
+-#nx, #n(xy (number register)~15
+-#o (overstrike)~13
+-#s (size change)~3
+-#u (superscript)~11
+-#v (vertical motion)~11
+-#w (width function)~12
+-#z (zero motion)~13
+-\(fmcommand instead of ^command~9
+-% (page number register)~10,15
+-^^ (end of macro definition)~7
+-^bp~9,10
+-^br (break)~9
+-^ce (center)~2
+-^ds (define string macro)~7,14
+-^fi (fill)~2
+-^ft (change font)~5
+-^if (conditional test)~16
+-^in (indent)~6
+-^lg (set ligatures~5
+-^ll (line length)~6
+-^nf (nofill)~2
+-^nr (set number register)~14
+-^pn (page number)~10
+-^ps (change point size)~1,3
+-^sp (space)~4
+-^ss (set space size)~10
+-^ta (set tab stops)~11
+-^tc (set tab character)~10
+-^tl (title)~9
+-^tr (translate characters)~2,6
+-^ul (italicize)~6
+-^vs (vertical spacing)~3
+-^wh (when conditional)~9,17
+-accents~6,13
+-apostrophes~6
+-arithmetic~15
+-backslash~1,3,5,14,16
+-begin page (^bp)~9
+-block macros (B1,B2)~8
+-bold font (.ft B)~5
+-boustrophedon~12
+-bracketing function (##b)~13
+-break (^br)~9
+-break-causing commmands~9
+-centering (^ce)~2
+-changing fonts (^ft, #f)~5
+-changing macros~15
+-character set~4,5,19
+-character translation (^tr)~2,6
+-columnated output~10
+-commands~1
+-commands that cause break~9
+-conditionals (^if)~16
+-constant proportion~7
+-default break list~9
+-define macro (^de)~7
+-define string macro (^ds)~14
+-drawing lines~11
+-em~7,11
+-end of macro (^^)~7
+-even page test (e)~17
+-fill (^fi)~2
+-fonts (^ft)~4,19
+-Greek (#(*-)~5,19
+-hanging indent (^ti)~12
+-hints~20
+-horizontal motion (#h)~12
+-hp (horizontal position register)~15
+-hyphen~6
+-i scale indicator~4
+-indent (^in)~6
+-index~21
+-italic font (.ft I)~4
+-italicize (^ul)~6
+-legal point sizes~3
+-ligatures (ff,fi,fl; ^lg)~5
+-line length (^ll)~6
+-line spacing (^vs)~3
+-local motions (#u,#d,#v,#h,#w,#o,#z,#b)~11 ff
+-m scale indicator~7
+-machine units~4,12
+-macro arguments~15
+-macros~7
+-macros that change~15
+-multiple backslashes~14
+-negating conditionals (!)~17
+-new page macro (NP)~8
+-nl (current vertical position register)~15
+-nofill (^nf)~2
+-NROFF test (n)~17
+-nested quotes~12
+-number registers (^nr,#n)~14
+-numbered paragraphs~12
+-odd page test (o)~17
+-order of evaluation~14
+-overstrike (#o)~13
+-p scale indicator~3
+-page number register (%)~10
+-page numbers (^pn, ^bp)~10
+-paragraph macro (PG)~7
+-Paternoster~6
+-point size (^ps)~1,3
+-previous font (#fP, ^ft P)~5
+-previous point size (#s0,^ps)~3
+-quotes~6
+-relative change (\(+-)~6
+-ROFF~1
+-ROFF header and footer~8
+-Roman font (.ft R)~4
+-scale indicator i~4
+-scale indicator m~7
+-scale indicator p~3
+-scale indicator u~12
+-scale indicators in arithmetic~15
+-section heading macro (SC)~15
+-set space size (^ss)~10
+-size _ see point size
+-space (^sp)~4
+-space between lines (^vs)~3
+-special characters (#(xx)~5,19
+-string macros (^ds,#*)~14
+-subscripts (#d)~11
+-superscripts (#u)~11
+-tab character (^tc)~11
+-tabs (^ta)~10
+-temporary indent (^ti)~7
+-titles (^tl)~8
+-translate (^tr)~2,6,12
+-TROFF examples~19
+-TROFF test (t)~17
+-truncating division~15
+-type faces _ see fonts
+-u scale indicator~12
+-underline (^ul)~6
+-valid point sizes~3
+-vertical motion (#v)~11
+-vertical position on page~9
+-vertical spacing (^vs)~3
+-when (^wh)~9,17
+-width function (#w)~12
+-width of digits~10
+-zero motion (#z)~13
+//GO.SYSIN DD ttindex
diff --git a/doc/7thEdMan/vol2/uprog.bun b/doc/7thEdMan/vol2/uprog.bun
new file mode 100644 (file)
index 0000000..f328e91
--- /dev/null
@@ -0,0 +1,2973 @@
+# To unbundle, run this file
+echo cwscript
+sed 's/.//' >cwscript <<'//GO.SYSIN DD cwscript'
+-/^\.if/b
+-/^\.ix/b
+-/^\.tm/b
+-s/\\\\/\\e\\e/g
+-s/\\\([n"'bt0]\)/\\e\1/g
+-s/^\.SS/.P1/
+-s/^\.ES/.P2/
+-s/\^/\\(14/g
+-s/~/\\v'.25m'\\s\\nS&\\s\\nP\\v'-.25m'/g
+-s/\\|/ZZZ/g
+-s/|/\\v'.05m'\\s\\nS&\\s\\nP\\v'-.05m'/g
+-s/ZZZ/\\|/g
+-s/_/\\(em/g
+-s/</\\(fi/g
+-s/>/\\(fl/g
+-/^\.P1/,/^\.P2/{
+-      s/{/\\(Fl/g
+-      s/}/\\(Fi/g
+-      s/"/\\(34/g
+-      s/[?!]/\\s\\ns&\\s\\nP/g
+-      s:/:\\s\\ns/\\s\\nP:g
+-}
+-/^\.UL/{
+-      s/{/\\(Fl/g
+-      s/}/\\(Fi/g
+-      s/"/\\(34/g
+-      s/[?!]/\\s\\ns&\\s\\nP/g
+-      s:/:\\s\\ns/\\s\\nP:g
+-}
+-s/#/\\(de/g
+-s/\\\*/XXX/g
+-s/\*/\\v'-.1m'\\s\\ns&\\s\\nP\\v'.1m'/g
+-s/XXX/\\*/g
+-s/\\e/\\s\\ns\\(rg\\s\\nP/g
+//GO.SYSIN DD cwscript
+echo p.mac
+sed 's/.//' >p.mac <<'//GO.SYSIN DD p.mac'
+-.fp 3 CW
+-.fz 3 -1
+-.fz S 3 -0
+-.bd S 3 3     \" embolden special font in context of 3
+-.if t .nr PI .25i     \" paragraph indent
+-.nr PS 10     \" text point size
+-.nr VS 12     \" text vertical (inter-line) spacing
+-.nr dP 1      \" delta point size for program
+-.ps \n(PS
+-.vs \n(VS
+-.if n .nr NH 1        \" space after NH or SH heading
+-.if t .nr NH .5v
+-.if n .ls 2
+-.de UC
+-\&\\$3\s-1\\$1\\s0\&\\$2
+-..
+-.de IT
+-.if n .ul
+-\&\\$3\f2\\$1\fR\^\&\\$2
+-..
+-.de UL
+-.lg 0
+-.if n .ul
+-\%\&\\$3\f3\\$1\fR\&\\$2
+-.lg
+-..
+-.cs 3 25 \\n(PS-1     \" constant space
+-.nr P \\n(PS  \" current point size
+-.nr S \\n(PS+1        \" 1 points bigger
+-.nr s \\n(PS-1        \" 1 points smaller
+-.de P1
+-.DS I .5i
+-.nf
+-.lg 0
+-.if n .ls 1
+-.if n .ta 5 10 15 20 25 30 35 40 45 50 55 60
+-.if t .ps -\\n(dP
+-.if t .vs -\\n(dP
+-.nr P \\n(.s
+-.nr S \\n(.s+1
+-.nr s \\n(.s-1
+-.nr t 5*33u   \" width in 9 point CW
+-.if t .ta 1u*\\ntu 2u*\\ntu 3u*\\ntu 4u*\\ntu 5u*\\ntu 6u*\\ntu 7u*\\ntu 8u*\\ntu 9u*\\ntu 10u*\\ntu 11u*\\ntu 12u*\\ntu 13u*\\ntu 14u*\\ntu
+-.ft 3
+-.cs 3 25 \\nP-1
+-.lg 0
+-..
+-.de P2
+-.ps \\n(PS
+-.vs \\n(VSp
+-.nr P \\n(PS
+-.nr S \\n(PS+1
+-.nr s \\n(PS-1
+-.ft R
+-.if n .ls 2
+-.fi
+-.DE
+-.lg
+-.cs 3 25 \\n(PS-1
+-..
+-.hy 14        \"2=not last lines; 4= no -xx; 8=no xx-
+-.am SH
+-.ft 1
+-.bd 1 3
+-..
+-.am NH
+-.ft 1
+-.bd 1 3
+-..
+-.am TL
+-.ft 1
+-.bd 1 3
+-..
+//GO.SYSIN DD p.mac
+echo p0
+sed 's/.//' >p0 <<'//GO.SYSIN DD p0'
+-.if n .ls 1
+-...TM 78-1273-9 39199 39199-11
+-...ND October 2, 1978
+-...old TM 75-1273-11 October 22, 1975
+-.RP
+-.TL
+-UNIX Programming \(em Second Edition
+-.AU "MH 2C-518" 6021
+-Brian W. Kernighan
+-.AU "MH 2C-517" 3770
+-Dennis M. Ritchie
+-.AI
+-.MH
+-.AB
+-.PP
+-This paper is an introduction to programming on
+-the
+-.UX
+-system.
+-The emphasis is on how to write programs that interface
+-to the operating system,
+-either directly or through the standard I/O library.
+-The topics discussed include
+-.IP "  \(bu"
+-handling command arguments
+-.IP "  \(bu"
+-rudimentary I/O; the standard input and output
+-.IP "  \(bu"
+-the standard I/O library; file system access
+-.IP "  \(bu"
+-low-level I/O: open, read, write, close, seek
+-.IP "  \(bu"
+-processes: exec, fork, pipes
+-.IP "  \(bu"
+-signals \(em interrupts, etc.
+-.PP
+-There is also an appendix which describes
+-the standard I/O library in detail.
+-.AE
+-.CS 17 0 17 0 0 4
+//GO.SYSIN DD p0
+echo p1
+sed 's/.//' >p1 <<'//GO.SYSIN DD p1'
+-.if n .ls 2
+-.if t .tr |\(or
+-.NH
+-INTRODUCTION
+-.PP
+-This paper describes how to write
+-programs 
+-that interface with the
+-.UC UNIX
+-operating system in a non-trivial way.
+-This includes programs that use files by name,
+-that use pipes,
+-that invoke other commands as they run,
+-or that attempt to catch interrupts and other signals
+-during execution.
+-.PP
+-The document collects material which is scattered
+-throughout several sections of
+-.I
+-The
+-.UC UNIX
+-Programmer's Manual
+-.R
+-[1]
+-for Version 7
+-.UC UNIX .
+-There is no attempt to be complete;
+-only generally useful material is dealt with.
+-It is assumed that you will be programming in C,
+-so you must be able to read the language
+-roughly up to the level of
+-.I
+-The C Programming Language
+-.R
+-[2].
+-Some of the material in sections 2 through 4
+-is based on
+-topics covered more carefully there.
+-You should also be familiar with
+-.UC UNIX
+-itself
+-at least
+-to the level of
+-.I
+-.UC UNIX
+-for Beginners
+-.R
+-[3].
+//GO.SYSIN DD p1
+echo p2
+sed 's/.//' >p2 <<'//GO.SYSIN DD p2'
+-.NH
+-BASICS
+-.NH 2
+-Program Arguments
+-.PP
+-When a C program is run as a command,
+-the arguments on the command line are made available
+-to the
+-function
+-.UL main
+-as an argument count
+-.UL argc
+-and an array
+-.UL argv
+-of
+-pointers to
+-character strings
+-that contain
+-the arguments.
+-By convention,
+-.UL argv[0]
+-is the command name itself,
+-so
+-.UL argc
+-is always greater than 0.
+-.PP
+-The following program illustrates the mechanism:
+-it simply echoes its arguments
+-back to the terminal.
+-(This is essentially the
+-.UL echo
+-command.)
+-.P1
+-main(argc, argv)      /* echo arguments */
+-int argc;
+-char *argv[];
+-{
+-      int i;
+-
+-      for (i = 1; i < argc; i++)
+-              printf("%s%c", argv[i], (i<argc-1) ? ' ' : '\n');
+-}
+-.P2
+-.UL argv
+-is a pointer to an array
+-whose individual elements are pointers to arrays of characters;
+-each is terminated by
+-.UL \e0 ,
+-so they can be treated as strings.
+-The program starts by printing 
+-.UL argv[1]
+-and loops until it has printed them all.
+-.PP
+-The argument count and the arguments
+-are parameters to
+-.UL main .
+-If you want to keep them around so other
+-routines can get at them, you must
+-copy them to external variables.
+-.NH 2
+-The ``Standard Input'' and ``Standard Output''
+-.PP
+-The simplest input mechanism is to read the ``standard input,''
+-which is generally the user's terminal.
+-The function
+-.UL getchar
+-returns the next input character each time it is called.
+-A file may be substituted for the terminal by
+-using the
+-.UL <
+-convention: 
+-if
+-.UL prog
+-uses 
+-.UL getchar ,
+-then
+-the command line
+-.P1
+-prog <file
+-.P2
+-causes
+-.UL prog
+-to read
+-.UL file
+-instead of the terminal.
+-.UL prog
+-itself need know nothing about where its input
+-is coming from.
+-This is also true if the input comes from another program via
+-the 
+-.U 
+-pipe mechanism:
+-.P1
+-otherprog | prog
+-.P2
+-provides the standard input for
+-.UL prog
+-from the standard output of
+-.UL otherprog.
+-.PP
+-.UL getchar
+-returns the value
+-.UL EOF
+-when it encounters the end of file
+-(or an error)
+-on whatever you are reading.
+-The value of
+-.UL EOF
+-is normally defined to be
+-.UL -1 ,
+-but it is unwise to take any advantage
+-of that knowledge.
+-As will become clear shortly,
+-this value is automatically defined for you when
+-you compile a program,
+-and need not be of any concern.
+-.PP
+-Similarly,
+-.UL putchar(c)
+-puts the character
+-.UL c
+-on the ``standard output,''
+-which is also by default the terminal.
+-The output can be captured on a file
+-by using
+-.UL > :
+-if
+-.UL prog
+-uses
+-.UL putchar ,
+-.P1
+-prog >outfile
+-.P2
+-writes the standard output on
+-.UL outfile 
+-instead of the terminal.
+-.UL outfile
+-is created if it doesn't exist;
+-if it already exists, its previous contents are overwritten.
+-And a pipe can be used:
+-.P1
+-prog | otherprog
+-.P2
+-puts the standard output of
+-.UL prog
+-into the standard input of
+-.UL otherprog.
+-.PP
+-The function
+-.UL printf ,
+-which formats output in various ways,
+-uses
+-the same mechanism as
+-.UL putchar
+-does,
+-so calls to
+-.UL printf
+-and
+-.UL putchar
+-may be intermixed in any order;
+-the output will appear in the order of the calls.
+-.PP
+-Similarly, the function
+-.UL scanf
+-provides for formatted input conversion;
+-it will read the standard input and break it
+-up into strings, numbers, etc.,
+-as desired.
+-.UL scanf
+-uses the same mechanism as
+-.UL getchar ,
+-so calls to them may also be intermixed.
+-.PP
+-Many programs
+-read only one input and write one output;
+-for such programs I/O
+-with
+-.UL getchar ,
+-.UL putchar ,
+-.UL scanf ,
+-and
+-.UL printf
+-may be entirely adequate,
+-and it is almost always enough to get started.
+-This is particularly true if
+-the
+-.UC UNIX
+-pipe facility is used to connect the output of
+-one program to the input of the next.
+-For example, the following program
+-strips out all ascii control characters
+-from its input
+-(except for newline and tab).
+-.P1
+-#include <stdio.h>
+-
+-main()        /* ccstrip: strip non-graphic characters */
+-{
+-      int c;
+-      while ((c = getchar()) != EOF)
+-              if ((c >= ' ' && c < 0177) || c == '\t' || c == '\n')
+-                      putchar(c);
+-      exit(0);
+-}
+-.P2
+-The line
+-.P1
+-#include <stdio.h>
+-.P2
+-should appear at the beginning of each source file.
+-It causes the C compiler to read a file
+-.IT /usr/include/stdio.h ) (
+-of
+-standard routines and symbols
+-that includes the definition of
+-.UL EOF .
+-.PP
+-If it is necessary to treat multiple files,
+-you can use
+-.UL cat
+-to collect the files for you:
+-.P1
+-cat file1 file2 ... | ccstrip >output
+-.P2
+-and thus avoid learning how to access files from a program.
+-By the way,
+-the call to
+-.UL exit
+-at the end is not necessary to make the program work
+-properly,
+-but it assures that any caller
+-of the program will see a normal termination status
+-(conventionally 0)
+-from the program when it completes.
+-Section 6 discusses status returns in more detail.
+//GO.SYSIN DD p2
+echo p3
+sed 's/.//' >p3 <<'//GO.SYSIN DD p3'
+-.NH
+-THE STANDARD I/O LIBRARY
+-.PP
+-The ``Standard I/O Library''
+-is a collection of routines
+-intended to provide
+-efficient
+-and portable
+-I/O services
+-for most C programs.
+-The standard I/O library is available on each system that supports C,
+-so programs that confine
+-their system interactions
+-to its facilities
+-can be transported from one system to another essentially without change.
+-.PP
+-In this section, we will discuss the basics of the standard I/O library.
+-The appendix contains a more complete description of its capabilities.
+-.NH 2
+-File Access
+-.PP
+-The programs written so far have all
+-read the standard input and written the standard output,
+-which we have assumed are magically pre-defined.
+-The next step
+-is to write a program that accesses
+-a file that is
+-.ul
+-not
+-already connected to the program.
+-One simple example is
+-.IT wc ,
+-which counts the lines, words and characters
+-in a set of files.
+-For instance, the command
+-.P1
+-wc x.c y.c
+-.P2
+-prints the number of lines, words and characters
+-in
+-.UL x.c
+-and
+-.UL y.c
+-and the totals.
+-.PP
+-The question is how to arrange for the named files
+-to be read \(em
+-that is, how to connect the file system names 
+-to the I/O statements which actually read the data.
+-.PP
+-The rules are simple.
+-Before it can be read or written
+-a file has to be
+-.ul
+-opened
+-by the standard library function
+-.UL fopen .
+-.UL fopen
+-takes an external name
+-(like
+-.UL x.c
+-or
+-.UL y.c ),
+-does some housekeeping and negotiation with the operating system,
+-and returns an internal name
+-which must be used in subsequent
+-reads or writes of the file.
+-.PP
+-This internal name is actually a pointer,
+-called a
+-.IT file
+-.IT pointer ,
+-to a structure
+-which contains information about the file,
+-such as the location of a buffer,
+-the current character position in the buffer,
+-whether the file is being read or written,
+-and the like.
+-Users don't need to know the details,
+-because part of the standard I/O definitions
+-obtained by including
+-.UL stdio.h
+-is a structure definition called
+-.UL FILE .
+-The only declaration needed for a file pointer
+-is exemplified by
+-.P1
+-FILE  *fp, *fopen();
+-.P2
+-This says that
+-.UL fp
+-is a pointer to a
+-.UL FILE ,
+-and
+-.UL fopen
+-returns a pointer to
+-a
+-.UL FILE .
+-.UL FILE \& (
+-is a type name, like
+-.UL int ,
+-not a structure tag.
+-.PP
+-The actual call to
+-.UL fopen
+-in a program
+-is
+-.P1
+-fp = fopen(name, mode);
+-.P2
+-The first argument of
+-.UL fopen
+-is the
+-name
+-of the file,
+-as a character string.
+-The second argument is the
+-mode,
+-also as a character string,
+-which indicates how you intend to
+-use the file.
+-The only allowable modes are
+-read
+-.UL \&"r" ), (
+-write
+-.UL \&"w" ), (
+-or append
+-.UL \&"a" ). (
+-.PP
+-If a file that you open for writing or appending does not exist,
+-it is created
+-(if possible).
+-Opening an existing file for writing causes the old contents
+-to be discarded.
+-Trying to read a file that does not exist
+-is an error,
+-and there may be other causes of error
+-as well
+-(like trying to read a file
+-when you don't have permission).
+-If there is any error,
+-.UL fopen
+-will return the null pointer
+-value
+-.UL NULL 
+-(which is defined as zero in
+-.UL stdio.h ).
+-.PP
+-The next thing needed is a way to read or write the file
+-once it is open.
+-There are several possibilities,
+-of which
+-.UL getc
+-and
+-.UL putc
+-are the simplest.
+-.UL getc
+-returns the next character from a file;
+-it needs the file pointer to tell it what file.
+-Thus
+-.P1
+-c = getc(fp)
+-.P2
+-places in 
+-.UL c
+-the next character from the file referred to by
+-.UL fp ;
+-it returns
+-.UL EOF
+-when it reaches end of file.
+-.UL putc
+-is the inverse of
+-.UL getc :
+-.P1
+-putc(c, fp)
+-.P2
+-puts the character
+-.UL c
+-on the file
+-.UL fp 
+-and returns
+-.UL c .
+-.UL getc
+-and
+-.UL putc
+-return
+-.UL EOF
+-on error.
+-.PP
+-When a program is started, three files are opened automatically,
+-and file pointers are provided for them.
+-These files are the standard input,
+-the standard output,
+-and the standard error output;
+-the corresponding file pointers are
+-called
+-.UL stdin ,
+-.UL stdout ,
+-and
+-.UL stderr .
+-Normally these are all connected to the terminal,
+-but
+-may be redirected to files or pipes as described in
+-Section 2.2.
+-.UL stdin ,
+-.UL stdout
+-and
+-.UL stderr
+-are pre-defined in the I/O library
+-as the standard input, output and error files;
+-they may be used anywhere an object of type
+-.UL FILE\ *
+-can be.
+-They are 
+-constants, however,
+-.ul
+-not
+-variables,
+-so don't try to assign to them.
+-.PP
+-With some of the preliminaries out of the way,
+-we can now write
+-.IT wc .
+-The basic design 
+-is one that has been found
+-convenient for many programs:
+-if there are command-line arguments, they are processed in order.
+-If there are no arguments, the standard input
+-is processed.
+-This way the program can be used stand-alone
+-or as part of a larger process.
+-.P1
+-#include <stdio.h>
+-
+-main(argc, argv)      /* wc: count lines, words, chars */
+-int argc;
+-char *argv[];
+-{
+-      int c, i, inword;
+-      FILE *fp, *fopen();
+-      long linect, wordct, charct;
+-      long tlinect = 0, twordct = 0, tcharct = 0;
+-
+-      i = 1;
+-      fp = stdin;
+-      do {
+-              if (argc > 1 && (fp=fopen(argv[i], "r")) == NULL) {
+-                      fprintf(stderr, "wc: can't open %s\n", argv[i]);
+-                      continue;
+-              }
+-              linect = wordct = charct = inword = 0;
+-              while ((c = getc(fp)) != EOF) {
+-                      charct++;
+-                      if (c == '\n')
+-                              linect++;
+-                      if (c == ' ' || c == '\t' || c == '\n')
+-                              inword = 0;
+-                      else if (inword == 0) {
+-                              inword = 1;
+-                              wordct++;
+-                      }
+-              }
+-              printf("%7ld %7ld %7ld", linect, wordct, charct);
+-              printf(argc > 1 ? " %s\n" : "\n", argv[i]);
+-              fclose(fp);
+-              tlinect += linect;
+-              twordct += wordct;
+-              tcharct += charct;
+-      } while (++i < argc);
+-      if (argc > 2)
+-              printf("%7ld %7ld %7ld total\n", tlinect, twordct, tcharct);
+-      exit(0);
+-}
+-.P2
+-The function
+-.UL fprintf
+-is identical to
+-.UL printf ,
+-save that the first argument is a file pointer
+-that specifies the file to be
+-written.
+-.PP
+-The function
+-.UL fclose
+-is the inverse of
+-.UL fopen ;
+-it breaks the connection between the file pointer and the external name
+-that was established by
+-.UL fopen ,
+-freeing the
+-file pointer for another file.
+-Since there is a limit on the number
+-of files
+-that a program may have open simultaneously,
+-it's a good idea to free things when they are no longer needed.
+-There is also another reason to call
+-.UL fclose 
+-on an output file
+-\(em it flushes the buffer
+-in which
+-.UL putc
+-is collecting output.
+-.UL fclose \& (
+-is called automatically for each open file
+-when a program terminates normally.)
+-.NH 2
+-Error Handling \(em Stderr and Exit
+-.PP
+-.UL stderr
+-is assigned to a program in the same way that
+-.UL stdin
+-and
+-.UL stdout
+-are.
+-Output written on 
+-.UL stderr
+-appears on the user's terminal
+-even if the standard output is redirected.
+-.IT wc
+-writes its diagnostics on
+-.UL stderr
+-instead of
+-.UL stdout
+-so that if one of the files can't
+-be accessed for some reason,
+-the message
+-finds its way to the user's terminal instead of disappearing
+-down a pipeline
+-or into an output file.
+-.PP
+-The program actually signals errors in another way,
+-using the function
+-.UL exit 
+-to terminate program execution.
+-The argument of
+-.UL exit
+-is available to whatever process
+-called it (see Section 6),
+-so the success or failure
+-of the program can be tested by another program
+-that uses this one as a sub-process.
+-By convention, a return value of 0
+-signals that all is well;
+-non-zero values signal abnormal situations.
+-.PP
+-.UL exit
+-itself
+-calls
+-.UL fclose
+-for each open output file,
+-to flush out any buffered output,
+-then calls
+-a routine named
+-.UL _exit .
+-The function
+-.UL _exit
+-causes immediate termination without any buffer flushing;
+-it may be called directly if desired.
+-.NH 2
+-Miscellaneous I/O Functions
+-.PP
+-The standard I/O library provides several other I/O functions
+-besides those we have illustrated above.
+-.PP
+-Normally output with
+-.UL putc ,
+-etc., is buffered (except to
+-.UL stderr );
+-to force it out immediately, use
+-.UL fflush(fp) .
+-.PP
+-.UL fscanf
+-is identical to
+-.UL scanf ,
+-except that its first argument is a file pointer
+-(as with
+-.UL fprintf )
+-that specifies the file from which the input comes;
+-it returns
+-.UL EOF
+-at end of file.
+-.PP
+-The functions
+-.UL sscanf
+-and
+-.UL sprintf
+-are identical to
+-.UL fscanf
+-and
+-.UL fprintf ,
+-except that the first argument names a character string
+-instead of a file pointer.
+-The conversion is done from the string
+-for 
+-.UL sscanf 
+-and into it for
+-.UL sprintf .
+-.PP
+-.UL fgets(buf,\ size,\ fp)
+-copies the next line from
+-.UL fp ,
+-up to and including a newline,
+-into 
+-.UL buf ;
+-at most
+-.UL size-1
+-characters are copied;
+-it returns
+-.UL NULL
+-at end of file.
+-.UL fputs(buf,\ fp)
+-writes the string in
+-.UL buf
+-onto file
+-.UL fp .
+-.PP
+-The function
+-.UL ungetc(c,\ fp)
+-``pushes back'' the character
+-.UL c
+-onto the input stream
+-.UL fp ;
+-a subsequent call to
+-.UL getc ,
+-.UL fscanf ,
+-etc.,
+-will encounter 
+-.UL c .
+-Only one character of pushback per file is permitted.
+//GO.SYSIN DD p3
+echo p4
+sed 's/.//' >p4 <<'//GO.SYSIN DD p4'
+-.NH
+-LOW-LEVEL I/O
+-.PP
+-This section describes the 
+-bottom level of I/O on the
+-.UC UNIX
+-system.
+-The lowest level of I/O in
+-.UC UNIX
+-provides no buffering or any other services;
+-it is in fact a direct entry into the operating system.
+-You are entirely on your own,
+-but on the other hand,
+-you have the most control over what happens.
+-And since the calls and usage are quite simple,
+-this isn't as bad as it sounds.
+-.NH 2
+-File Descriptors
+-.PP
+-In the
+-.UC UNIX
+-operating system,
+-all input and output is done
+-by reading or writing files,
+-because all peripheral devices, even the user's terminal,
+-are files in the file system.
+-This means that a single, homogeneous interface
+-handles all communication between a program and peripheral devices.
+-.PP
+-In the most general case,
+-before reading or writing a file,
+-it is necessary to inform the system
+-of your intent to do so,
+-a process called
+-``opening'' the file.
+-If you are going to write on a file,
+-it may also be necessary to create it.
+-The system checks your right to do so
+-(Does the file exist?
+-Do you have permission to access it?),
+-and if all is well,
+-returns a small positive integer
+-called a
+-.ul
+-file descriptor.
+-Whenever I/O is to be done on the file,
+-the file descriptor is used instead of the name to identify the file.
+-(This is roughly analogous to the use of
+-.UC READ(5,...)
+-and
+-.UC WRITE(6,...)
+-in Fortran.)
+-All
+-information about an open file is maintained by the system;
+-the user program refers to the file
+-only
+-by the file descriptor.
+-.PP
+-The file pointers discussed in section 3
+-are similar in spirit to file descriptors,
+-but file descriptors are more fundamental.
+-A file pointer is a pointer to a structure that contains,
+-among other things, the file descriptor for the file in question.
+-.PP
+-Since input and output involving the user's terminal
+-are so common,
+-special arrangements exist to make this convenient.
+-When the command interpreter (the
+-``shell'')
+-runs a program,
+-it opens
+-three files, with file descriptors 0, 1, and 2,
+-called the standard input,
+-the standard output, and the standard error output.
+-All of these are normally connected to the terminal,
+-so if a program reads file descriptor 0
+-and writes file descriptors 1 and 2,
+-it can do terminal I/O
+-without worrying about opening the files.
+-.PP
+-If I/O is redirected 
+-to and from files with
+-.UL < 
+-and
+-.UL > ,
+-as in
+-.P1
+-prog <infile >outfile
+-.P2
+-the shell changes the default assignments for file descriptors
+-0 and 1
+-from the terminal to the named files.
+-Similar observations hold if the input or output is associated with a pipe.
+-Normally file descriptor 2 remains attached to the terminal,
+-so error messages can go there.
+-In all cases,
+-the file assignments are changed by the shell,
+-not by the program.
+-The program does not need to know where its input
+-comes from nor where its output goes,
+-so long as it uses file 0 for input and 1 and 2 for output.
+-.NH 2
+-Read and Write
+-.PP
+-All input and output is done by
+-two functions called
+-.UL read
+-and
+-.UL write .
+-For both, the first argument is a file descriptor.
+-The second argument is a buffer in your program where the data is to
+-come from or go to.
+-The third argument is the number of bytes to be transferred.
+-The calls are
+-.P1
+-n_read = read(fd, buf, n);
+-
+-n_written = write(fd, buf, n);
+-.P2
+-Each call returns a byte count
+-which is the number of bytes actually transferred.
+-On reading,
+-the number of bytes returned may be less than
+-the number asked for,
+-because fewer than
+-.UL n
+-bytes remained to be read.
+-(When the file is a terminal,
+-.UL read
+-normally reads only up to the next newline,
+-which is generally less than what was requested.)
+-A return value of zero bytes implies end of file,
+-and
+-.UL -1
+-indicates an error of some sort.
+-For writing, the returned value is the number of bytes
+-actually written;
+-it is generally an error if this isn't equal
+-to the number supposed to be written.
+-.PP
+-The number of bytes to be read or written is quite arbitrary.
+-The two most common values are 
+-1,
+-which means one character at a time
+-(``unbuffered''),
+-and
+-512,
+-which corresponds to a physical blocksize on many peripheral devices.
+-This latter size will be most efficient,
+-but even character at a time I/O
+-is not inordinately expensive.
+-.PP
+-Putting these facts together,
+-we can write a simple program to copy
+-its input to its output.
+-This program will copy anything to anything,
+-since the input and output can be redirected to any file or device.
+-.P1
+-#define       BUFSIZE 512     /* best size for PDP-11 UNIX */
+-
+-main()        /* copy input to output */
+-{
+-      char    buf[BUFSIZE];
+-      int     n;
+-
+-      while ((n = read(0, buf, BUFSIZE)) > 0)
+-              write(1, buf, n);
+-      exit(0);
+-}
+-.P2
+-If the file size is not a multiple of
+-.UL BUFSIZE ,
+-some 
+-.UL read
+-will return a smaller number of bytes
+-to be written by
+-.UL write ;
+-the next call to 
+-.UL read
+-after that
+-will return zero.
+-.PP
+-It is instructive to see how
+-.UL read
+-and
+-.UL write
+-can be used to construct
+-higher level routines like
+-.UL getchar ,
+-.UL putchar ,
+-etc.
+-For example,
+-here is a version of
+-.UL getchar
+-which does unbuffered input.
+-.P1
+-#define       CMASK   0377    /* for making char's > 0 */
+-
+-getchar()     /* unbuffered single character input */
+-{
+-      char c;
+-
+-      return((read(0, &c, 1) > 0) ? c & CMASK : EOF);
+-}
+-.P2
+-.UL c
+-.ul
+-must
+-be declared
+-.UL char ,
+-because
+-.UL read
+-accepts a character pointer.
+-The character being returned must be masked with
+-.UL 0377
+-to ensure that it is positive;
+-otherwise sign extension may make it negative.
+-(The constant
+-.UL 0377
+-is appropriate for the
+-.UC PDP -11
+-but not necessarily for other machines.)
+-.PP
+-The second version of
+-.UL getchar
+-does input in big chunks,
+-and hands out the characters one at a time.
+-.P1
+-#define       CMASK   0377    /* for making char's > 0 */
+-#define       BUFSIZE 512
+-
+-getchar()     /* buffered version */
+-{
+-      static char     buf[BUFSIZE];
+-      static char     *bufp = buf;
+-      static int      n = 0;
+-
+-      if (n == 0) {   /* buffer is empty */
+-              n = read(0, buf, BUFSIZE);
+-              bufp = buf;
+-      }
+-      return((--n >= 0) ? *bufp++ & CMASK : EOF);
+-}
+-.P2
+-.NH 2
+-Open, Creat, Close, Unlink
+-.PP
+-Other than the default
+-standard input, output and error files,
+-you must explicitly open files in order to
+-read or write them.
+-There are two system entry points for this,
+-.UL open
+-and
+-.UL creat 
+-[sic].
+-.PP
+-.UL open
+-is rather like the
+-.UL  fopen
+-discussed in the previous section,
+-except that instead of returning a file pointer,
+-it returns a file descriptor,
+-which is just an
+-.UL int .
+-.P1
+-int fd;
+-
+-fd = open(name, rwmode);
+-.P2
+-As with
+-.UL fopen ,
+-the
+-.UL name
+-argument
+-is a character string corresponding to the external file name.
+-The access mode argument
+-is different, however:
+-.UL rwmode
+-is 0 for read, 1 for write, and 2 for read and write access.
+-.UL open
+-returns
+-.UL -1
+-if any error occurs;
+-otherwise it returns a valid file descriptor.
+-.PP
+-It is an error to 
+-try to
+-.UL open
+-a file that does not exist.
+-The entry point
+-.UL creat
+-is provided to create new files,
+-or to re-write old ones.
+-.P1
+-fd = creat(name, pmode);
+-.P2
+-returns a file descriptor
+-if it was able to create the file
+-called
+-.UL name ,
+-and
+-.UL -1
+-if not.
+-If the file
+-already exists,
+-.UL creat
+-will truncate it to zero length;
+-it is not an error to
+-.UL creat
+-a file that already exists.
+-.PP
+-If the file is brand new,
+-.UL creat
+-creates it with the
+-.ul
+-protection mode 
+-specified by
+-the
+-.UL pmode
+-argument.
+-In the
+-.UC UNIX
+-file system,
+-there are nine bits of protection information
+-associated with a file,
+-controlling read, write and execute permission for
+-the owner of the file,
+-for the owner's group,
+-and for all others.
+-Thus a three-digit octal number
+-is most convenient for specifying the permissions.
+-For example,
+-0755
+-specifies read, write and execute permission for the owner,
+-and read and execute permission for the group and everyone else.
+-.PP
+-To illustrate,
+-here is a simplified version of
+-the
+-.UC UNIX
+-utility
+-.IT cp ,
+-a program which copies one file to another.
+-(The main simplification is that our version
+-copies only one file,
+-and does not permit the second argument
+-to be a directory.)
+-.P1
+-#define NULL 0
+-#define BUFSIZE 512
+-#define PMODE 0644 /* RW for owner, R for group, others */
+-
+-main(argc, argv)      /* cp: copy f1 to f2 */
+-int argc;
+-char *argv[];
+-{
+-      int     f1, f2, n;
+-      char    buf[BUFSIZE];
+-
+-      if (argc != 3)
+-              error("Usage: cp from to", NULL);
+-      if ((f1 = open(argv[1], 0)) == -1)
+-              error("cp: can't open %s", argv[1]);
+-      if ((f2 = creat(argv[2], PMODE)) == -1)
+-              error("cp: can't create %s", argv[2]);
+-
+-      while ((n = read(f1, buf, BUFSIZE)) > 0)
+-              if (write(f2, buf, n) != n)
+-                      error("cp: write error", NULL);
+-      exit(0);
+-}
+-.P2
+-.P1
+-error(s1, s2) /* print error message and die */
+-char *s1, *s2;
+-{
+-      printf(s1, s2);
+-      printf("\n");
+-      exit(1);
+-}
+-.P2
+-.PP
+-As we said earlier,
+-there is a limit (typically 15-25)
+-on the number of files which a program
+-may have open simultaneously.
+-Accordingly, any program which intends to process
+-many files must be prepared to re-use
+-file descriptors.
+-The routine
+-.UL close
+-breaks the connection between a file descriptor
+-and an open file,
+-and frees the
+-file descriptor for use with some other file.
+-Termination of a program
+-via
+-.UL exit
+-or return from the main program closes all open files.
+-.PP
+-The function
+-.UL unlink(filename)
+-removes the file
+-.UL filename
+-from the file system.
+-.NH 2
+-Random Access \(em Seek and Lseek
+-.PP
+-File I/O is normally sequential:
+-each
+-.UL read
+-or
+-.UL write
+-takes place at a position in the file
+-right after the previous one.
+-When necessary, however,
+-a file can be read or written in any arbitrary order.
+-The
+-system call
+-.UL lseek
+-provides a way to move around in
+-a file without actually reading
+-or writing:
+-.P1
+-lseek(fd, offset, origin);
+-.P2
+-forces the current position in the file
+-whose descriptor is
+-.UL fd
+-to move to position
+-.UL offset ,
+-which is taken relative to the location
+-specified by
+-.UL origin .
+-Subsequent reading or writing will begin at that position.
+-.UL offset
+-is
+-a
+-.UL long ;
+-.UL fd
+-and
+-.UL origin
+-are
+-.UL int 's.
+-.UL origin
+-can be 0, 1, or 2 to specify that 
+-.UL offset
+-is to be
+-measured from
+-the beginning, from the current position, or from the
+-end of the file respectively.
+-For example,
+-to append to a file,
+-seek to the end before writing:
+-.P1
+-lseek(fd, 0L, 2);
+-.P2
+-To get back to the beginning (``rewind''),
+-.P1
+-lseek(fd, 0L, 0);
+-.P2
+-Notice the
+-.UL 0L
+-argument;
+-it could also be written as
+-.UL (long)\ 0 .
+-.PP
+-With 
+-.UL lseek ,
+-it is possible to treat files more or less like large arrays,
+-at the price of slower access.
+-For example, the following simple function reads any number of bytes
+-from any arbitrary place in a file.
+-.P1
+-get(fd, pos, buf, n) /* read n bytes from position pos */
+-int fd, n;
+-long pos;
+-char *buf;
+-{
+-      lseek(fd, pos, 0);      /* get to pos */
+-      return(read(fd, buf, n));
+-}
+-.P2
+-.PP
+-In pre-version 7
+-.UC UNIX ,
+-the basic entry point to the I/O system
+-is called
+-.UL seek .
+-.UL seek
+-is identical to
+-.UL lseek ,
+-except that its
+-.UL  offset 
+-argument is an
+-.UL int
+-rather than  a
+-.UL long .
+-Accordingly,
+-since
+-.UC PDP -11
+-integers have only 16 bits,
+-the
+-.UL offset
+-specified
+-for
+-.UL seek
+-is limited to 65,535;
+-for this reason,
+-.UL origin
+-values of 3, 4, 5 cause
+-.UL seek
+-to multiply the given offset by 512
+-(the number of bytes in one physical block)
+-and then interpret
+-.UL origin
+-as if it were 0, 1, or 2 respectively.
+-Thus to get to an arbitrary place in a large file
+-requires two seeks, first one which selects
+-the block, then one which
+-has
+-.UL origin
+-equal to 1 and moves to the desired byte within the block.
+-.NH 2
+-Error Processing
+-.PP
+-The routines discussed in this section,
+-and in fact all the routines which are direct entries into the system
+-can incur errors.
+-Usually they indicate an error by returning a value of \-1.
+-Sometimes it is nice to know what sort of error occurred;
+-for this purpose all these routines, when appropriate,
+-leave an error number in the external cell
+-.UL errno .
+-The meanings of the various error numbers are
+-listed
+-in the introduction to Section II
+-of the
+-.I
+-.UC UNIX
+-Programmer's Manual,
+-.R
+-so your program can, for example, determine if
+-an attempt to open a file failed because it did not exist
+-or because the user lacked permission to read it.
+-Perhaps more commonly,
+-you may want to print out the
+-reason for failure.
+-The routine
+-.UL perror
+-will print a message associated with the value
+-of
+-.UL errno ;
+-more generally,
+-.UL sys\_errno
+-is an array of character strings which can be indexed
+-by
+-.UL errno
+-and printed by your program.
+//GO.SYSIN DD p4
+echo p5
+sed 's/.//' >p5 <<'//GO.SYSIN DD p5'
+-.NH
+-PROCESSES
+-.PP
+-It is often easier to use a program written
+-by someone else than to invent one's own.
+-This section describes how to
+-execute a program from within another.
+-.NH 2
+-The ``System'' Function
+-.PP
+-The easiest way to execute a program from another
+-is to use
+-the standard library routine
+-.UL system .
+-.UL system
+-takes one argument, a command string exactly as typed
+-at the terminal
+-(except for the newline at the end)
+-and executes it.
+-For instance, to time-stamp the output of a program,
+-.P1
+-main()
+-{
+-      system("date");
+-      /* rest of processing */
+-}
+-.P2
+-If the command string has to be built from pieces,
+-the in-memory formatting capabilities of
+-.UL sprintf
+-may be useful.
+-.PP
+-Remember than
+-.UL getc
+-and
+-.UL putc
+-normally buffer their input;
+-terminal I/O will not be properly synchronized unless
+-this buffering is defeated.
+-For output, use 
+-.UL fflush ;
+-for input, see
+-.UL setbuf 
+-in the appendix.
+-.NH 2
+-Low-Level Process Creation \(em Execl and Execv
+-.PP
+-If you're not using the standard library,
+-or if you need finer control over what
+-happens,
+-you will have to construct calls to other programs
+-using the more primitive routines that the standard
+-library's
+-.UL system
+-routine is based on.
+-.PP
+-The most basic operation is to execute another program
+-.ul
+-without
+-.IT returning ,
+-by using the routine
+-.UL execl  .
+-To print the date as the last action of a running program,
+-use
+-.P1
+-execl("/bin/date", "date", NULL);
+-.P2
+-The first argument to
+-.UL execl
+-is the
+-.ul
+-file name
+-of the command; you have to know where it is found
+-in the file system.
+-The second argument is conventionally
+-the program name
+-(that is, the last component of the file name),
+-but this is seldom used except as a place-holder.
+-If the command takes arguments, they are strung out after
+-this;
+-the end of the list is marked by a 
+-.UL NULL
+-argument.
+-.PP
+-The
+-.UL execl
+-call
+-overlays the existing program with
+-the new one,
+-runs that, then exits.
+-There is
+-.ul
+-no
+-return to the original program.
+-.PP
+-More realistically,
+-a program might fall into two or more phases
+-that communicate only through temporary files.
+-Here it is natural to make the second pass
+-simply an
+-.UL execl
+-call from the first.
+-.PP
+-The one exception to the rule that the original program never gets control
+-back occurs when there is an error, for example if the file can't be found
+-or is not executable.
+-If you don't know where
+-.UL date
+-is located, say
+-.P1
+-execl("/bin/date", "date", NULL);
+-execl("/usr/bin/date", "date", NULL);
+-fprintf(stderr, "Someone stole 'date'\n");
+-.P2
+-.PP
+-A variant of
+-.UL execl
+-called
+-.UL execv
+-is useful when you don't know in advance how many arguments there are going to be.
+-The call is
+-.P1
+-execv(filename, argp);
+-.P2
+-where
+-.UL argp
+-is an array of pointers to the arguments;
+-the last pointer in the array must be 
+-.UL NULL
+-so
+-.UL execv
+-can tell where the list ends.
+-As with
+-.UL execl ,
+-.UL filename
+-is the file in which the program is found, and
+-.UL argp[0]
+-is the name of the program.
+-(This arrangement is identical to the
+-.UL argv
+-array for program arguments.)
+-.PP
+-Neither of these routines provides the niceties of normal command execution.
+-There is no automatic search of multiple directories \(em
+-you have to know precisely where the command is located.
+-Nor do you get the expansion of metacharacters like
+-.UL < ,
+-.UL > ,
+-.UL * ,
+-.UL ? ,
+-and
+-.UL []
+-in the argument list.
+-If you want these, use
+-.UL execl
+-to invoke the shell
+-.UL sh ,
+-which then does all the work.
+-Construct a string
+-.UL commandline
+-that contains the complete command as it would have been typed
+-at the terminal, then say
+-.P1
+-execl("/bin/sh", "sh", "-c", commandline, NULL);
+-.P2
+-The shell is assumed to be at a fixed place,
+-.UL /bin/sh .
+-Its argument
+-.UL -c
+-says to treat the next argument
+-as a whole command line, so it does just what you want.
+-The only problem is in constructing the right information
+-in
+-.UL commandline .
+-.NH 2
+-Control of Processes \(em Fork and Wait
+-.PP
+-So far what we've talked about isn't really all that useful by itself.
+-Now we will show how to regain control after running
+-a program with
+-.UL execl
+-or
+-.UL execv .
+-Since these routines simply overlay the new program on the old one,
+-to save the old one requires that it first be split into
+-two copies;
+-one of these can be overlaid, while the other waits for the new,
+-overlaying program to finish.
+-The splitting is done by a routine called
+-.UL fork :
+-.P1
+-proc_id = fork();
+-.P2
+-splits the program into two copies, both of which continue to run.
+-The only difference between the two is the value of
+-.UL proc_id ,
+-the ``process id.''
+-In one of these processes (the ``child''),
+-.UL proc_id
+-is zero.
+-In the other
+-(the ``parent''),
+-.UL proc_id
+-is non-zero; it is the process number of the child.
+-Thus the basic way to call, and return from,
+-another program is
+-.P1
+-if (fork() == 0)
+-      execl("/bin/sh", "sh", "-c", cmd, NULL);        /* in child */
+-.P2
+-And in fact, except for handling errors, this is sufficient.
+-The
+-.UL fork
+-makes two copies of the program.
+-In the child, the value returned by
+-.UL fork
+-is zero, so it calls
+-.UL execl
+-which does the
+-.UL command
+-and then dies.
+-In the parent,
+-.UL fork
+-returns non-zero
+-so it skips the
+-.UL execl.
+-(If there is any error,
+-.UL fork
+-returns
+-.UL -1 ).
+-.PP
+-More often, the parent wants to wait for the child to terminate
+-before continuing itself.
+-This can be done with
+-the function
+-.UL wait :
+-.P1
+-int status;
+-
+-if (fork() == 0)
+-      execl(...);
+-wait(&status);
+-.P2
+-This still doesn't handle any abnormal conditions, such as a failure
+-of the
+-.UL execl
+-or
+-.UL fork ,
+-or the possibility that there might be more than one child running simultaneously.
+-(The
+-.UL wait
+-returns the
+-process id
+-of the terminated child, if you want to check it against the value
+-returned by
+-.UL fork .)
+-Finally, this fragment doesn't deal with any
+-funny behavior on the part of the child
+-(which is reported in
+-.UL status ).
+-Still, these three lines
+-are the heart of the standard library's
+-.UL system
+-routine,
+-which we'll show in a moment.
+-.PP
+-The
+-.UL  status 
+-returned by
+-.UL wait
+-encodes in its low-order eight bits
+-the system's idea of the child's termination status;
+-it is 0 for normal termination and non-zero to indicate
+-various kinds of problems.
+-The next higher eight bits are taken from the argument
+-of the call to
+-.UL exit
+-which caused a normal termination of the child process.
+-It is good coding practice
+-for all programs to return meaningful
+-status.
+-.PP
+-When a program is called by the shell,
+-the three file descriptors
+-0, 1, and 2 are set up pointing at the right files,
+-and all other possible file descriptors
+-are available for use.
+-When this program calls another one,
+-correct etiquette suggests making sure the same conditions
+-hold.
+-Neither
+-.UL fork
+-nor the
+-.UL exec
+-calls affects open files in any way.
+-If the parent is buffering output
+-that must come out before output from the child,
+-the parent must flush its buffers
+-before the
+-.UL execl .
+-Conversely,
+-if a caller buffers an input stream,
+-the called program will lose any information
+-that has been read by the caller.
+-.NH 2
+-Pipes
+-.PP
+-A
+-.ul
+-pipe
+-is an I/O channel intended for use
+-between two cooperating processes:
+-one process writes into the pipe,
+-while the other reads.
+-The system looks after buffering the data and synchronizing
+-the two processes.
+-Most pipes are created by the shell,
+-as in
+-.P1
+-ls | pr
+-.P2
+-which connects the standard output of
+-.UL ls
+-to the standard input of
+-.UL pr .
+-Sometimes, however, it is most convenient
+-for a process to set up its own plumbing;
+-in this section, we will illustrate how
+-the pipe connection is established and used.
+-.PP
+-The system call
+-.UL pipe
+-creates a pipe.
+-Since a pipe is used for both reading and writing,
+-two file descriptors are returned;
+-the actual usage is like this:
+-.P1
+-int   fd[2];
+-
+-stat = pipe(fd);
+-if (stat == -1)
+-      /* there was an error ... */
+-.P2
+-.UL fd
+-is an array of two file descriptors, where
+-.UL fd[0]
+-is the read side of the pipe and
+-.UL fd[1] 
+-is for writing.
+-These may be used in
+-.UL read ,
+-.UL write
+-and
+-.UL close
+-calls just like any other file descriptors.
+-.PP
+-If a process reads a pipe which is empty,
+-it will wait until data arrives;
+-if a process writes into a pipe which
+-is too full, it will wait until the pipe empties somewhat.
+-If the write side of the pipe is closed,
+-a subsequent
+-.UL  read 
+-will encounter end of file.
+-.PP
+-To illustrate the use of pipes in a realistic setting,
+-let us write a function called
+-.UL popen(cmd,\ mode) ,
+-which creates a process
+-.UL cmd
+-(just as
+-.UL system 
+-does),
+-and returns a file descriptor that will either
+-read or write that process, according to 
+-.UL mode .
+-That is,
+-the call
+-.P1
+-fout = popen("pr", WRITE);
+-.P2
+-creates a process that executes
+-the
+-.UL pr
+-command;
+-subsequent
+-.UL write
+-calls using the file descriptor
+-.UL fout
+-will send their data to that process
+-through the pipe.
+-.PP
+-.UL popen
+-first creates the
+-the pipe with a
+-.UL pipe
+-system call;
+-it then
+-.UL fork s
+-to create two copies of itself.
+-The child decides whether it is supposed to read or write,
+-closes the other side of the pipe,
+-then calls the shell (via
+-.UL execl )
+-to run the desired process.
+-The parent likewise closes the end of the pipe it does not use.
+-These closes are necessary to make end-of-file tests work properly.
+-For example, if a child that intends to read
+-fails to close the write end of the pipe, it will never
+-see the end of the pipe file, just because there is one writer
+-potentially active.
+-.P1
+-#include <stdio.h>
+-
+-#define       READ    0
+-#define       WRITE   1
+-#define       tst(a, b)       (mode == READ ? (b) : (a))
+-static        int     popen_pid;
+-
+-popen(cmd, mode)
+-char  *cmd;
+-int   mode;
+-{
+-      int p[2];
+-
+-      if (pipe(p) < 0)
+-              return(NULL);
+-      if ((popen_pid = fork()) == 0) {
+-              close(tst(p[WRITE], p[READ]));
+-              close(tst(0, 1));
+-              dup(tst(p[READ], p[WRITE]));
+-              close(tst(p[READ], p[WRITE]));
+-              execl("/bin/sh", "sh", "-c", cmd, 0);
+-              _exit(1);       /* disaster has occurred if we get here */
+-      }
+-      if (popen_pid == -1)
+-              return(NULL);
+-      close(tst(p[READ], p[WRITE]));
+-      return(tst(p[WRITE], p[READ]));
+-}
+-.P2
+-The sequence of
+-.UL close s
+-in the child
+-is a bit tricky.
+-Suppose
+-that the task is to create a child process that will read data from the parent.
+-Then the first
+-.UL close
+-closes the write side of the pipe,
+-leaving the read side open.
+-The lines
+-.P1
+-close(tst(0, 1));
+-dup(tst(p[READ], p[WRITE]));
+-.P2
+-are the conventional way to associate the pipe descriptor
+-with the standard input of the child.
+-The 
+-.UL close
+-closes file descriptor 0,
+-that is, the standard input.
+-.UL dup
+-is a system call that
+-returns a duplicate of an already open file descriptor.
+-File descriptors are assigned in increasing order
+-and the first available one is returned,
+-so
+-the effect of the
+-.UL dup
+-is to copy the file descriptor for the pipe (read side)
+-to file descriptor 0;
+-thus the read side of the pipe becomes the standard input.
+-(Yes, this is a bit tricky, but it's a standard idiom.)
+-Finally, the old read side of the pipe is closed.
+-.PP
+-A similar sequence of operations takes place
+-when the child process is supposed to write
+-from the parent instead of reading.
+-You may find it a useful exercise to step through that case.
+-.PP
+-The job is not quite done,
+-for we still need a function
+-.UL pclose
+-to close the pipe created by
+-.UL popen .
+-The main reason for using a separate function rather than
+-.UL close
+-is that it is desirable to wait for the termination of the child process.
+-First, the return value from
+-.UL pclose
+-indicates whether the process succeeded.
+-Equally important when a process creates several children
+-is that only a bounded number of unwaited-for children
+-can exist, even if some of them have terminated;
+-performing the
+-.UL wait
+-lays the child to rest.
+-Thus:
+-.P1
+-#include <signal.h>
+-
+-pclose(fd)    /* close pipe fd */
+-int fd;
+-{
+-      register r, (*hstat)(), (*istat)(), (*qstat)();
+-      int      status;
+-      extern int popen_pid;
+-
+-      close(fd);
+-      istat = signal(SIGINT, SIG_IGN);
+-      qstat = signal(SIGQUIT, SIG_IGN);
+-      hstat = signal(SIGHUP, SIG_IGN);
+-      while ((r = wait(&status)) != popen_pid && r != -1);
+-      if (r == -1)
+-              status = -1;
+-      signal(SIGINT, istat);
+-      signal(SIGQUIT, qstat);
+-      signal(SIGHUP, hstat);
+-      return(status);
+-}
+-.P2
+-The calls to
+-.UL signal
+-make sure that no interrupts, etc.,
+-interfere with the waiting process;
+-this is the topic of the next section.
+-.PP
+-The routine as written has the limitation that only one pipe may
+-be open at once, because of the single shared variable
+-.UL popen_pid ;
+-it really should be an array indexed by file descriptor.
+-A
+-.UL popen
+-function, with slightly different arguments and return value is available
+-as part of the standard I/O library discussed below.
+-As currently written, it shares the same limitation.
+//GO.SYSIN DD p5
+echo p6
+sed 's/.//' >p6 <<'//GO.SYSIN DD p6'
+-.NH
+-SIGNALS \(em INTERRUPTS AND ALL THAT
+-.PP
+-This section is concerned with how to
+-deal gracefully with signals from
+-the outside world (like interrupts), and with program faults.
+-Since there's nothing very useful that
+-can be done from within C about program
+-faults, which arise mainly from illegal memory references
+-or from execution of peculiar instructions,
+-we'll discuss only the outside-world signals:
+-.IT interrupt ,
+-which is sent when the
+-.UC DEL
+-character is typed;
+-.IT quit ,
+-generated by the
+-.UC FS
+-character;
+-.IT hangup ,
+-caused by hanging up the phone;
+-and
+-.IT terminate ,
+-generated by the
+-.IT kill
+-command.
+-When one of these events occurs,
+-the signal is sent to
+-.IT  all 
+-processes which were started
+-from the corresponding terminal;
+-unless other arrangements have been made,
+-the signal
+-terminates the process.
+-In the
+-.IT quit
+-case, a core image file is written for debugging
+-purposes.
+-.PP
+-The routine which alters the default action
+-is
+-called
+-.UL signal .
+-It has two arguments: the first specifies the signal, and the second
+-specifies how to treat it.
+-The first argument is just a number code, but the second is the
+-address is either a function, or a somewhat strange code
+-that requests that the signal either be ignored, or that it be
+-given the default action.
+-The include file
+-.UL signal.h
+-gives names for the various arguments, and should always be included
+-when signals are used.
+-Thus
+-.P1
+-#include <signal.h>
+- ...
+-signal(SIGINT, SIG_IGN);
+-.P2
+-causes interrupts to be ignored, while
+-.P1
+-signal(SIGINT, SIG_DFL);
+-.P2
+-restores the default action of process termination.
+-In all cases,
+-.UL signal
+-returns the previous value of the signal.
+-The second argument to
+-.UL signal
+-may instead be the name of a function
+-(which has to be declared explicitly if
+-the compiler hasn't seen it already).
+-In this case, the named routine will be called
+-when the signal occurs.
+-Most commonly this facility is used
+-to allow the program to clean up
+-unfinished business before terminating, for example to
+-delete a temporary file:
+-.P1
+-#include <signal.h>
+-
+-main()
+-{
+-      int onintr();
+-
+-      if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+-              signal(SIGINT, onintr);
+-
+-      /* Process ... */
+-
+-      exit(0);
+-}
+-
+-onintr()
+-{
+-      unlink(tempfile);
+-      exit(1);
+-}
+-.P2
+-.PP
+-Why the test and the double call to
+-.UL signal ?
+-Recall that signals like interrupt are sent to
+-.ul
+-all
+-processes started from a particular terminal.
+-Accordingly, when a program is to be run
+-non-interactively
+-(started by
+-.UL & ),
+-the shell turns off interrupts for it
+-so it won't be stopped by interrupts intended for foreground processes.
+-If this program began by announcing that all interrupts were to be sent
+-to the
+-.UL onintr
+-routine regardless,
+-that would undo the shell's effort to protect it
+-when run in the background.
+-.PP
+-The solution, shown above, is to test the state of interrupt handling,
+-and to continue to ignore interrupts if they are already being ignored.
+-The code as written
+-depends on the fact that
+-.UL signal
+-returns the previous state of a particular signal.
+-If signals were already being ignored, the process should continue to ignore them;
+-otherwise, they should be caught.
+-.PP
+-A more sophisticated program may wish to intercept
+-an interrupt and interpret it as a request
+-to stop what it is doing
+-and return to its own command-processing loop.
+-Think of a text editor:
+-interrupting a long printout should not cause it
+-to terminate and lose the work
+-already done.
+-The outline of the code for this case is probably best written like this:
+-.P1
+-#include <signal.h>
+-#include <setjmp.h>
+-jmp_buf       sjbuf;
+-
+-main()
+-{
+-      int (*istat)(), onintr();
+-
+-      istat = signal(SIGINT, SIG_IGN);        /* save original status */
+-      setjmp(sjbuf);  /* save current stack position */
+-      if (istat != SIG_IGN)
+-              signal(SIGINT, onintr);
+-
+-      /* main processing loop */
+-}
+-.P2
+-.P1
+-onintr()
+-{
+-      printf("\nInterrupt\n");
+-      longjmp(sjbuf); /* return to saved state */
+-}
+-.P2
+-The include file
+-.UL setjmp.h
+-declares the type
+-.UL jmp_buf
+-an object in which the state
+-can be saved.
+-.UL sjbuf
+-is such an object; it is an array of some sort.
+-The
+-.UL setjmp
+-routine then saves
+-the state of things.
+-When an interrupt occurs,
+-a call is forced to the
+-.UL onintr
+-routine,
+-which can print a message, set flags, or whatever.
+-.UL longjmp
+-takes as argument an object stored into by
+-.UL setjmp ,
+-and restores control
+-to the location after the call to
+-.UL setjmp ,
+-so control (and the stack level) will pop back
+-to the place in the main routine where
+-the signal is set up and the main loop entered.
+-Notice, by the way, that
+-the signal
+-gets set again after an interrupt occurs.
+-This is necessary; most signals are automatically
+-reset to their default action when they occur.
+-.PP
+-Some programs that want to detect signals simply can't be stopped
+-at an arbitrary point,
+-for example in the middle of updating a linked list.
+-If the routine called on occurrence of a signal
+-sets a flag and then
+-returns instead of calling
+-.UL exit
+-or
+-.UL longjmp ,
+-execution will continue
+-at the exact point it was interrupted.
+-The interrupt flag can then be tested later.
+-.PP
+-There is one difficulty associated with this
+-approach.
+-Suppose the program is reading the
+-terminal when the interrupt is sent.
+-The specified routine is duly called; it sets its flag
+-and returns.
+-If it were really true, as we said
+-above, that ``execution resumes at the exact point it was interrupted,''
+-the program would continue reading the terminal
+-until the user typed another line.
+-This behavior might well be confusing, since the user
+-might not know that the program is reading;
+-he presumably would prefer to have the signal take effect instantly.
+-The method chosen to resolve this difficulty
+-is to terminate the terminal read when execution
+-resumes after the signal, returning an error code
+-which indicates what happened.
+-.PP
+-Thus programs which catch and resume
+-execution after signals should be prepared for ``errors''
+-which are caused by interrupted
+-system calls.
+-(The ones to watch out for are reads from a terminal,
+-.UL wait ,
+-and
+-.UL pause .)
+-A program
+-whose
+-.UL onintr
+-program just sets
+-.UL intflag ,
+-resets the interrupt signal, and returns,
+-should usually include code like the following when it reads
+-the standard input:
+-.P1
+-if (getchar() == EOF)
+-      if (intflag)
+-              /* EOF caused by interrupt */
+-      else
+-              /* true end-of-file */
+-.P2
+-.PP
+-A final subtlety to keep in mind becomes important
+-when signal-catching is combined with execution of other programs.
+-Suppose a program catches interrupts, and also includes
+-a method (like ``!'' in the editor)
+-whereby other programs can be executed.
+-Then the code should look something like this:
+-.P1
+-if (fork() == 0)
+-      execl(...);
+-signal(SIGINT, SIG_IGN);      /* ignore interrupts */
+-wait(&status);        /* until the child is done */
+-signal(SIGINT, onintr);       /* restore interrupts */
+-.P2
+-Why is this?
+-Again, it's not obvious but not really difficult.
+-Suppose the program you call catches its own interrupts.
+-If you interrupt the subprogram,
+-it will get the signal and return to its
+-main loop, and probably read your terminal.
+-But the calling program will also pop out of
+-its wait for the subprogram and read your terminal.
+-Having two processes reading
+-your terminal is very unfortunate,
+-since the system figuratively flips a coin to decide
+-who should get each line of input.
+-A simple way out is to have the parent program
+-ignore interrupts until the child is done.
+-This reasoning is reflected in the standard I/O library function
+-.UL system :
+-.P1
+-#include <signal.h>
+-
+-system(s)     /* run command string s */
+-char *s;
+-{
+-      int status, pid, w;
+-      register int (*istat)(), (*qstat)();
+-
+-      if ((pid = fork()) == 0) {
+-              execl("/bin/sh", "sh", "-c", s, 0);
+-              _exit(127);
+-      }
+-      istat = signal(SIGINT, SIG_IGN);
+-      qstat = signal(SIGQUIT, SIG_IGN);
+-      while ((w = wait(&status)) != pid && w != -1)
+-              ;
+-      if (w == -1)
+-              status = -1;
+-      signal(SIGINT, istat);
+-      signal(SIGQUIT, qstat);
+-      return(status);
+-}
+-.P2
+-.PP
+-As an aside on declarations,
+-the function
+-.UL signal
+-obviously has a rather strange second argument.
+-It is in fact a pointer to a function delivering an integer,
+-and this is also the type of the signal routine itself.
+-The two values
+-.UL SIG_IGN
+-and
+-.UL SIG_DFL
+-have the right type, but are chosen so they coincide with
+-no possible actual functions.
+-For the enthusiast, here is how they are defined for the PDP-11;
+-the definitions should be sufficiently ugly
+-and nonportable to encourage use of the include file.
+-.P1
+-#define       SIG_DFL (int (*)())0
+-#define       SIG_IGN (int (*)())1
+-.P2
+//GO.SYSIN DD p6
+echo p8
+sed 's/.//' >p8 <<'//GO.SYSIN DD p8'
+-.SH
+-References
+-.LP
+-.IP [1]
+-K. L. Thompson and D. M. Ritchie,
+-.ul
+-The
+-.ul
+-.UC UNIX
+-.ul
+-Programmer's Manual,
+-Bell Laboratories, 1978.
+-.IP [2]
+-B. W. Kernighan and D. M. Ritchie,
+-.ul
+-The C Programming Language,
+-Prentice-Hall, Inc., 1978.
+-.IP [3]
+-B. W. Kernighan,
+-.UC UNIX \& ``
+-for Beginners \(em Second Edition.''
+-Bell Laboratories, 1978.
+//GO.SYSIN DD p8
+echo p9
+sed 's/.//' >p9 <<'//GO.SYSIN DD p9'
+-.sp 100
+-.TL
+-.ft R
+-Appendix \(em The Standard I/O Library
+-.AU
+-D. M. Ritchie
+-.AI
+-.MH
+-.PP
+-The standard I/O library
+-was designed with the following goals in mind.
+-.IP 1.
+-It must be as efficient as possible, both in time and in space,
+-so that there will be no hesitation in using it
+-no matter how critical the application.
+-.IP 2.
+-It must be simple to use, and also free of the magic
+-numbers and mysterious calls
+-whose use mars the understandability and portability
+-of many programs using older packages.
+-.IP 3.
+-The interface provided should be applicable on all machines,
+-whether or not the programs which implement it are directly portable
+-to other systems,
+-or to machines other than the PDP-11 running a version of
+-.UC UNIX .
+-.SH
+-1.  General Usage
+-.PP
+-Each program using the library must have the line
+-.P1
+-              #include <stdio.h>
+-.P2
+-which defines certain macros and variables.
+-The routines are in the normal C library,
+-so no special library argument is needed for loading.
+-All names in the include file intended only for internal use begin
+-with an underscore
+-.UL _
+-to reduce the possibility
+-of collision with a user name.
+-The names intended to be visible outside the package are
+-.IP \f3stdin\f1 10
+-The name of the standard input file
+-.IP \f3stdout\f1 10
+-The name of the standard output file
+-.IP \f3stderr\f1 10
+-The name of the standard error file
+-.IP \f3EOF\f1 10
+-is actually \-1, and is the value returned by
+-the read routines on end-of-file or error.
+-.IP \f3NULL\f1 10
+-is a notation for the null pointer, returned by
+-pointer-valued functions
+-to indicate an error
+-.IP \f3FILE\f1 10
+-expands to
+-.UL struct
+-.UL _iob
+-and is a useful
+-shorthand when declaring pointers
+-to streams.
+-.IP \f3BUFSIZ\f1 10
+-is a number (viz. 512)
+-of the size suitable for an I/O buffer supplied by the user.
+-See
+-.UL setbuf ,
+-below.
+-.IP \f3getc,\ getchar,\ putc,\ putchar,\ feof,\ ferror,\ f\&ileno\f1 10
+-.br
+-are defined as macros.
+-Their actions are described below;
+-they are mentioned here
+-to point out that it is not possible to
+-redeclare them
+-and that they are not actually functions;
+-thus, for example, they may not have breakpoints set on them.
+-.PP
+-The routines in this package
+-offer the convenience of automatic buffer allocation
+-and output flushing where appropriate.
+-The names
+-.UL stdin ,
+-.UL stdout ,
+-and
+-.UL stderr
+-are in effect constants and may not be assigned to.
+-.SH
+-2.  Calls
+-.nr PD .4v
+-.LP
+-.UL FILE\ *fopen(filename,\ type)\ char\ *filename,\ *type;
+-.nr PD 0
+-.IP
+-.br
+-opens the file and, if needed, allocates a buffer for it.
+-.UL filename
+-is a character string specifying the name.
+-.UL type
+-is a character string (not a single character).
+-It may be
+-.UL \&"r" ,
+-.UL \&"w" ,
+-or
+-.UL \&"a"
+-to indicate
+-intent to read, write, or append.
+-The value returned is a file pointer.
+-If it is
+-.UL  NULL
+-the attempt to open failed.
+-.ne 3
+-.nr PD .4v
+-.LP
+-.UL FILE\ *freopen(filename,\ type,\ ioptr)\ char\ *filename,\ *type;\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-The stream named by
+-.UL ioptr
+-is closed, if necessary, and then reopened
+-as if by
+-.UL fopen .
+-If the attempt to open fails,
+-.UL  NULL
+-is returned,
+-otherwise
+-.UL ioptr ,
+-which will now refer to the new file.
+-Often the reopened stream is
+-.UL stdin
+-or
+-.UL stdout .
+-.nr PD .4v
+-.LP
+-.UL int\ getc(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-returns the next character from the stream named by
+-.UL ioptr ,
+-which is a pointer to a file such as returned by
+-.UL fopen ,
+-or the name
+-.UL stdin .
+-The integer
+-.UL  EOF
+-is returned on end-of-file or when
+-an error occurs.
+-The null character
+-.UL \e0
+-is a legal character.
+-.nr PD .4v
+-.LP
+-.UL int\ fgetc(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-acts like
+-.UL getc
+-but is a genuine function,
+-not a macro,
+-so it can be pointed to, passed as an argument, etc.
+-.nr PD .4v
+-.LP
+-.UL putc(c,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-.UL putc
+-writes the character
+-.UL c
+-on the output stream named by
+-.UL ioptr ,
+-which is a value returned from
+-.UL fopen
+-or perhaps
+-.UL stdout
+-or
+-.UL stderr .
+-The character is returned as value,
+-but
+-.UL  EOF
+-is returned on error.
+-.nr PD .4v
+-.LP
+-.UL fputc(c,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-acts like
+-.UL putc
+-but is a genuine
+-function, not a macro.
+-.nr PD .4v
+-.LP
+-.UL fclose(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-The file corresponding to
+-.UL ioptr
+-is closed after any buffers are emptied.
+-A buffer allocated by the I/O system is freed.
+-.UL fclose
+-is automatic on normal termination of the program.
+-.nr PD .4v
+-.LP
+-.UL fflush(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-Any buffered information on the (output) stream named by
+-.UL ioptr
+-is written out.
+-Output files are normally buffered
+-if and only if they are not directed to the terminal;
+-however,
+-.UL stderr
+-always starts off unbuffered and remains so unless
+-.UL setbuf
+-is used, or unless it is reopened.
+-.nr PD .4v
+-.LP
+-.UL exit(errcode);
+-.nr PD 0
+-.IP
+-.br
+-terminates the process and returns its argument as status
+-to the parent.
+-This is a special version of the routine
+-which calls
+-.UL fflush
+-for each output file.
+-To terminate without flushing,
+-use
+-.UL _exit .
+-.nr PD .4v
+-.LP
+-.UL feof(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-returns non-zero when end-of-file
+-has occurred on the specified input stream.
+-.nr PD .4v
+-.LP
+-.UL ferror(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-returns non-zero when an error has occurred while reading
+-or writing the named stream.
+-The error indication lasts until the file has been closed.
+-.nr PD .4v
+-.LP
+-.UL getchar();
+-.nr PD 0
+-.IP
+-.br
+-is identical to
+-.UL getc(stdin) .
+-.nr PD .4v
+-.LP
+-.UL putchar(c);
+-.nr PD 0
+-.IP
+-.br
+-is identical to
+-.UL putc(c,\ stdout) .
+-.nr PD .4v
+-.nr PD .4v
+-.ne 2
+-.LP
+-.UL char\ *fgets(s,\ n,\ ioptr)\ char\ *s;\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-reads up to
+-.UL n-1
+-characters from the stream
+-.UL ioptr
+-into the character pointer
+-.UL s .
+-The read terminates with a newline character.
+-The newline character is placed in the buffer
+-followed by a null character.
+-.UL fgets
+-returns the first argument,
+-or
+-.UL  NULL
+-if error or end-of-file occurred.
+-.nr PD .4v
+-.nr PD .4v
+-.LP
+-.UL fputs(s,\ ioptr)\ char\ *s;\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-writes the null-terminated string (character array)
+-.UL s
+-on the stream
+-.UL ioptr .
+-No newline is appended.
+-No value is returned.
+-.nr PD .4v
+-.LP
+-.UL ungetc(c,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-The argument character
+-.UL c
+-is pushed back on the input stream named by
+-.UL ioptr .
+-Only one character may be pushed back.
+-.ne 5
+-.nr PD .4v
+-.LP
+-.UL printf(format,\ a1,\ ...)\ char\ *format;
+-.br
+-.UL fprintf(ioptr,\ format,\ a1,\ ...)\ FILE\ *ioptr;\ char\ *format;
+-.br
+-.UL sprintf(s,\ format,\ a1,\ ...)char\ *s,\ *format;
+-.br
+-.nr PD 0
+-.IP
+-.UL printf
+-writes on the standard output.
+-.UL fprintf
+-writes on the named output stream.
+-.UL sprintf
+-puts characters in the character array (string)
+-named by
+-.UL s .
+-The specifications are as described in section
+-.UL printf (3)
+-of the
+-.ul
+-.UC UNIX
+-.ul
+-Programmer's Manual.
+-.nr PD .4v
+-.LP
+-.UL scanf(format,\ a1,\ ...)\ char\ *format;
+-.br
+-.UL fscanf(ioptr,\ format,\ a1,\ ...)\ FILE\ *ioptr;\ char\ *format;
+-.br
+-.UL sscanf(s,\ format,\ a1,\ ...)\ char\ *s,\ *format;
+-.nr PD 0
+-.IP
+-.br
+-.UL scanf
+-reads from the standard input.
+-.UL fscanf
+-reads from the named input stream.
+-.UL sscanf
+-reads from the character string
+-supplied as
+-.UL s .
+-.UL scanf
+-reads characters, interprets
+-them according to a format, and stores the results in its arguments.
+-Each routine expects as arguments
+-a control string
+-.UL format ,
+-and a set of arguments,
+-.I
+-each of which must be a pointer,
+-.R
+-indicating where the converted input should be stored.
+-.if t .sp .4v
+-.UL scanf
+-returns as its value the number of successfully matched and assigned input
+-items.
+-This can be used to decide how many input items were found.
+-On end of file,
+-.UL EOF
+-is returned; note that this is different
+-from 0, which means that the next input character does not
+-match what was called for in the control string.
+-.RE
+-.nr PD .4v
+-.LP
+-.UL fread(ptr,\ sizeof(*ptr),\ nitems,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-reads
+-.UL nitems
+-of data beginning at
+-.UL ptr
+-from file
+-.UL ioptr .
+-No advance notification
+-that binary I/O is being done is required;
+-when, for portability reasons,
+-it becomes required, it will be done
+-by adding an additional character to the mode-string on the
+-.UL fopen
+-call.
+-.nr PD .4v
+-.LP
+-.UL fwrite(ptr,\ sizeof(*ptr),\ nitems,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-Like
+-.UL fread ,
+-but in the other direction.
+-.nr PD .4v
+-.LP
+-.UL rewind(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-rewinds the stream
+-named by
+-.UL ioptr .
+-It is not very useful except on input,
+-since a rewound output file is still open only for output.
+-.nr PD .4v
+-.LP
+-.UL system(string)\ char\ *string;
+-.nr PD 0
+-.IP
+-.br
+-The
+-.UL string
+-is executed by the shell as if typed at the terminal.
+-.nr PD .4v
+-.LP
+-.UL getw(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-returns the next word from the input stream named by
+-.UL ioptr .
+-.UL EOF
+-is returned on end-of-file or error,
+-but since this a perfectly good
+-integer
+-.UL feof
+-and
+-.UL ferror
+-should be used.
+-A ``word'' is 16 bits on the
+-.UC PDP-11.
+-.nr PD .4v
+-.LP
+-.UL putw(w,\ ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-writes the integer
+-.UL w
+-on the named output stream.
+-.nr PD .4v
+-.LP
+-.UL setbuf(ioptr,\ buf)\ FILE\ *ioptr;\ char\ *buf;
+-.nr PD 0
+-.IP
+-.br
+-.UL setbuf
+-may be used after a stream has been opened
+-but before I/O has started.
+-If
+-.UL buf
+-is
+-.UL NULL ,
+-the stream will be unbuffered.
+-Otherwise the buffer supplied will be used.
+-It must be a character array of sufficient size:
+-.P1
+-char  buf[BUFSIZ];
+-.P2
+-.nr PD .4v
+-.LP
+-.UL fileno(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-returns the integer file descriptor associated with the file.
+-.nr PD .4v
+-.LP
+-.UL fseek(ioptr,\ offset,\ ptrname)\ FILE\ *ioptr;\ long\ offset;
+-.nr PD 0
+-.IP
+-.br
+-The location of the next byte in the stream
+-named by
+-.UL ioptr
+-is adjusted.
+-.UL offset
+-is a long integer.
+-If
+-.UL ptrname
+-is 0, the offset is measured from the beginning of the file;
+-if
+-.UL ptrname
+-is 1, the offset is measured from the current read or
+-write pointer;
+-if
+-.UL ptrname
+-is 2, the offset is measured from the end of the file.
+-The routine accounts properly for any buffering.
+-(When this routine is used on
+-.UC UNIX \& non-
+-systems,
+-the offset must be a value returned from
+-.UL ftell
+-and the ptrname must be 0).
+-.ne 3
+-.nr PD .4v
+-.LP
+-.UL long\ ftell(ioptr)\ FILE\ *ioptr;
+-.nr PD 0
+-.IP
+-.br
+-The byte offset, measured from the beginning of the file,
+-associated with the named stream is returned.
+-Any buffering is properly accounted for.
+-(On
+-.UC UNIX \& non-
+-systems the value of this call is useful only
+-for handing to
+-.UL fseek ,
+-so as to position the file to the same place it was when
+-.UL ftell
+-was called.)
+-.nr PD .4v
+-.LP
+-.UL getpw(uid,\ buf)\ char\ *buf;
+-.nr PD 0
+-.IP
+-.br
+-The password file is searched for the given integer user ID.
+-If an appropriate line is found, it is copied into
+-the character array
+-.UL buf ,
+-and 0 is returned.
+-If no line is found corresponding to the user ID
+-then 1 is returned.
+-.nr PD .4v
+-.LP
+-.UL char\ *malloc(num);
+-.nr PD 0
+-.IP
+-.br
+-allocates
+-.UL num
+-bytes.
+-The pointer returned is sufficiently well aligned to be usable for any purpose.
+-.UL NULL
+-is returned if no space is available.
+-.nr PD .4v
+-.LP
+-.UL char\ *calloc(num,\ size);
+-.nr PD 0
+-.IP
+-.br
+-allocates space for
+-.UL num
+-items each of size
+-.UL size .
+-The space is guaranteed to be set to 0 and the pointer is
+-sufficiently well aligned to be usable for any purpose.
+-.UL NULL
+-is returned if no space is available .
+-.nr PD .4v
+-.LP
+-.UL cfree(ptr)\ char\ *ptr;
+-.nr PD 0
+-.IP
+-.br
+-Space is returned to the pool used by
+-.UL calloc .
+-Disorder can be expected if the pointer was not obtained
+-from
+-.UL calloc .
+-.nr PD .4v
+-.LP
+-The following are macros whose definitions may be obtained by including
+-.UL <ctype.h> .
+-.nr PD .4v
+-.LP
+-.UL isalpha(c)
+-returns non-zero if the argument is alphabetic.
+-.nr PD .4v
+-.LP
+-.UL isupper(c)
+-returns non-zero if the argument is upper-case alphabetic.
+-.nr PD .4v
+-.LP
+-.UL islower(c)
+-returns non-zero if the argument is lower-case alphabetic.
+-.nr PD .4v
+-.LP
+-.UL isdigit(c)
+-returns non-zero if the argument is a digit.
+-.nr PD .4v
+-.LP
+-.UL isspace(c)
+-returns non-zero if the argument is a spacing character:
+-tab, newline, carriage return, vertical tab,
+-form feed, space.
+-.nr PD .4v
+-.LP
+-.UL ispunct(c)
+-returns non-zero if the argument is
+-any punctuation character, i.e., not a space, letter,
+-digit or control character.
+-.nr PD .4v
+-.LP
+-.UL isalnum(c)
+-returns non-zero if the argument is a letter or a digit.
+-.nr PD .4v
+-.LP
+-.UL isprint(c)
+-returns non-zero if the argument is printable \(em
+-a letter, digit, or punctuation character.
+-.nr PD .4v
+-.LP
+-.UL iscntrl(c)
+-returns non-zero if the argument is a control character.
+-.nr PD .4v
+-.LP
+-.UL isascii(c)
+-returns non-zero if the argument is an ascii character, i.e., less than octal 0200.
+-.nr PD .4v
+-.LP
+-.UL toupper(c)
+-returns the upper-case character corresponding to the lower-case
+-letter
+-.UL c.
+-.nr PD .4v
+-.LP
+-.UL tolower(c)
+-returns the lower-case character corresponding to the upper-case
+-letter
+-.UL c .
+//GO.SYSIN DD p9
diff --git a/doc/7thEdMan/vol2/uucp.bun b/doc/7thEdMan/vol2/uucp.bun
new file mode 100644 (file)
index 0000000..162b7ab
--- /dev/null
@@ -0,0 +1,2521 @@
+# To unbundle, run this file
+echo implement
+sed 's/.//' >implement <<'//GO.SYSIN DD implement'
+-.RP
+-.TM 78-1273-5 39199 39199-11
+-.ND October 31, 1978
+-.if \n(TN>0 .FS
+-.if \n(TN>0 * On internship from Department 9444.
+-.if \n(TN>0 .FE
+-.TL
+-Uucp Implementation Description
+-.AU "MH 2C-572" 3126
+-.ie \n(TN>0 D. A. Nowitz\s-2\u*\d\s+2
+-.el D. A. Nowitz
+-.AB
+-.PP
+-Uucp is a series of programs designed to permit communication
+-between
+-UNIX
+-systems using either dial-up or hardwired communication
+-lines.
+-This document gives a detailed implementation
+-description of the current (second)
+-implementation of uucp.
+-.PP
+-This document is
+-for use by an administrator/installer of the system.
+-It is not meant as a user's guide.
+-.AE
+-.CS 12 5 15
+-.SH
+-Introduction
+-.LP
+-Uucp is a series of programs designed to permit communication between
+-.UX
+-systems using either dial-up or
+-hardwired communication lines.
+-It is used for file transfers and remote command execution.
+-The first version of the system was designed and implemented
+-by M. E. Lesk.\s-2\u1\d\s+2
+-.FS
+-1 M. E. Lesk and A. S. Cohen,
+-.UX
+-Software Distribution by Communication Link,
+-.ie \n(TN>0 TM-77-1274-3, TM-77-8234-5.
+-.el private communication.
+-.FE
+-This paper describes the current (second) implementation
+-of the system.
+-.LP
+-Uucp is a batch type operation.
+-Files are created in a spool directory for processing
+-by the uucp demons.
+-There are three types of files used for the execution
+-of work.
+-.I Data\ files
+-contain data for transfer to remote systems.
+-.I Work\ files
+-contain directions for file transfers between systems.
+-.I Execution\ files
+-are directions for
+-.UX
+-command executions which
+-involve the resources of one or more systems.
+-.LP
+-The uucp system consists of four primary and two
+-secondary programs.
+-The primary programs are:
+-.RS
+-.IP uucp 10
+-This program creates work and gathers data files in the spool directory
+-for the transmission of files.
+-.IP uux
+-This program creates work files, execute files and gathers data files for the remote execution of
+-.UX
+-commands.
+-.IP uucico
+-This program executes the work files for data transmission.
+-.IP uuxqt
+-This program executes the execution files for
+-.UX
+-command execution.
+-.RE
+-.ne 10
+-.LP
+-The secondary programs are:
+-.RS
+-.IP uulog 10
+-This program updates the log file with new entries
+-and reports on the status of uucp requests.
+-.IP uuclean
+-This program removes old files from the spool directory.
+-.LP
+-.RE
+-The remainder of this paper will describe the operation
+-of each program, the installation of the system,
+-the security aspects of the system,
+-the files required for execution,
+-and the administration of the system.
+-.NH
+-Uucp - UNIX to UNIX File Copy
+-.LP
+-The
+-.I uucp
+-command is the user's primary interface with the system.
+-The
+-.I uucp
+-command was designed to look like
+-.I cp
+-to the user.
+-The syntax is
+-.IP
+-.I uucp\ \ 
+-.B [
+-option
+-.B ]
+-\ ...\ \ source\ ...\ \ destination
+-.LP
+-where the source and destination
+-may contain the prefix
+-.I system-name!
+-which indicates the system on which the file
+-or files reside
+-or where they will be copied.
+-.LP
+-The options interpreted by
+-.I uucp
+-are:
+-.RS
+-.IP \-d 10
+-Make directories when necessary for copying the file.
+-.IP \-c
+-Don't copy source files to the spool directory,
+-but use the specified source when the actual
+-transfer takes place.
+-.IP \-g\fIletter\fR
+-Put
+-.I letter
+-in as the grade in the name of the work file.
+-(This can be used to change the order of work for a particular
+-machine.)
+-.IP \-m
+-Send mail on completion of the work.
+-.LP
+-The following options are used primarily for debugging:
+-.IP \-r 10
+-Queue the job but do not start
+-.I uucico
+-program.
+-.IP \-s\fIdir\fR
+-Use directory
+-.I dir
+-for the spool directory.
+-.IP \-x\fInum\fR
+-.I Num
+-is the level of debugging output desired.
+-.RE
+-.LP
+-The destination may be a directory name,
+-in which case the file name is taken from the last part of the
+-source's name.
+-The source
+-name may contain special shell characters
+-such as ``\fI?*[]\fR''.
+-If a source argument has a
+-.I system-name!
+-prefix for a remote system,
+-the file name expansion will be done on the remote system.
+-.LP
+-The command
+-.IP "" 12
+-uucp\ \ *.c\ \ usg!/usr/dan
+-.LP
+-will set up the transfer of all files whose names end with ``.c''
+-to the ``/usr/dan'' directory on the``usg'' machine.
+-.LP
+-The source and/or destination names may also contain a
+-.I ~user
+-prefix.
+-This translates to the login directory on
+-the specified system.
+-For names with partial path-names,
+-the current directory is prepended to the file name.
+-File names with
+-.I ../
+-are not permitted.
+-.LP
+-The command
+-.IP "" 12
+-uucp\ \ usg!~dan/*.h\ \ ~dan
+-.LP
+-will set up the transfer of files whose names end with ``.h''
+-in dan's login
+-directory on system ``usg'' to dan's local
+-login directory.
+-.LP
+-For each source file,
+-the program will check the source and destination
+-file-names
+-and the system-part of each to
+-classify the work into one of five types:
+-.RS
+-.IP [1]
+-Copy source to destination on local system.
+-.IP [2]
+-Receive files from other systems.
+-.IP [3]
+-Send files to a remote systems.
+-.IP [4]
+-Send files from remote systems
+-to another remote system.
+-.IP [5]
+-Receive files from remote systems when the source
+-contains special shell characters as
+-mentioned above.
+-.RE
+-.LP
+-After the work has been set up in the spool directory,
+-the
+-.I uucico
+-program is started to try to contact the other
+-machine to execute the work (unless the \-r option
+-was specified).
+-.SH
+-Type 1
+-.LP
+-A
+-.I cp
+-command is used to do the work.
+-The
+-.I \-d
+-and the
+-.I \-m
+-options are not honored in this case.
+-.SH
+-Type 2
+-.LP
+-A one line
+-.I "work file"
+-is created for each file requested and put in the spool directory
+-with the following fields, each separated by a blank.
+-(All
+-.I "work files"
+-and
+-.I "execute files"
+-use a blank as the field separator.)
+-.RS
+-.IP [1]
+-R
+-.IP [2]
+-The full path-name of the source or a ~user/path-name.
+-The
+-.I ~user
+-part will be expanded on the remote system.
+-.IP [3]
+-The full path-name of the destination file.
+-If the
+-.I ~user
+-notation is used, it will be immediately
+-expanded to be the login directory for the user.
+-.IP [4]
+-The user's login name.
+-.IP [5]
+-A ``\-'' followed by an option list.
+-(Only the \-m and \-d options will appear in this list.)
+-.RE
+-.KS
+-.SH
+-Type 3
+-.LP
+-For each source file, a
+-.I "work file"
+-is created and the source file is copied into a
+-.I "data file"
+-in the spool directory.
+-(A ``\-c'' option on the
+-.I uucp
+-command will prevent the
+-.I "data file"
+-from being made.)
+-In this case, the file will be transmitted from
+-the indicated source.)
+-The fields of each entry are given below.
+-.RS
+-.IP [1]
+-S
+-.IP [2]
+-The full-path name of the source file.
+-.IP [3]
+-The full-path name of the destination or
+-~user/file-name.
+-.IP [4]
+-The user's login name.
+-.IP [5]
+-A ``\-'' followed by an option list.
+-.IP [6]
+-The name of the
+-.I "data file"
+-in the spool directory.
+-.IP [7]
+-The file mode bits of the source file
+-in octal print format
+-(e.g. 0666).
+-.RE
+-.KE
+-.SH
+-Type 4 and Type 5
+-.LP
+-.I Uucp
+-generates a
+-.I uucp
+-command and sends it to the remote machine;
+-the remote
+-.I uucico
+-executes the
+-.I uucp
+-command.
+-.NH
+-Uux - UNIX To UNIX Execution
+-.LP
+-The
+-.I uux
+-command is used to set up the execution of a
+-.UX
+-command
+-where the execution machine and/or some of the
+-files are remote.
+-The syntax of the uux command is
+-.IP
+-.I uux\ \ 
+-.B [
+-\-
+-.B "] ["
+-option
+-.B ]
+-\ ...\ \ command-string
+-.LP
+-where the command-string is made up of one or more arguments.
+-All special shell characters such as ``<>|^'' must be quoted
+-either by quoting the entire command-string
+-or quoting the character as a separate argument.
+-Within the command-string, the command and file names may
+-contain a
+-.I system-name!
+-prefix.
+-All arguments which do not contain a ``!'' will not
+-be treated as files.
+-(They will not be copied to the execution machine.)
+-The ``\-'' is used to indicate that the standard input
+-for
+-.I command-string
+-should be inherited from the standard input
+-of the
+-.I uux
+-command.
+-The options, essentially for debugging, are:
+-.RS
+-.IP \-r 10
+-Don't start
+-.I uucico
+-or
+-.I uuxqt
+-after queuing the job;
+-.IP \-x\fInum\fR
+-Num is the level of debugging output desired.
+-.RE
+-.LP
+-The command
+-.IP "" 12
+-pr\ \ abc\ \ |\ \ uux\ \ \-\ \ usg!lpr
+-.LP
+-will set up the output of ``pr abc''
+-as standard input to an lpr command
+-to be executed on system ``usg''.
+-.LP
+-.I Uux
+-generates an
+-.I "execute file"
+-which contains the
+-names of the files required
+-for execution (including standard input),
+-the user's login name, the destination
+-of the standard output, and the command to be executed.
+-This file is either put in the spool directory
+-for local execution or sent to the remote system using
+-a generated send command (type 3 above).
+-.LP
+-For required files which are not on the execution machine,
+-.I uux
+-will generate receive command files (type 2 above).
+-These command-files will be put on the execution machine and
+-executed by the
+-.I uucico
+-program.
+-(This will work only if the local system has permission
+-to put files in the remote spool directory as controlled
+-by the remote
+-.I USERFILE .
+-)
+-.LP
+-The
+-.I "execute file"
+-will be processed
+-by the
+-.I uuxqt
+-program on the execution machine.
+-It is made up of several lines,
+-each of which contains an identification character
+-and one or more arguments.
+-The order of the lines in the file is not relevant
+-and some of the lines may not be present.
+-Each line is described below.
+-.RS
+-.SH
+-User Line
+-.IP
+-U\ \ user\ \ system
+-.LP
+-where the
+-.I user
+-and
+-.I system
+-are the requester's login name and system.
+-.SH
+-Required File Line
+-.IP
+-F file-name real-name
+-.LP
+-where the
+-.I file-name
+-is the generated name of a file for the execute machine
+-and
+-.I real-name
+-is the last part of the actual file name (contains no
+-path information).
+-Zero or more of these lines may be present in the
+-.I "execute file" .
+-The
+-.I uuxqt
+-program will check for the existence of all required
+-files before the command is executed.
+-.SH
+-Standard Input Line
+-.IP
+-I\ \ file-name
+-.LP
+-The standard input is either specified by a ``<'' in the
+-command-string or inherited from the standard input of the
+-.I uux
+-command if the ``\-'' option is used.
+-If a standard input is not specified,
+-``/dev/null'' is used.
+-.SH
+-Standard Output Line
+-.IP
+-O\ \ file-name\ \ system-name
+-.LP
+-The standard output is specified by a ``>'' within the
+-command-string.
+-If a standard output is not specified,
+-``/dev/null'' is used.
+-(Note \- the use of ``>>'' is not implemented.)
+-.SH
+-Command Line
+-.IP
+-C\ \ command\ \ 
+-.B [
+-arguments
+-.B ]
+-\ ...
+-.LP
+-The arguments are those specified in the command-string.
+-The standard input and standard output will not appear on this
+-line.
+-All
+-.I "required files"
+-will be moved to the execution directory (a subdirectory
+-of the spool directory)
+-and the
+-.UX
+-command is executed using the Shell specified in the
+-.I uucp.h
+-header file.
+-In addition, a shell ``PATH'' statement is prepended
+-to the command line as specified in the
+-.I uuxqt
+-program.
+-.LP
+-After execution, the standard output is copied or set up to be
+-sent to the proper place.
+-.RE
+-.NH
+-Uucico - Copy In, Copy Out
+-.LP
+-The
+-.I uucico
+-program will perform the following major functions:
+-.RS
+-.IP -\ \  3
+-Scan the spool directory for work.
+-.IP -\ \  
+-Place a call to a remote system.
+-.IP -\ \ 
+-Negotiate a line protocol to be used.
+-.IP -\ \ 
+-Execute all requests from both systems.
+-.IP -\ \ 
+-Log work requests and work completions.
+-.RE
+-.LP
+-.I Uucico
+-may be started in several ways;
+-.RS
+-.IP a) 5
+-by a system daemon,
+-.IP b)
+-by one of the
+-.I
+-uucp, uux, uuxqt
+-.R
+-or
+-.I uucico
+-programs,
+-.IP c)
+-directly by the user (this is usually for testing),
+-.IP d)
+-by a remote system.
+-(The uucico program should be specified as the ``shell''
+-field in the ``/etc/passwd'' file for the ``uucp'' logins.)
+-.RE
+-.LP
+-When started by method a, b or c, the program is considered to
+-be in
+-.I MASTER
+-mode.
+-In this mode, a connection will be made to a remote system.
+-If started by a remote system (method d),
+-the program is considered to be in
+-.I SLAVE
+-mode.
+-.LP
+-The
+-.I MASTER
+-mode will operate in one of two ways.
+-If no system name is specified
+-(\-s option not specified)
+-the program will scan the spool directory for
+-systems to call.
+-If a system name is specified, that system will be called,
+-and work will only be done for that system.
+-.LP
+-The
+-.I uucico
+-program is generally started by another program.
+-There are several options used for execution:
+-.RS
+-.IP \-r1 10
+-Start the program in
+-.I MASTER
+-mode.
+-This is used when
+-.I uucico
+-is started by a program or ``cron'' shell.
+-.IP \-s\fIsys\fR
+-Do work only for system
+-.I sys.
+-If
+-.I \-s
+-is specified,
+-a call to the specified system
+-will be made even if there is no work for system
+-.I sys
+-in the spool directory.
+-This is useful for polling systems which do not have
+-the hardware to initiate a connection.
+-.LP
+-The following options are used primarily for debugging:
+-.IP \-d\fIdir\fR
+-Use directory
+-.I dir
+-for the spool directory.
+-.IP \-x\fInum\fR
+-.I Num
+-is the level of debugging output desired.
+-.RE
+-.LP
+-The next part of this section will describe the major steps within
+-the
+-.I uucico
+-program.
+-.SH
+-Scan For Work
+-.LP
+-The names of the work related files in the spool directory have format
+-.IP
+-type . system-name grade number
+-.LP
+-where:
+-.IP
+-.I Type
+-is an upper case letter,
+-(
+-.I C
+--\ copy command file,
+-.I D
+--\ data file,
+-.I X
+--\ execute file);
+-.IP
+-.I System-name
+-is the remote system;
+-.IP
+-.I Grade
+-is a character;
+-.IP
+-.I Number
+-is a four digit, padded sequence number.
+-.LP
+-The file
+-.IP "" 12
+-C.res45n0031
+-.LP
+-would be a
+-.I "work file"
+-for a file transfer between the local
+-machine and the ``res45'' machine.
+-.LP
+-The scan for work is done by looking through the
+-spool directory for
+-.I "work files"
+-(files with prefix ``C.'').
+-A list is made of all systems to be called.
+-.I Uucico
+-will then call each system and process all
+-.I "work files" .
+-.SH
+-Call Remote System
+-.LP
+-The call is made using information from several
+-files which reside in the uucp program directory.
+-At the start of the call process, a lock is
+-set to forbid multiple conversations 
+-between the same two systems.
+-.LP
+-The system name is found in the
+-.I L.sys
+-file.
+-The information contained for each system is;
+-.RS
+-.IP [1]
+-system name,
+-.IP [2]
+-times to call the system
+-(days-of-week and times-of-day),
+-.IP [3]
+-device or device type to be used for call,
+-.IP [4]
+-line speed,
+-.IP [5]
+-phone number if field [3] is
+-.I ACU
+-or the device name (same as field [3])
+-if not
+-.I ACU,
+-.IP [6]
+-login information (multiple fields),
+-.RE
+-.LP
+-The time field is checked against the present time to see
+-if the call should be made.
+-.LP
+-The
+-.I
+-phone number
+-.R
+-may contain abbreviations (e.g. mh, py, boston) which get translated into dial
+-sequences using the
+-.I L-dialcodes
+-file.
+-.LP
+-The
+-.I L-devices
+-file is scanned using fields [3] and [4] from the
+-.I L.sys
+-file to find an available device for the call.
+-The program will try all devices which satisfy
+-[3] and [4] until the call is made, or no more
+-devices can be tried.
+-If a device is successfully opened, a lock file
+-is created so that another copy of
+-.I uucico
+-will not try to use it.
+-If the call is complete, the
+-.I
+-login information
+-.R
+-(field [6] of
+-.I L.sys )
+-is used to login.
+-.LP
+-The conversation between the two
+-.I uucico
+-programs begins with a handshake started by the called,
+-.I SLAVE ,
+-system.
+-The
+-.I SLAVE
+-sends a message to let the
+-.I MASTER
+-know it is ready to receive the system
+-identification and conversation sequence number.
+-The response from the
+-.I MASTER
+-is
+-verified by the
+-.I SLAVE
+-and if acceptable, protocol selection begins.
+-The
+-.I SLAVE
+-can also reply with a ``call-back required''
+-message in which case, the current conversation
+-is terminated.
+-.SH
+-Line Protocol Selection
+-.LP
+-The remote system sends a message
+-.IP "" 12
+-P\fIproto-list\fR
+-.LP
+-where proto-list is a string of characters, each
+-representing a line protocol.
+-.LP
+-The calling program checks the proto-list
+-for a letter corresponding to an available line
+-protocol and returns a
+-.I use-protocol
+-message.
+-The
+-.I use-protocol
+-message is
+-.IP "" 12
+-U\fIcode\fR
+-.LP
+-where code is either a one character
+-protocol letter or
+-.I N
+-which means there is no common protocol.
+-.SH
+-Work Processing
+-.LP
+-The initial roles (
+-.I MASTER
+-or
+-.I SLAVE
+-) for the work processing are
+-the mode in which each program starts.
+-(The 
+-.I MASTER
+-has been specified by the ``\-r1'' uucico option.)
+-The
+-.I MASTER
+-program does a work search similar to the
+-one used in the ``Scan For Work'' section.
+-.LP
+-There are five messages used during the
+-work processing, each specified by the first
+-character of the message.
+-They are;
+-.IP "" 12
+-.RS
+-.IP S 3
+-send a file,
+-.IP R
+-receive a file,
+-.IP C
+-copy complete,
+-.IP X
+-execute a
+-.I uucp
+-command,
+-.IP H
+-hangup.
+-.RE
+-.LP
+-The
+-.I MASTER
+-will send
+-.I R ,
+-.I S
+-or
+-.I X
+-messages until all work from the spool directory is
+-complete, at which point an
+-.I H
+-message will be sent.
+-The
+-.I SLAVE
+-will reply with
+-\fISY\fR, \fISN\fR, \fIRY\fR, \fIRN\fR, \fIHY\fR, \fIHN\fR,
+-\fIXY\fR, \fIXN\fr,
+-corresponding to
+-.I yes
+-or
+-.I no
+-for each request.
+-.LP
+-The send and receive replies are
+-based on permission to access the
+-requested file/directory using the
+-.I USERFILE
+-and read/write permissions of the file/directory.
+-After each file is copied into the spool directory
+-of the receiving system,
+-a copy-complete message is sent by the receiver of the file.
+-The message
+-.I CY
+-will be sent if the
+-file has successfully been moved from the
+-temporary spool file to the actual destination.
+-Otherwise, a
+-.I CN
+-message is sent.
+-(In the case of
+-.I CN ,
+-the transferred file will be in the spool
+-directory with a name beginning with ``TM'.)
+-The requests and results are logged on both systems.
+-.LP
+-The hangup response is determined by the
+-.I SLAVE
+-program by a work scan of the spool directory.
+-If work for the remote system exists in the
+-.I SLAVE's
+-spool directory, an
+-.I HN
+-message is sent and the programs switch roles.
+-If no work exists, an
+-.I HY
+-response is sent.
+-.SH
+-Conversation Termination
+-.LP
+-When a
+-.I HY
+-message is received by the
+-.I MASTER
+-it is echoed back to the
+-.I SLAVE
+-and the protocols are turned off.
+-Each program sends a final ``OO'' message to the
+-other.
+-The original
+-.I SLAVE
+-program will clean up and terminate.
+-The
+-.I MASTER
+-will proceed to call other systems
+-and process work as long as possible
+-or terminate if a
+-.I \-s
+-option was specified.
+-.LP
+-.NH
+-Uuxqt - Uucp Command Execution
+-.LP
+-The
+-.I uuxqt
+-program is used to execute
+-.I
+-execute files
+-.R
+-generated by
+-.I uux.
+-The
+-.I uuxqt
+-program may be started by either the
+-.I uucico
+-or
+-.I uux
+-programs.
+-The program scans the spool directory for
+-.I
+-execute files
+-.R
+-(prefix ``X.'').
+-Each one is checked to see if all the required files are available and
+-if so, the command line or send line is executed.
+-.LP
+-The
+-.I
+-execute file
+-.R
+-is described in the ``Uux''
+-section above.
+-.SH
+-Command Execution
+-.LP
+-The execution is accomplished by executing a
+-.I
+-sh \-c
+-.R
+-of the command line after appropriate
+-standard input and standard output have been opened.
+-If a standard output is specified, the program
+-will create a send command or copy the output
+-file as appropriate.
+-.NH
+-Uulog - Uucp Log Inquiry
+-.LP
+-The
+-.I uucp
+-programs create individual
+-log files for each program invocation.
+-Periodically,
+-.I uulog
+-may be executed to prepend these files to the
+-system logfile.
+-This method of logging was chosen to minimize file
+-locking of the logfile during program execution.
+-.LP
+-The
+-.I uulog
+-program merges the individual
+-log files and outputs specified log entries.
+-The output request is specified by the use of the
+-following options:
+-.RS
+-.IP \-s\fIsys\fR 9
+-Print entries where
+-.I sys
+-is the remote system name;
+-.IP \-u\fIuser\fR
+-Print entries for user
+-.I user.
+-.RE
+-.LP
+-The intersection of lines satisfying the two options is output.
+-A null
+-.I sys
+-or
+-.I user
+-means all system names or users respectively.
+-.NH
+-Uuclean - Uucp Spool Directory Cleanup
+-.LP
+-This program is typically started by the daemon, once a day.
+-Its function is to remove files from the spool directory which
+-are more than 3 days old.
+-These are usually files for work which can not be completed.
+-.LP
+-.LP
+-The options available are:
+-.RS
+-.IP \-d\fIdir\fR 10
+-The directory to be scanned is
+-.I dir .
+-.IP \-m
+-Send mail to the owner of each file being removed.
+-(Note that most files put into the spool directory
+-will be owned by the owner of the
+-uucp programs since the setuid bit will be set on these
+-programs.
+-The mail will therefore most often go to the owner
+-of the uucp programs.)
+-.IP \-n\fIhours\fR
+-Change the aging time from 72 hours to
+-.I hours
+-hours.
+-.IP \-p\fIpre\fR
+-Examine files with prefix
+-.I pre
+-for deletion.
+-(Up to 10 file prefixes may be specified.)
+-.IP \-x\fInum\fR
+-This is the level of debugging output desired.
+-.RE
+-.NH
+-Security
+-.LP
+-.LG
+-\fB
+-The uucp system, left unrestricted,
+-will let any outside user execute any commands
+-and copy in/out any file which is readable/writable
+-by the uucp login user.
+-It is up to the individual sites to be aware of this and
+-apply the protections that they feel are necessary.
+-\fR
+-.NL
+-.LP
+-There are several security features available aside from the
+-normal file mode protections.
+-These must be set up by the installer of the
+-.I uucp
+-system.
+-.IP - 3
+-The login for uucp does not get a standard shell.
+-Instead, the
+-.I uucico
+-program is started.
+-Therefore, the only work that can be done is through
+-.I uucico .
+-.IP -
+-A path check is done on file names that are to be sent
+-or received.
+-The
+-.I USERFILE
+-supplies the information for these checks.
+-The
+-.I USERFILE
+-can also be set up to require call-back
+-for certain login-ids.
+-(See the ``Files required for execution'' section
+-for the file description.)
+-.IP -
+-A conversation sequence count can be set up so
+-that the called system
+-can be more confident that the caller
+-is who he says he is.
+-.IP -
+-The
+-.I uuxqt
+-program comes with a list of commands that it
+-will execute.
+-A ``PATH'' shell statement is prepended to the command
+-line as specifed in the
+-.I uuxqt
+-program.
+-The installer may modify the list or remove the
+-restrictions as desired.
+-.IP -
+-The
+-.I L.sys
+-file should be owned by uucp and have mode 0400
+-to protect the phone numbers and login information
+-for remote sites.
+-(Programs uucp, uucico, uux, uuxqt should be also
+-owned by uucp and have the setuid bit set.)
+-.NH
+-Uucp Installation
+-.LP
+-There are several source modifications that may be required
+-before the system programs are compiled.
+-These relate to the directories used during compilation,
+-the directories used during execution,
+-and the local
+-.I
+-uucp system-name.
+-.R
+-.LP
+-The four directories are:
+-.RS
+-.IP lib 12
+-(/usr/src/cmd/uucp)
+-This directory contains the source files for generating the
+-.I uucp
+-system.
+-.IP program
+-(/usr/lib/uucp)
+-This is the directory used for the executable system programs and
+-the system files.
+-.IP spool
+-(/usr/spool/uucp)
+-This is the spool directory used during
+-.I uucp
+-execution.
+-.IP xqtdir
+-(/usr/spool/uucp/.XQTDIR)
+-This directory is used during execution of
+-.I "execute files" .
+-.RE
+-.LP
+-The names given in parentheses above are the default values
+-for the directories.
+-The italicized named
+-.I
+-lib, program, xqtdir,
+-.R
+-and
+-.I spool
+-will be used in the following text to represent the
+-appropriate directory names.
+-.LP
+-There are two files which may require modification,
+-the
+-.I makefile
+-file and the
+-.I uucp.h
+-file.
+-The following paragraphs describe the modifications.
+-The modes of
+-.I spool
+-and
+-.I xqtdir
+-should be made ``0777''.
+-.SH
+-Uucp.h modification
+-.LP
+-Change the
+-.I program
+-and the
+-.I spool
+-names from the default values to the directory
+-names to be used on the local system using
+-global edit commands.
+-.LP
+-Change the
+-.I define
+-value for
+-.I MYNAME
+-to be the local
+-.I uucp
+-system-name.
+-.SH
+-makefile modification
+-.LP
+-There are several
+-.I make
+-variable definitions which may need modification.
+-.RS
+-.IP INSDIR 10
+-This is the
+-.I program
+-directory
+-(e.g. INSDIR=/usr/lib/uucp).
+-This parameter is used if ``make cp'' is
+-used after the programs are compiled.
+-.IP IOCTL
+-This is required to be set if an appropriate
+-.I ioctl
+-interface subroutine does not exist in the standard
+-``C'' library;
+-the statement
+-``IOCTL=ioctl.o'' is required in this case.
+-.IP PKON
+-The statement ``PKON=pkon.o'' is required if the
+-packet driver is not in the kernel.
+-.RE
+-.SH
+-Compile the system
+-The command
+-.IP "" 12
+-make
+-.LP
+-will compile the entire system.
+-The command
+-.IP "" 12
+-make cp
+-.LP
+-will copy the commands to the
+-to the appropriate directories.
+-.LP
+-The programs
+-.I uucp ,
+-.I uux ,
+-and
+-.I uulog
+-should be put in ``/usr/bin''.
+-The programs
+-.I uuxqt ,
+-.I uucico ,
+-and
+-.I uuclean
+-should be put in the
+-.I program
+-directory.
+-.SH
+-Files required for execution
+-.LP
+-There are four files which are required for execution,
+-all of which should reside in the
+-.I program
+-directory.
+-The field separator for all files is a space unless otherwise
+-specified.
+-.SH
+-L-devices
+-.LP
+-This file contains entries for the call-unit devices and
+-hardwired connections which are to be used by
+-.I uucp.
+-The special device files are assumed to be in the
+-.I /dev
+-directory.
+-The format for each entry is
+-.IP "" 12
+-line\ \ call-unit\ \ speed
+-.LP
+-where;
+-.RS
+-.IP line 12
+-is the device for the line (e.g. cul0),
+-.IP call-unit
+-is the automatic call unit associated with
+-.I line
+-(e.g. cua0),
+-(Hardwired lines have a number ``0'' in this field.),
+-.IP speed
+-is the line speed.
+-.RE
+-.LP
+-The line
+-.IP "" 12
+-cul0\ \ cua0\ \ 300
+-.LP
+-would be set up for a system which
+-had device cul0 wired to a call-unit
+-cua0 for use at 300 baud.
+-.SH
+-L-dialcodes
+-.LP
+-This file contains entries with location abbreviations used
+-in the
+-.I L.sys
+-file (e.g. py, mh, boston).
+-The entry format is
+-.IP "" 12
+-abb\ \ dial-seq
+-.LP
+-where;
+-.RS
+-.IP abb 12
+-is the abbreviation,
+-.IP dial-seq
+-is the dial sequence to call that location.
+-.RE
+-.LP
+-The line
+-.IP "" 12
+-py\ \ 165\-
+-.LP
+-would be set up so that entry py7777 would
+-send 165\-7777 to the dial-unit.
+-.SH
+-LOGIN/SYSTEM NAMES
+-.LP
+-It is assumed that the
+-.I "login name"
+-used by a remote computer to call into a local computer
+-is not the same as the login name of a normal user
+-of that local machine.
+-However, several remote computers may employ the same
+-login name.
+-.LP
+-Each computer is given a unique
+-.I "system name"
+-which is transmitted at the start of each call.
+-This name identifies the calling machine to the called machine.
+-.SH
+-USERFILE
+-.LP
+-This file contains user accessibility information.
+-It specifies four types of constraint;
+-.RS
+-.IP [1]
+-which files can be accessed by a normal user of the local machine,
+-.IP [2]
+-which files can be accessed from a remote computer,
+-.IP [3]
+-which login name is used by a particular remote computer,
+-.IP [4]
+-whether a remote computer should be called back in order to confirm
+-its identity.
+-.RE
+-.LP
+-Each line in the file has the following format
+-.IP "" 6
+-login,sys\ \ 
+-.B [
+-c
+-.B ]
+-\ \ path-name\ \ 
+-.B [
+-path-name
+-.B ]
+-\ ...
+-.LP
+-where;
+-.RS
+-.IP login 12
+-is the login name for a user or the remote computer,
+-.IP  sys
+-is the system name for a remote computer,
+-.IP c
+-is the optional
+-.I
+-call-back required
+-.R
+-flag,
+-.IP path-name
+-is a path-name prefix that is acceptable for
+-.I user.
+-.LP
+-.RE
+-.LP
+-The constraints are implemented as follows.
+-.RS
+-.IP [1]
+-When the program is obeying a command stored on the local machine,
+-.I MASTER
+-mode,
+-the path-names allowed are those given for the first line in the
+-.I USERFILE
+-that has a login name that matches the login name of the user
+-who entered the command.
+-If no such line is found, the first line with a
+-.I null
+-login name is used.
+-.IP [2]
+-When the program is responding to a command from a remote machine,
+-.I SLAVE
+-mode, the path-names allowed are those given for the first line
+-in the file that has the system name that matches the system name
+-of the remote machine.
+-If no such line is found, the first one with a
+-.I null
+-system name is used.
+-.IP [3]
+-When a remote computer logs in, the login name that
+-it uses must appear in the
+-.I USERFILE .
+-There may be several lines with the same login name but one of them must
+-either have the name of the remote system or must contain a
+-.I null
+-system name.
+-.IP [4]
+-If the line matched in ([3]) contains a ``c'',
+-the remote machine is called back before any transactions take place.
+-.RE
+-.LP
+-The line
+-.IP "" 12
+-u,m  /usr/xyz
+-.LP
+-allows machine
+-.I m
+-to login with name
+-.I u
+-and request the transfer of files whose names start with
+-``/usr/xyz''.
+-.LP
+-The line
+-.IP "" 12
+-dan,  /usr/dan
+-.LP
+-allows the ordinary user
+-.I dan
+-to issue commands for files whose name starts with
+-``/usr/dan''.
+-.LP
+-The lines
+-.IP "" 12
+-u,m /usr/xyz  /usr/spool
+-.br
+-u,  /usr/spool
+-.LP
+-allows any remote machine to login with name
+-.I u ,
+-but if its system name is not
+-.I m ,
+-it can only ask to transfer files whose names start with
+-``/usr/spool''.
+-.LP
+-The lines
+-.IP "" 12
+-root,  /
+-.br
+-,   /usr
+-.LP
+-allows any user to transfer files beginning with ``/usr''
+-but the user with login
+-.I root
+-can transfer any file.
+-.SH
+-L.sys
+-.LP
+-Each entry in this file represents one system
+-which can be called by the local uucp programs.
+-The fields are described below.
+-.RS
+-.SH
+-system name
+-.LP
+-The name of the remote system.
+-.SH
+-time
+-.LP
+-This is a string which indicates the days-of-week
+-and times-of-day when the system should
+-be called
+-(e.g. MoTuTh0800\-1730).
+-.LP
+-The day portion may be a list containing
+-some of
+-.IP
+-.I
+-Su Mo Tu We Th Fr Sa
+-.R
+-.LP
+-or it may be
+-.I Wk
+-for any week-day or
+-.I Any
+-for any day.
+-.LP
+-The time should be a range of times (e.g. 0800\-1230).
+-If no time portion is specified, any time
+-of day is assumed to be ok for the call.
+-.SH
+-device
+-.LP
+-This is either
+-.I ACU
+-or the hardwired device to be used for the call.
+-For the hardwired case, the last part of the
+-special file name is used (e.g. tty0).
+-.SH
+-speed
+-.LP
+-This is the line speed for the call (e.g. 300).
+-.SH
+-phone
+-.LP
+-The phone number is made up of an optional
+-alphabetic abbreviation and a numeric part.
+-The abbreviation is one which appears in the
+-.I L-dialcodes
+-file (e.g. mh5900, boston995\-9980).
+-.LP
+-For the hardwired devices, this field contains
+-the same string as used for the
+-.I device
+-field.
+-.SH
+-login
+-.LP
+-The login information is given as a series of
+-fields and subfields in the format
+-.IP
+-expect\ \ send\ 
+-.B [
+-expect\ \ send
+-.B ]
+-\ ...
+-.LP
+-where;
+-.I expect
+-is the string expected to be read and
+-.I send
+-is the string to be sent when the
+-.I expect
+-string is received.
+-.LP
+-The expect field may be made up of subfields
+-of the form
+-.IP
+-expect\fB[\fR\-send\-expect\fB]\fR...
+-.LP
+-where the
+-.I send
+-is sent if the prior
+-.I expect
+-is not successfully read
+-and the
+-.I expect
+-following the
+-.I send
+-is the next expected string.
+-.LP
+-There are two special names available to be sent
+-during the login sequence.
+-The string
+-.I EOT
+-will send an EOT character and the string
+-.I BREAK
+-will try to send a BREAK character.
+-(The
+-.I BREAK
+-character is simulated using line speed changes
+-and null characters and may not work on all
+-devices and/or systems.)
+-.RE
+-.LP
+-A typical entry in the L.sys file would be
+-.IP "" 6
+-sys Any ACU 300  mh7654 login uucp ssword: word
+-.LP
+-The expect algorithm looks at the last part of the
+-string as illustrated in the password field.
+-.RE
+-.NH
+-Administration
+-.LP
+-This section indicates some events and files which must be
+-administered for the
+-.I uucp
+-system.
+-Some administration can be accomplished by 
+-.I "shell files"
+-which can be initiated by
+-.I crontab
+-entries.
+-Others will require manual intervention.
+-Some sample 
+-.I "shell files"
+-are given toward the end of this section.
+-.SH
+-SQFILE \- sequence check file
+-.LP
+-This file is set up in the
+-.I program
+-directory and contains an entry for each remote
+-system with which you agree to perform conversation
+-sequence checks.
+-The initial entry is just the system name of
+-the remote system.
+-The first conversation will add two items to the line,
+-the conversation count, and the date/time of the most
+-resent conversation.
+-These items will be updated with each conversation.
+-If a sequence check fails, the entry will have to
+-be adjusted.
+-.SH
+-TM \- temporary data files
+-.LP
+-These files are created in the
+-.I spool
+-directory while files are being copied
+-from a remote machine.
+-Their names have the form
+-.IP "" 12
+-\fBTM\fR.pid.ddd
+-.LP
+-where
+-.I pid
+-is a process-id and
+-.I ddd
+-is a sequential three digit number starting at zero
+-for each invocation of
+-.I uucico
+-and incremented for each file received.
+-
+-After the entire remote file is received, the
+-.I TM
+-file is moved/copied to the requested destination.
+-If processing is abnormally terminated or the
+-move/copy fails, the file will remain in the
+-spool directory.
+-.LP
+-The leftover files should be periodically removed;
+-the
+-.I uuclean
+-program is useful in this regard.
+-The command
+-.IP "" 12
+-uuclean\ \ \-pTM
+-.LP
+-will remove all
+-.I TM
+-files older than three days.
+-.SH
+-LOG \- log entry files
+-.LP
+-During execution of programs, individual
+-.I LOG
+-files are created in the
+-.I spool
+-directory with information about
+-queued requests, calls to remote systems,
+-execution of
+-.I uux
+-commands and file copy results.
+-These files should be combined into the
+-.I LOGFILE
+-by using the
+-.I uulog
+-program.
+-This program will put the new
+-.I LOG
+-files at the beginning of the existing
+-.I LOGFILE.
+-The command
+-.IP "" 12
+-uulog
+-.LP
+-will accomplish the merge.
+-Options are available to print some or all the
+-log entries after the files are merged.
+-The
+-.I LOGFILE
+-should be removed periodically
+-since it is copied each time new LOG
+-entries are put into the file.
+-.LP
+-The
+-.I LOG
+-files are created initially with mode 0222.
+-If the program which creates the file terminates normally,
+-it changes the
+-mode to 0666.
+-Aborted runs may leave the files with mode
+-0222 and the
+-.I uulog
+-program will not read or remove them.
+-To remove them, either use
+-.I rm ,
+-.I uuclean ,
+-or change the mode to 0666 and let
+-.I uulog
+-merge them with the
+-.I LOGFILE .
+-.SH
+-STST \- system status files
+-.LP
+-These files are created in the spool directory by the
+-.I uucico
+-program.
+-They contain information of failures such as login, dialup or
+-sequence check and will contain a
+-.I TALKING
+-status when to machines are conversing.
+-The form of the file name is
+-.IP
+-\fBSTST\fR.sys
+-.LP
+-where
+-.I sys
+-is the remote system name.
+-.LP
+-For ordinary failures (dialup, login), the file will prevent
+-repeated tries for about one hour.
+-For sequence check failures, the file must be removed before
+-any future attempts to converse with that remote system.
+-.LP
+-If the file is left due to an aborted run, it may contain a
+-.I TALKING
+-status.
+-In this case, the file must be removed before a conversation
+-is attempted.
+-.SH
+-LCK \- lock files
+-.LP
+-Lock files are created for each device in use (e.g. automatic calling
+-unit) and each system conversing.
+-This prevents duplicate conversations and multiple attempts to use the
+-same devices.
+-The form of the lock file name is
+-.IP "" 12
+-\fBLCK..\fRstr
+-.LP
+-where
+-.I str
+-is either a device or system name.
+-The files may be left in the spool directory if runs abort.
+-They will be ignored (reused) after a time of about 24 hours.
+-When runs abort and calls are desired before the time limit,
+-the lock files should be removed.
+-.SH
+-Shell Files
+-.LP
+-The
+-.I uucp
+-program will spool work and attempt to start the
+-.I uucico
+-program, but the starting of
+-.I uucico
+-will sometimes fail.
+-(No devices available, login failures etc.).
+-Therefore, the
+-.I uucico
+-program should be periodically started.
+-The command to start
+-.I uucico
+-can be put in a ``shell'' file with a command to merge
+-.I LOG
+-files and started by a crontab entry on an hourly basis.
+-The file could contain the commands
+-.IP
+-.I program /uulog
+-.br
+-.I program /uucico
+-\ \ \-r1
+-.LP
+-Note that the ``\-r1'' option is required to start the
+-.I uucico
+-program in
+-.I MASTER
+-mode.
+-.LP
+-Another shell file may be set up on a daily basis to remove
+-.I TM ,
+-.I ST
+-and
+-.I LCK
+-files
+-and
+-.I C.
+-or
+-.I D.
+-files for work which can not be accomplished for
+-reasons like bad phone number, login changes etc.
+-A shell file containing commands like
+-.IP
+-.I program /uuclean
+-\ \ \-pTM \-pC. \-pD.
+-.br
+-.I program /uuclean
+-\ \ \-pST \-pLCK \-n12
+-.LP
+-can be used.
+-Note the ``\-n12'' option causes the
+-.I ST
+-and
+-.I LCK
+-files older than 12 hours to be deleted.
+-The absence of the ``\-n'' option will use a three day time
+-limit.
+-.LP
+-A daily or weekly shell should also be created
+-to remove or save old
+-.I LOGFILE s.
+-A shell like
+-.IP
+-cp
+-.I spool /LOGFILE
+-\ \ 
+-.I spool /o.LOGFILE
+-.br
+-rm
+-.I spool /LOGFILE
+-.LP
+-can be used.
+-.SH
+-Login Entry
+-.LP
+-One or more logins should be set up for
+-.I uucp .
+-Each of the ``/etc/passwd'' entries should
+-have the
+-``\fIprogram\fR/uucico''
+-as the shell to be executed.
+-The login directory is not used, but if the system
+-has a special directory for use by the users for
+-sending or receiving file, it should as the
+-login entry.
+-The various logins are used in conjunction with the
+-.I USERFILE
+-to restrict file access.
+-Specifying the
+-.I shell
+-argument limits the login to the use of uucp
+-(
+-.I uucico )
+-only.
+-.SH
+-File Modes
+-.LP
+-It is suggested that the owner and file modes of various
+-programs and files be set as follows.
+-.LP
+-The programs
+-.I uucp ,
+-.I uux ,
+-.I uucico
+-and
+-.I uuxqt
+-should be owned by the
+-.I uucp
+-login with the ``setuid'' bit set and only execute
+-permissions (e.g. mode 04111).
+-This will prevent outsiders from modifying the programs
+-to get at a standard
+-.I shell
+-for the
+-.I uucp
+-logins.
+-.LP
+-The
+-.I L.sys ,
+-.I SQFILE
+-and the
+-.I USERFILE
+-which are put in the
+-.I program
+-directory should be owned by
+-the
+-.I uucp
+-login and set with mode 0400.
+-.SG MH-1273-DAN-unix
+//GO.SYSIN DD implement
+echo network
+sed 's/.//' >network <<'//GO.SYSIN DD network'
+-.RP
+-.if n .ls 2
+-.ds RH Nowitz
+-.ND "August 18, 1978"
+-.TL
+-A Dial-Up Network of
+-UNIX\s6\uTM\d\s0
+-Systems
+-.AU
+-D. A. Nowitz
+-.AU
+-M. E. Lesk
+-.AI
+-.MH
+-.AB
+-.if n .ls 2
+-A network of over eighty
+-.UX
+-computer systems has been established using the
+-telephone system as its primary communication medium.
+-The network was designed to meet the growing demands for
+-software distribution and exchange.
+-Some advantages of our design are:
+-.IP -
+-The startup cost is low.
+-A system needs only a dial-up port,
+-but systems with automatic calling units have much more
+-flexibility.
+-.IP -
+-No operating system changes are required to install or use the system.
+-.IP -
+-The communication is basically over dial-up lines,
+-however, hardwired communication lines can be used
+-to increase speed.
+-.IP -
+-The command for sending/receiving files is simple to use.
+-.sp
+-Keywords: networks, communications, software distribution, software maintenance
+-.AE
+-.NH 
+-Purpose
+-.PP
+-The widespread use of the
+-.UX
+-system
+-.[
+-ritchie thompson bstj 1978
+-.]
+-within Bell Laboratories
+-has produced problems of software distribution and maintenance.
+-A conventional mechanism was set up to distribute the operating
+-system and associated programs from a central site to the
+-various users.
+-However this mechanism alone does not meet all software
+-distribution needs.
+-Remote sites generate much software and must transmit it to
+-other sites.
+-Some
+-.UX
+-systems
+-are themselves central sites for redistribution
+-of a particular specialized utility,
+-such as the Switching Control Center System.
+-Other sites have particular, often long-distance needs for
+-software exchange; switching research,
+-for example, is carried on in
+-New Jersey, Illinois, Ohio, and Colorado.
+-In addition, general purpose utility programs are written at
+-all
+-.UX
+-system sites.
+-The
+-.UX
+-system is modified
+-and enhanced by many people in many places and
+-it would be very constricting to deliver new software in a one-way
+-stream without any alternative
+-for the user sites to respond with changes of their own.
+-.PP
+-Straightforward software distribution is only part of the problem.
+-A large project may exceed the capacity of a single computer and
+-several machines may be used by the one group of people.
+-It then becomes necessary
+-for them to pass messages, data and other information back an forth
+-between computers.
+-.PP
+-Several groups with similar problems, both inside and outside of
+-Bell Laboratories, have constructed networks built of
+-hardwired connections only.
+-.[
+-dolotta mashey 1978 bstj
+-.]
+-.[
+-network unix system chesson
+-.]
+-Our network, however, uses both dial-up and hardwired
+-connections so that service can be provided to as many sites as possible.
+-.NH
+-Design Goals
+-.PP
+-Although some of our machines are connected directly, others
+-can only communicate over low-speed dial-up lines.
+-Since the dial-up lines are often unavailable
+-and file transfers may take considerable time,
+-we spool all work and transmit in the background.
+-We also had to adapt to a community of systems which are independently
+-operated and resistant to suggestions that they should all
+-buy particular hardware or install particular operating system
+-modifications.
+-Therefore, we make minimal demands on the local sites
+-in the network.
+-Our implementation requires no operating system changes;
+-in fact, the transfer programs look like any other user
+-entering the system through the normal dial-up login ports,
+-and obeying all local protection rules.
+-.PP
+-We distinguish ``active'' and ``passive'' systems
+-on the network.
+-Active systems have an automatic calling unit
+-or a hardwired line to another system,
+-and can initiate a connection.
+-Passive systems do not have the hardware
+-to initiate a connection.
+-However, an
+-active system can be assigned the job of calling passive
+-systems and executing work found there;
+-this makes a passive system the functional equivalent of
+-an active system, except for an additional delay while it waits to be polled.
+-Also, people frequently log into active systems and
+-request copying from one passive system to another.
+-This requires two telephone calls, but even so, it is faster
+-than mailing tapes.
+-.PP
+-Where convenient, we use hardwired communication lines.
+-These permit much faster transmission and multiplexing
+-of
+-the communications link.
+-Dial-up connections are made at either 300 or 1200 baud;
+-hardwired connections are asynchronous up to 9600 baud 
+-and might run even faster on special-purpose communications
+-hardware.
+-.[
+-fraser spider 1974 ieee
+-.]
+-.[
+-fraser channel network datamation 1975
+-.]
+-Thus, systems typically join our network first as
+-passive systems and when
+-they find the service more important, they acquire
+-automatic calling units and become active
+-systems; eventually, they may install high-speed
+-links to particular machines with which they
+-handle a great deal of traffic.
+-At no point, however, must users change their
+-programs or procedures.
+-.PP
+-The basic operation of the network is very simple.
+-Each participating system has a spool directory,
+-in which work to be done (files to be moved, or commands to be executed
+-remotely) is stored.
+-A standard program,
+-.I uucico ,
+-performs all transfers.
+-This program starts by identifying a particular communication channel
+-to a remote system with which it will hold a conversation.
+-.I Uucico
+-then selects a device and establishes the connection,
+-logs onto the remote machine
+-and starts the
+-.I uucico
+-program on the remote machine.
+-Once two of these programs are connected, they first agree on a line protocol,
+-and then start exchanging work.
+-Each program in turn, beginning with the calling (active system) program,
+-transmits everything it needs, and then asks the other what it wants done.
+-Eventually neither has any more work, and both exit.
+-.PP
+-In this way, all services are available from all sites; passive sites,
+-however, must wait until called.
+-A variety of protocols may be used; this conforms to the real,
+-non-standard world.
+-As long as the caller and called programs have a protocol in common,
+-they can communicate.
+-Furthermore, each caller knows the hours when each destination system
+-should be called.
+-If a destination is unavailable, the data intended for it
+-remain in the spool directory until the destination machine can be reached.
+-.PP
+-The implementation of this
+-Bell Laboratories network
+-between independent sites, all of which
+-store proprietary programs and data,
+-illustratives the pervasive need for security
+-and administrative controls over file access.
+-Each site, in configuring its programs and system files,
+-limits and monitors transmission.
+-In order to access a file a user needs access permission
+-for the machine that contains the file and access permission
+-for the file itself.
+-This is achieved by first requiring the user to use his password
+-to log into his local machine and then his local
+-machine logs into the remote machine whose files are to be accessed.
+-In addition, records are kept identifying all files
+-that are moved into and out of the local system,
+-and how the requestor of such accesses identified
+-himself.
+-Some sites may arrange
+-to permit users only
+-to call up
+-and request work to be done;
+-the calling users are then called back
+-before the work is actually done.
+-It is then possible to verify
+-that the request is legitimate from the standpoint of the
+-target system, as well as the originating system.
+-Furthermore, because of the call-back,
+-no site can masquerade as another
+-even if it knows all the necessary passwords.
+-.PP
+-Each machine can optionally maintain a sequence count for
+-conversations with other machines and require a verification of the
+-count at the start of each conversation.
+-Thus, even if call back is not in use, a successful masquerade requires
+-the calling party to present the correct sequence number.
+-A would-be impersonator must not just steal the correct phone number,
+-user name, and password, but also the sequence count, and must call in
+-sufficiently promptly to precede the next legitimate request from either side.
+-Even a successful masquerade will be detected on the next correct
+-conversation.
+-.NH
+-Processing
+-.PP
+-The user has two commands which set up communications,
+-.I uucp
+-to set up file copying,
+-and
+-.I uux
+-to set up command execution where some of the required
+-resources (system and/or files)
+-are not on the local machine.
+-Each of these commands will put work and data files
+-into the spool directory for execution by
+-.I uucp
+-daemons.
+-Figure 1 shows the major blocks of the file transfer process.
+-.SH
+-File Copy
+-.PP
+-The
+-.I uucico
+-program is used to perform all communications between
+-the two systems.
+-It performs the following functions:
+-.RS
+-.IP - 3
+-Scan the spool directory for work.
+-.IP -
+-Place a call to a remote system.
+-.IP -\ \ 
+-Negotiate a line protocol to be used.
+-.IP -\ \ 
+-Start program
+-.I uucico
+-on the remote system.
+-.IP -\ \ 
+-Execute all requests from both systems.
+-.IP -\ \ 
+-Log work requests and work completions.
+-.RE
+-.LP
+-.I Uucico
+-may be started in several ways;
+-.RS
+-.IP a) 5
+-by a system daemon,
+-.IP b)
+-by one of the
+-.I uucp
+-or
+-.I uux
+-programs,
+-.IP c)
+-by a remote system.
+-.RE
+-.SH
+-Scan For Work
+-.PP
+-The file names in the spool directory are constructed to allow the
+-daemon programs
+-.I "(uucico, uuxqt)"
+-to determine the files they should look at,
+-the remote machines they should call
+-and the order in which the files for a particular
+-remote machine should be processed.
+-.SH
+-Call Remote System
+-.PP
+-The call is made using information from several
+-files which reside in the uucp program directory.
+-At the start of the call process, a lock is
+-set on the system being called so that another
+-call will not be attempted at the same time.
+-.PP
+-The system name is found in a
+-``systems''
+-file.
+-The information contained for each system is:
+-.IP
+-.RS
+-.IP [1]
+-system name,
+-.IP [2]
+-times to call the system
+-(days-of-week and times-of-day),
+-.IP [3]
+-device or device type to be used for call,
+-.IP [4]
+-line speed,
+-.IP [5]
+-phone number,
+-.IP [6]
+-login information (multiple fields).
+-.RE
+-.PP
+-The time field is checked against the present time to see
+-if the call should be made.
+-The
+-.I
+-phone number
+-.R
+-may contain abbreviations (e.g. ``nyc'', ``boston'') which get translated into dial
+-sequences using a
+-``dial-codes'' file.
+-This permits the same ``phone number'' to be stored at every site, despite
+-local variations in telephone services and dialing conventions.
+-.PP
+-A ``devices''
+-file is scanned using fields [3] and [4] from the
+-``systems''
+-file to find an available device for the connection.
+-The program will try all devices which satisfy
+-[3] and [4] until a connection is made, or no more
+-devices can be tried.
+-If a non-multiplexable device is successfully opened, a lock file
+-is created so that another copy of
+-.I uucico
+-will not try to use it.
+-If the connection is complete, the
+-.I
+-login information
+-.R
+-is used to log into the remote system.
+-Then
+-a command is sent to the remote system
+-to start the
+-.I uucico
+-program.
+-The conversation between the two
+-.I uucico
+-programs begins with a handshake started by the called,
+-.I SLAVE ,
+-system.
+-The
+-.I SLAVE
+-sends a message to let the
+-.I MASTER
+-know it is ready to receive the system
+-identification and conversation sequence number.
+-The response from the
+-.I MASTER
+-is
+-verified by the
+-.I SLAVE
+-and if acceptable, protocol selection begins.
+-.SH
+-Line Protocol Selection
+-.PP
+-The remote system sends a message
+-.IP "" 12
+-P\fIproto-list\fR
+-.LP
+-where
+-.I proto-list
+-is a string of characters, each
+-representing a line protocol.
+-The calling program checks the proto-list
+-for a letter corresponding to an available line
+-protocol and returns a
+-.I use-protocol
+-message.
+-The
+-.I use-protocol
+-message is
+-.IP "" 12
+-U\fIcode\fR
+-.LP
+-where code is either a one character
+-protocol letter or a
+-.I N
+-which means there is no common protocol.
+-.PP
+-Greg Chesson designed and implemented the standard
+-line protocol used by the uucp transmission program.
+-Other protocols may be added by individual installations.
+-.SH
+-Work Processing
+-.PP
+-During processing, one program is the
+-.I MASTER
+-and the other is
+-.I SLAVE .
+-Initially, the calling program is the
+-.I MASTER.
+-These roles may switch one or more times during
+-the conversation.
+-.PP
+-There are four messages used during the
+-work processing, each specified by the first
+-character of the message.
+-They are
+-.KS
+-.TS
+-center;
+-c l.
+-S     send a file,
+-R     receive a file,
+-C     copy complete,
+-H     hangup.
+-.TE
+-.KE
+-.LP
+-The
+-.I MASTER
+-will send
+-.I R
+-or
+-.I S
+-messages until all work from the spool directory is
+-complete, at which point an
+-.I H
+-message will be sent.
+-The
+-.I SLAVE
+-will reply with
+-\fISY\fR, \fISN\fR, \fIRY\fR, \fIRN\fR, \fIHY\fR, \fIHN\fR,
+-corresponding to
+-.I yes
+-or
+-.I no
+-for each request.
+-.PP
+-The send and receive replies are
+-based on permission to access the
+-requested file/directory.
+-After each file is copied into the spool directory
+-of the receiving system,
+-a copy-complete message is sent by the receiver of the file.
+-The message
+-.I CY
+-will be sent if the
+-.UX
+-.I cp
+-command, used to copy from the spool directory, is successful.
+-Otherwise, a
+-.I CN
+-message is sent.
+-The requests and results are logged on both systems,
+-and, if requested, mail is sent to the user reporting completion
+-(or the user can request status information from the log program at any time).
+-.PP
+-The hangup response is determined by the
+-.I SLAVE
+-program by a work scan of the spool directory.
+-If work for the remote system exists in the
+-.I SLAVE's
+-spool directory, a
+-.I HN
+-message is sent and the programs switch roles.
+-If no work exists, an
+-.I HY
+-response is sent.
+-.PP
+-A sample conversation is shown in Figure 2.
+-.SH
+-Conversation Termination
+-.PP
+-When a
+-.I HY
+-message is received by the
+-.I MASTER
+-it is echoed back to the
+-.I SLAVE
+-and the protocols are turned off.
+-Each program sends a final "OO" message to the
+-other.
+-.NH
+-Present Uses
+-.PP
+-One application of this software is remote mail.
+-Normally, a
+-.UX
+-system user
+-writes ``mail dan'' to send mail to
+-user ``dan''.
+-By writing ``mail usg!dan''
+-the mail is sent to user 
+-``dan''
+-on system ``usg''.
+-.PP
+-The primary uses of our network to date have been in software maintenance.
+-Relatively few of the bytes passed between systems are intended for
+-people to read.
+-Instead, new programs (or new versions of programs)
+-are sent to users, and potential bugs are returned to authors.
+-Aaron Cohen has implemented a
+-``stockroom'' which allows remote users to call in and request software.
+-He keeps a ``stock list'' of available programs, and new bug
+-fixes and utilities are added regularly.
+-In this way, users can always obtain the latest version of anything
+-without bothering the authors of the programs.
+-Although the stock list is maintained on a particular system,
+-the items in the stockroom may be warehoused in many places;
+-typically each program is distributed from the home site of
+-its author.
+-Where necessary, uucp does remote-to-remote copies.
+-.PP
+-We also routinely retrieve test cases from other systems
+-to determine whether errors on remote systems are caused
+-by local misconfigurations or old versions of software,
+-or whether they are bugs that must be fixed at the home site.
+-This helps identify errors rapidly.
+-For one set of test programs maintained by us,
+-over 70% of the bugs reported from remote sites
+-were due to old software, and were fixed
+-merely by distributing the current version.
+-.PP
+-Another application of the network for software maintenance
+-is to compare files on two different machines.
+-A very useful utility on one machine has been
+-Doug McIlroy's ``diff'' program
+-which compares two text files and indicates the differences,
+-line by line, between them.
+-.[
+-hunt mcilroy file
+-.]
+-Only lines which are
+-not identical are printed.
+-Similarly,
+-the program ``uudiff''
+-compares files (or directories) on two machines.
+-One of these directories may be on a passive system.
+-The
+-``uudiff'' program
+-is set up to work similarly to the inter-system mail, but it is slightly
+-more complicated.
+-.PP
+-To avoid moving large numbers of usually identical
+-files,  
+-.I uudiff
+-computes file checksums
+-on each side, and only moves files that are different
+-for detailed comparison.
+-For large files, this process can be iterated; checksums can be computed
+-for each line, and only those lines that are different
+-actually moved.
+-.PP
+-The ``uux'' command has
+-been useful for providing remote output.
+-There are some machines which do not have hard-copy
+-devices, but which are connected over 9600 baud
+-communication lines to machines with printers.
+-The
+-.I uux
+-command allows the formatting of the
+-printout on the local machine and printing on the
+-remote machine using standard
+-.UX
+-command programs.
+-.br
+-.NH
+-Performance
+-.PP
+-Throughput, of course, is primarily dependent on transmission speed.
+-The table below shows the real throughput of characters
+-on communication links of different speeds.
+-These numbers represent actual data transferred;
+-they do not include bytes used by the line protocol for
+-data validation such as checksums and messages.
+-At the higher speeds, contention for the processors on both
+-ends prevents the network from driving the line full speed.
+-The range of speeds represents the difference between light and
+-heavy loads on the two systems.
+-If desired, operating system modifications can
+-be installed
+-that permit full use of even very fast links.
+-.KS
+-.TS
+-center;
+-c c
+-n n.
+-Nominal speed Characters/sec.
+-300 baud      27
+-1200 baud     100-110
+-9600 baud     200-850
+-.TE
+-.KE
+-In addition to the transfer time, there is some overhead
+-for making the connection and logging in ranging from
+-15 seconds to 1 minute.
+-Even at 300 baud, however, a typical 5,000 byte source program
+-can be transferred in
+-four minutes instead of the 2 days that might be required
+-to mail a tape.
+-.PP
+-Traffic between systems is variable.  Between two
+-closely related systems,
+-we observed
+-20 files moved and 5 remote commands executed in a typical day.
+-A more normal traffic out of a single system would be around
+-a dozen files per day.
+-.PP
+-The total number of sites at present
+-in the main network is
+-82, which includes most of the Bell Laboratories
+-full-size machines
+-which run the
+-.UX
+-operating system.
+-Geographically, the machines range from Andover, Massachusetts to
+-Denver, Colorado.
+-.PP
+-Uucp has also
+-been used to set up another network
+-which connects a group of
+-systems in operational sites with the home site.
+-The two networks touch at one
+-Bell Labs computer.
+-.NH
+-Further Goals
+-.PP
+-Eventually, we would like to develop a full system of remote software
+-maintenance.
+-Conventional maintenance (a support group which mails tapes)
+-has many well-known disadvantages.
+-.[
+-brooks mythical man month 1975
+-.]
+-There are distribution errors and delays, resulting in old software
+-running at remote sites and old bugs continually reappearing.
+-These difficulties are aggravated when
+-there are 100 different small systems, instead of a few large ones.
+-.PP
+-The availability of file transfer on a network of compatible operating
+-systems
+-makes it possible just to send programs directly to the end user who wants them.
+-This avoids the bottleneck of negotiation and packaging in the central support
+-group.
+-The ``stockroom'' serves this function for new utilities
+-and fixes to old utilities.
+-However, it is still likely that distributions will not be sent
+-and installed as often as needed.
+-Users are justifiably suspicious of the ``latest version'' that has just
+-arrived; all too often it features the ``latest bug.''
+-What is needed is to address both problems simultaneously:
+-.IP 1.
+-Send distributions whenever programs change.
+-.IP 2.
+-Have sufficient quality control so that users will install them.
+-.LP
+-To do this, we recommend systematic regression testing both on the
+-distributing and receiving systems.
+-Acceptance testing on the receiving systems can be automated and
+-permits the local system to ensure that its essential work can continue
+-despite the constant installation of changes sent from elsewhere.
+-The work of writing the test sequences should be recovered in lower
+-counseling and distribution costs.
+-.PP
+-Some slow-speed network services are also being implemented.
+-We now have inter-system ``mail'' and ``diff,''
+-plus the many implied commands represented by ``uux.''
+-However, we still need inter-system ``write'' (real-time inter-user
+-communication) and ``who'' (list of people logged in
+-on different systems).
+-A slow-speed network of this sort may be very useful
+-for speeding up counseling and education, even
+-if not fast enough for the distributed data base
+-applications that attract many users to networks.
+-Effective use of remote execution over slow-speed lines, however,
+-must await the general installation of multiplexable channels so
+-that long file transfers do not lock out short inquiries.
+-.NH
+-Lessons
+-.PP
+-The following is a summary of the lessons we learned in
+-building these programs.
+-.IP 1.
+-By starting your network in a way that requires no hardware or major operating system
+-changes, you can get going quickly.
+-.IP 2.
+-Support will follow use.
+-Since the network existed and was being used, system maintainers
+-were easily persuaded to help keep it operating, including purchasing
+-additional hardware to speed traffic.
+-.IP 3.
+-Make the network commands look like local commands.
+-Our users have a resistance to learning anything new:
+-all the inter-system commands look very similar to
+-standard
+-.UX
+-system
+-commands so that little training cost
+-is involved.
+-.IP 4.
+-An initial error was not coordinating enough
+-with existing communications projects: thus, the first
+-version of this network was restricted to dial-up, since
+-it did not support the various hardware links between systems.
+-This has been fixed in the current system.
+-.SH
+-Acknowledgements
+-.PP
+-We thank G. L. Chesson for his design and implementation
+-of the packet driver and protocol, and A. S. Cohen, J. Lions,
+-and P. F. Long for their suggestions and assistance.
+-.[
+-$LIST$
+-.]
+//GO.SYSIN DD network
diff --git a/doc/7thEdMan/vol2/yacc.bun b/doc/7thEdMan/vol2/yacc.bun
new file mode 100644 (file)
index 0000000..8f1a6c0
--- /dev/null
@@ -0,0 +1,2614 @@
+# To unbundle, run this file
+echo ss..
+sed 's/.//' >ss.. <<'//GO.SYSIN DD ss..'
+-.RP
+-.ND "July 31, 1978"
+-.TL
+-Yacc:
+-Yet Another Compiler-Compiler
+-.AU "MH 2C-559" 3968
+-Stephen C. Johnson
+-.AI
+-.MH
+-.AB
+-.PP
+-Computer program input generally has some structure;
+-in fact, every computer program that does input can be thought of as defining
+-an ``input language'' which it accepts.
+-An input language may be as complex as a programming language, or as simple as
+-a sequence of numbers.
+-Unfortunately, usual input facilities
+-are limited, difficult to use,
+-and often are lax about checking their inputs for validity.
+-.PP
+-Yacc provides a general tool for describing
+-the input to a computer program.
+-The Yacc user specifies the structures
+-of his input, together with code to be invoked as
+-each such structure is recognized.
+-Yacc turns such a specification into a subroutine that
+-handles the input process;
+-frequently, it is convenient and appropriate to have most
+-of the flow of control in the user's application
+-handled by this subroutine.
+-.PP
+-The input subroutine produced by Yacc calls a user-supplied routine to
+-return the next basic input item.
+-Thus, the user can specify his input in terms of individual input characters, or
+-in terms of higher level constructs such as names and numbers.
+-The user-supplied routine may also handle idiomatic features such as
+-comment and continuation conventions, which typically defy easy grammatical specification.
+-.PP
+-Yacc is written in portable C.
+-The class of specifications accepted is a very general one: LALR(1)
+-grammars with disambiguating rules.
+-.PP
+-In addition to compilers for C, APL, Pascal, RATFOR, etc., Yacc
+-has also been used for less conventional languages,
+-including a phototypesetter language, several desk calculator languages, a document retrieval system,
+-and a Fortran debugging system.
+-.AE
+-.OK
+-Computer Languages
+-Compilers
+-Formal Language Theory
+-.CS 23 11 34 0 0 8
+//GO.SYSIN DD ss..
+echo ss0
+sed 's/.//' >ss0 <<'//GO.SYSIN DD ss0'
+-.SH
+-0: Introduction
+-.PP
+-Yacc provides a general tool for imposing structure on the input to a computer program.
+-The Yacc user prepares a
+-specification of the input process; this includes rules
+-describing the input structure, code to be invoked when these
+-rules are recognized, and a low-level routine to do the
+-basic input.
+-Yacc then generates a function to control the input process.
+-This function, called a
+-.I parser ,
+-calls the user-supplied low-level input routine
+-(the
+-.I "lexical analyzer" )
+-to pick up the basic items
+-(called
+-.I tokens )
+-from the input stream.
+-These tokens are organized according to the input structure rules,
+-called
+-.I "grammar rules" \|;
+-when one of these rules has been recognized,
+-then user code supplied for this rule, an
+-.I action ,
+-is invoked; actions have the ability to return values and
+-make use of the values of other actions.
+-.PP
+-Yacc is written in a portable dialect of C
+-.[
+-Ritchie Kernighan Language Prentice
+-.]
+-and the actions, and output subroutine, are in C as well.
+-Moreover, many of the syntactic conventions of Yacc follow C.
+-.PP
+-The heart of the input specification is a collection of grammar rules.
+-Each rule describes an allowable structure and gives it a name.
+-For example, one grammar rule might be
+-.DS
+-date  :  month\_name  day  \',\'  year   ;
+-.DE
+-Here,
+-.I date ,
+-.I month\_name ,
+-.I day ,
+-and
+-.I year
+-represent structures of interest in the input process;
+-presumably,
+-.I month\_name ,
+-.I day ,
+-and
+-.I year
+-are defined elsewhere.
+-The comma ``,'' is enclosed in single quotes; this implies that the
+-comma is to appear literally in the input.
+-The colon and semicolon merely serve as punctuation in the rule, and have
+-no significance in controlling the input.
+-Thus, with proper definitions, the input
+-.DS
+-July  4, 1776
+-.DE
+-might be matched by the above rule.
+-.PP
+-An important part of the input process is carried out by the
+-lexical analyzer.
+-This user routine reads the input stream, recognizing the lower level structures,
+-and communicates these tokens
+-to the parser.
+-For historical reasons, a structure recognized by the lexical analyzer is called a
+-.I "terminal symbol" ,
+-while the structure recognized by the parser is called a
+-.I "nonterminal symbol" .
+-To avoid confusion, terminal symbols will usually be referred to as
+-.I tokens .
+-.PP
+-There is considerable leeway in deciding whether to recognize structures using the lexical
+-analyzer or grammar rules.
+-For example, the rules
+-.DS
+-month\_name  :  \'J\' \'a\' \'n\'   ;
+-month\_name  :  \'F\' \'e\' \'b\'   ;
+-
+-         . . .
+-
+-month\_name  :  \'D\' \'e\' \'c\'   ;
+-.DE
+-might be used in the above example.
+-The lexical analyzer would only need to recognize individual letters, and
+-.I month\_name
+-would be a nonterminal symbol.
+-Such low-level rules tend to waste time and space, and may
+-complicate the specification beyond Yacc's ability to deal with it.
+-Usually, the lexical analyzer would
+-recognize the month names,
+-and return an indication that a
+-.I month\_name
+-was seen; in this case,
+-.I month\_name
+-would be a token.
+-.PP
+-Literal characters such as ``,'' must also be passed through the lexical
+-analyzer, and are also considered tokens.
+-.PP
+-Specification files are very flexible.
+-It is realively easy to add to the above example the rule
+-.DS
+-date  :  month \'/\' day \'/\' year   ;
+-.DE
+-allowing
+-.DS
+-7 / 4 / 1776
+-.DE
+-as a synonym for
+-.DS
+-July 4, 1776
+-.DE
+-In most cases, this new rule could be ``slipped in'' to a working system with minimal effort,
+-and little danger of disrupting existing input.
+-.PP
+-The input being read may not conform to the
+-specifications.
+-These input errors are detected as early as is theoretically possible with a
+-left-to-right scan;
+-thus, not only is the chance of reading and computing with bad
+-input data substantially reduced, but the bad data can usually be quickly found.
+-Error handling,
+-provided as part of the input specifications,
+-permits the reentry of bad data,
+-or the continuation of the input process after skipping over the bad data.
+-.PP
+-In some cases, Yacc fails to produce a parser when given a set of
+-specifications.
+-For example, the specifications may be self contradictory, or they may
+-require a more powerful recognition mechanism than that available to Yacc.
+-The former cases represent design errors;
+-the latter cases
+-can often be corrected
+-by making
+-the lexical analyzer
+-more powerful, or by rewriting some of the grammar rules.
+-While Yacc cannot handle all possible specifications, its power
+-compares favorably with similar systems;
+-moreover, the
+-constructions which are difficult for Yacc to handle are
+-also frequently difficult for human beings to handle.
+-Some users have reported that the discipline of formulating valid
+-Yacc specifications for their input revealed errors of
+-conception or design early in the program development.
+-.PP
+-The theory underlying Yacc has been described elsewhere.
+-.[
+-Aho Johnson Surveys LR Parsing
+-.]
+-.[
+-Aho Johnson Ullman Ambiguous Grammars
+-.]
+-.[
+-Aho Ullman Principles Compiler Design
+-.]
+-Yacc has been extensively used in numerous practical applications,
+-including
+-.I lint ,
+-.[
+-Johnson Lint
+-.]
+-the Portable C Compiler,
+-.[
+-Johnson Portable Compiler Theory
+-.]
+-and a system for typesetting mathematics.
+-.[
+-Kernighan Cherry typesetting system CACM
+-.]
+-.PP
+-The next several sections describe the
+-basic process of preparing a Yacc specification;
+-Section 1 describes the preparation of grammar rules,
+-Section 2 the preparation of the user supplied actions associated with these rules,
+-and Section 3 the preparation of lexical analyzers.
+-Section 4 describes the operation of the parser.
+-Section 5 discusses various reasons why Yacc may be unable to produce a
+-parser from a specification, and what to do about it.
+-Section 6 describes a simple mechanism for
+-handling operator precedences in arithmetic expressions.
+-Section 7 discusses error detection and recovery.
+-Section 8 discusses the operating environment and special features
+-of the parsers Yacc produces.
+-Section 9 gives some suggestions which should improve the
+-style and efficiency of the specifications.
+-Section 10 discusses some advanced topics, and Section 11 gives
+-acknowledgements.
+-Appendix A has a brief example, and Appendix B gives a
+-summary of the Yacc input syntax.
+-Appendix C gives an example using some of the more advanced
+-features of Yacc, and, finally,
+-Appendix D describes mechanisms and syntax
+-no longer actively supported, but
+-provided for historical continuity with older versions of Yacc.
+//GO.SYSIN DD ss0
+echo ss1
+sed 's/.//' >ss1 <<'//GO.SYSIN DD ss1'
+-.tr *\(**
+-.tr |\(or
+-.SH
+-1: Basic Specifications
+-.PP
+-Names refer to either tokens or nonterminal symbols.
+-Yacc requires
+-token names to be declared as such.
+-In addition, for reasons discussed in Section 3, it is often desirable
+-to include the lexical analyzer as part of the specification file;
+-it may be useful to include other programs as well.
+-Thus, every specification file consists of three sections:
+-the
+-.I declarations ,
+-.I "(grammar) rules" ,
+-and
+-.I programs .
+-The sections are separated by double percent ``%%'' marks.
+-(The percent ``%'' is generally used in Yacc specifications as an escape character.)
+-.PP
+-In other words, a full specification file looks like
+-.DS
+-declarations
+-%%
+-rules
+-%%
+-programs
+-.DE
+-.PP
+-The declaration section may be empty.
+-Moreover, if the programs section is omitted, the second %% mark may be omitted also;
+-thus, the smallest legal Yacc specification is
+-.DS
+-%%
+-rules
+-.DE
+-.PP
+-Blanks, tabs, and newlines are ignored except
+-that they may not appear in names or multi-character reserved symbols.
+-Comments may appear wherever a name is legal; they are enclosed
+-in /* . . . */, as in C and PL/I.
+-.PP
+-The rules section is made up of one or more grammar rules.
+-A grammar rule has the form:
+-.DS
+-A  :  BODY  ;
+-.DE
+-A represents a nonterminal name, and BODY represents a sequence of zero or more names and literals.
+-The colon and the semicolon are Yacc punctuation.
+-.PP
+-Names may be of arbitrary length, and may be made up of letters, dot ``.'', underscore ``\_'', and
+-non-initial digits.
+-Upper and lower case letters are distinct.
+-The names used in the body of a grammar rule may represent tokens or nonterminal symbols.
+-.PP
+-A literal consists of a character enclosed in single quotes ``\'''.
+-As in C, the backslash ``\e'' is an escape character within literals, and all the C escapes
+-are recognized.
+-Thus
+-.DS
+-\'\en\'       newline
+-\'\er\'       return
+-\'\e\'\'      single quote ``\'''
+-\'\e\e\'      backslash ``\e''
+-\'\et\'       tab
+-\'\eb\'       backspace
+-\'\ef\'       form feed
+-\'\exxx\'     ``xxx'' in octal
+-.DE
+-For a number of technical reasons, the
+-\s-2NUL\s0
+-character (\'\e0\' or 0) should never
+-be used in grammar rules.
+-.PP
+-If there are several grammar rules with the same left hand side, the vertical bar ``|''
+-can be used to avoid rewriting the left hand side.
+-In addition,
+-the semicolon at the end of a rule can be dropped before a vertical bar.
+-Thus the grammar rules
+-.DS
+-A     :       B  C  D   ;
+-A     :       E  F   ;
+-A     :       G   ;
+-.DE
+-can be given to Yacc as
+-.DS
+-A     :       B  C  D
+-      |       E  F
+-      |       G
+-      ;
+-.DE
+-It is not necessary that all grammar rules with the same left side appear together in the grammar rules section,
+-although it makes the input much more readable, and easier to change.
+-.PP
+-If a nonterminal symbol matches the empty string, this can be indicated in the obvious way:
+-.DS
+-empty :   ;
+-.DE
+-.PP
+-Names representing tokens must be declared; this is most simply done by writing
+-.DS
+-%token   name1  name2 . . .
+-.DE
+-in the declarations section.
+-(See Sections 3 , 5, and 6 for much more discussion).
+-Every name not defined in the declarations section is assumed to represent a nonterminal symbol.
+-Every nonterminal symbol must appear on the left side of at least one rule.
+-.PP
+-Of all the nonterminal symbols, one, called the
+-.I "start symbol" ,
+-has particular importance.
+-The parser is designed to recognize the start symbol; thus,
+-this symbol represents the largest,
+-most general structure described by the grammar rules.
+-By default,
+-the start symbol is taken to be the left hand side of the first
+-grammar rule in the rules section.
+-It is possible, and in fact desirable, to declare the start
+-symbol explicitly in the declarations section using the %start keyword:
+-.DS
+-%start   symbol
+-.DE
+-.PP
+-The end of the input to the parser is signaled by a special token, called the
+-.I endmarker .
+-If the tokens up to, but not including, the endmarker form a structure
+-which matches the start symbol, the parser function returns to its caller
+-after the endmarker is seen; it
+-.I accepts
+-the input.
+-If the endmarker is seen in any other context, it is an error.
+-.PP
+-It is the job of the user-supplied lexical analyzer
+-to return the endmarker when appropriate; see section 3, below.
+-Usually the endmarker represents some reasonably obvious 
+-I/O status, such as ``end-of-file'' or ``end-of-record''.
+//GO.SYSIN DD ss1
+echo ss2
+sed 's/.//' >ss2 <<'//GO.SYSIN DD ss2'
+-.SH
+-2: Actions
+-.PP
+-With each grammar rule, the user may associate actions to be performed each time
+-the rule is recognized in the input process.
+-These actions may return values, and may obtain the values returned by previous
+-actions.
+-Moreover, the lexical analyzer can return values
+-for tokens, if desired.
+-.PP
+-An action is an arbitrary C statement, and as such can do
+-input and output, call subprograms, and alter
+-external vectors and variables.
+-An action is specified by
+-one or more statements, enclosed in curly braces ``{'' and ``}''.
+-For example,
+-.DS
+-A     :       \'(\'  B  \')\'
+-                      {       hello( 1, "abc" );  }
+-.DE
+-and
+-.DS
+-XXX   :       YYY  ZZZ
+-                      {       printf("a message\en");
+-                              flag = 25;   }
+-.DE
+-are grammar rules with actions.
+-.PP
+-To facilitate easy communication between the actions and the parser, the action statements are altered
+-slightly.
+-The symbol ``dollar sign'' ``$'' is used as a signal to Yacc in this context.
+-.PP
+-To return a value, the action normally sets the
+-pseudo-variable ``$$'' to some value.
+-For example, an action that does nothing but return the value 1 is
+-.DS
+-      {  $$ = 1;  }
+-.DE
+-.PP
+-To obtain the values returned by previous actions and the lexical analyzer, the
+-action may use the pseudo-variables $1, $2, . . .,
+-which refer to the values returned by the
+-components of the right side of a rule, reading from left to right.
+-Thus, if the rule is
+-.DS
+-A     :       B  C  D   ;
+-.DE
+-for example, then $2 has the value returned by C, and $3 the value returned by D.
+-.PP
+-As a more concrete example, consider the rule
+-.DS
+-expr  :       \'(\'  expr  \')\'   ;
+-.DE
+-The value returned by this rule is usually the value of the
+-.I expr
+-in parentheses.
+-This can be indicated by
+-.DS
+-expr  :        \'(\'  expr  \')\'             {  $$ = $2 ;  }
+-.DE
+-.PP
+-By default, the value of a rule is the value of the first element in it ($1).
+-Thus, grammar rules of the form
+-.DS
+-A     :       B    ;
+-.DE
+-frequently need not have an explicit action.
+-.PP
+-In the examples above, all the actions came at the end of their rules.
+-Sometimes, it is desirable to get control before a rule is fully parsed.
+-Yacc permits an action to be written in the middle of a rule as well
+-as at the end.
+-This rule is assumed to return a value, accessible
+-through the usual \$ mechanism by the actions to
+-the right of it.
+-In turn, it may access the values
+-returned by the symbols to its left.
+-Thus, in the rule
+-.DS
+-A     :       B
+-                      {  $$ = 1;  }
+-              C
+-                      {   x = $2;   y = $3;  }
+-      ;
+-.DE
+-the effect is to set
+-.I x
+-to 1, and
+-.I y
+-to the value returned by C.
+-.PP
+-Actions that do not terminate a rule are actually
+-handled by Yacc by manufacturing a new nonterminal
+-symbol name, and a new rule matching this
+-name to the empty string.
+-The interior action is the action triggered off by recognizing
+-this added rule.
+-Yacc actually treats the above example as if
+-it had been written:
+-.DS
+-$ACT  :       /* empty */
+-                      {  $$ = 1;  }
+-      ;
+-
+-A     :       B  $ACT  C
+-                      {   x = $2;   y = $3;  }
+-      ;
+-.DE
+-.PP
+-In many applications, output is not done directly by the actions;
+-rather, a data structure, such as a parse tree, is constructed in memory,
+-and transformations are applied to it before output is generated.
+-Parse trees are particularly easy to
+-construct, given routines to build and maintain the tree
+-structure desired.
+-For example, suppose there is a C function
+-.I node ,
+-written so that the call
+-.DS
+-node( L, n1, n2 )
+-.DE
+-creates a node with label L, and descendants n1 and n2, and returns the index of
+-the newly created node.
+-Then parse tree can be built by supplying actions such as:
+-.DS
+-expr  :       expr  \'+\'  expr  
+-                      {  $$ = node( \'+\', $1, $3 );  }
+-.DE
+-in the specification.
+-.PP
+-The user may define other variables to be used by the actions.
+-Declarations and definitions can appear in
+-the declarations section,
+-enclosed in the marks ``%{'' and ``%}''.
+-These declarations and definitions have global scope, 
+-so they are known to the action statements and the lexical analyzer.
+-For example,
+-.DS
+-%{   int variable = 0;   %}
+-.DE
+-could be placed in the declarations section,
+-making
+-.I variable
+-accessible to all of the actions.
+-The Yacc parser uses only names beginning in ``yy'';
+-the user should avoid such names.
+-.PP
+-In these examples, all the values are integers: a discussion of
+-values of other types will be found in Section 10.
+//GO.SYSIN DD ss2
+echo ss3
+sed 's/.//' >ss3 <<'//GO.SYSIN DD ss3'
+-.SH
+-3: Lexical Analysis
+-.PP
+-The user must supply a lexical analyzer to read the input stream and communicate tokens
+-(with values, if desired) to the parser.
+-The lexical analyzer is an integer-valued function called
+-.I yylex .
+-The function returns an integer, the
+-.I "token number" ,
+-representing the kind of token read.
+-If there is a value associated with that token, it should be assigned
+-to the external variable
+-.I yylval .
+-.PP
+-The parser and the lexical analyzer must agree on these token numbers in order for
+-communication between them to take place.
+-The numbers may be chosen by Yacc, or chosen by the user.
+-In either case, the ``# define'' mechanism of C is used to allow the lexical analyzer
+-to return these numbers symbolically.
+-For example, suppose that the token name DIGIT has been defined in the declarations section of the
+-Yacc specification file.
+-The relevant portion of the lexical analyzer might look like:
+-.DS
+-yylex(){
+-      extern int yylval;
+-      int c;
+-      . . .
+-      c = getchar();
+-      . . .
+-      switch( c ) {
+-              . . .
+-      case \'0\':
+-      case \'1\':
+-        . . .
+-      case \'9\':
+-              yylval = c\-\'0\';
+-              return( DIGIT );
+-              . . .
+-              }
+-      . . .
+-.DE
+-.PP
+-The intent is to return a token number of DIGIT, and a value equal to the numerical value of the
+-digit.
+-Provided that the lexical analyzer code is placed in the programs section of the specification file,
+-the identifier DIGIT will be defined as the token number associated
+-with the token DIGIT.
+-.PP
+-This mechanism leads to clear,
+-easily modified lexical analyzers; the only pitfall is the need
+-to avoid using any token names in the grammar that are reserved
+-or significant in C or the parser; for example, the use of
+-token names
+-.I if
+-or
+-.I while
+-will almost certainly cause severe
+-difficulties when the lexical analyzer is compiled.
+-The token name
+-.I error
+-is reserved for error handling, and should not be used naively
+-(see Section 7).
+-.PP
+-As mentioned above, the token numbers may be chosen by Yacc or by the user.
+-In the default situation, the numbers are chosen by Yacc.
+-The default token number for a literal
+-character is the numerical value of the character in the local character set.
+-Other names are assigned token numbers
+-starting at 257.
+-.PP
+-To assign a token number to a token (including literals),
+-the first appearance of the token name or literal
+-.I
+-in the declarations section
+-.R
+-can be immediately followed by
+-a nonnegative integer.
+-This integer is taken to be the token number of the name or literal.
+-Names and literals not defined by this mechanism retain their default definition.
+-It is important that all token numbers be distinct.
+-.PP
+-For historical reasons, the endmarker must have token
+-number 0 or negative.
+-This token number cannot be redefined by the user; thus, all
+-lexical analyzers should be prepared to return 0 or negative as a token number
+-upon reaching the end of their input.
+-.PP
+-A very useful tool for constructing lexical analyzers is
+-the
+-.I Lex
+-program developed by Mike Lesk.
+-.[
+-Lesk Lex
+-.]
+-These lexical analyzers are designed to work in close
+-harmony with Yacc parsers.
+-The specifications for these lexical analyzers
+-use regular expressions instead of grammar rules.
+-Lex can be easily used to produce quite complicated lexical analyzers,
+-but there remain some languages (such as FORTRAN) which do not
+-fit any theoretical framework, and whose lexical analyzers
+-must be crafted by hand.
+//GO.SYSIN DD ss3
+echo ss4
+sed 's/.//' >ss4 <<'//GO.SYSIN DD ss4'
+-.SH
+-4: How the Parser Works
+-.PP
+-Yacc turns the specification file into a C program, which
+-parses the input according to the specification given.
+-The algorithm used to go from the
+-specification to the parser is complex, and will not be discussed
+-here (see
+-the references for more information).
+-The parser itself, however, is relatively simple,
+-and understanding how it works, while
+-not strictly necessary, will nevertheless make
+-treatment of error recovery and ambiguities much more
+-comprehensible.
+-.PP
+-The parser produced by Yacc consists
+-of a finite state machine with a stack.
+-The parser is also capable of reading and remembering the next
+-input token (called the
+-.I lookahead
+-token).
+-The
+-.I "current state"
+-is always the one on the top of the stack.
+-The states of the finite state machine are given
+-small integer labels; initially, the machine is in state 0,
+-the stack contains only state 0, and no lookahead token has been read.
+-.PP
+-The machine has only four actions available to it, called
+-.I shift ,
+-.I reduce ,
+-.I accept ,
+-and
+-.I error .
+-A move of the parser is done as follows:
+-.IP 1.
+-Based on its current state, the parser decides
+-whether it needs a lookahead token to decide
+-what action should be done; if it needs one, and does
+-not have one, it calls
+-.I yylex
+-to obtain the next token.
+-.IP 2.
+-Using the current state, and the lookahead token
+-if needed, the parser decides on its next action, and
+-carries it out.
+-This may result in states being pushed onto the stack, or popped off of
+-the stack, and in the lookahead token being processed
+-or left alone.
+-.PP
+-The
+-.I shift
+-action is the most common action the parser takes.
+-Whenever a shift action is taken, there is always
+-a lookahead token.
+-For example, in state 56 there may be
+-an action:
+-.DS
+-      IF      shift 34
+-.DE
+-which says, in state 56, if the lookahead token is IF,
+-the current state (56) is pushed down on the stack,
+-and state 34 becomes the current state (on the
+-top of the stack).
+-The lookahead token is cleared.
+-.PP
+-The
+-.I reduce
+-action keeps the stack from growing without
+-bounds.
+-Reduce actions are appropriate when the parser has seen
+-the right hand side of a grammar rule,
+-and is prepared to announce that it has seen
+-an instance of the rule, replacing the right hand side
+-by the left hand side.
+-It may be necessary to consult the lookahead token
+-to decide whether to reduce, but
+-usually it is not; in fact, the default
+-action (represented by a ``.'') is often a reduce action.
+-.PP
+-Reduce actions are associated with individual grammar rules.
+-Grammar rules are also given small integer
+-numbers, leading to some confusion.
+-The action
+-.DS
+-      \fB.\fR reduce 18
+-.DE
+-refers to
+-.I "grammar rule"
+-18, while the action
+-.DS
+-      IF      shift 34
+-.DE
+-refers to
+-.I state
+-34.
+-.PP
+-Suppose the rule being reduced is
+-.DS
+-A     \fB:\fR x  y  z    ;
+-.DE
+-The reduce action depends on the
+-left hand symbol (A in this case), and the number of
+-symbols on the right hand side (three in this case).
+-To reduce, first pop off the top three states
+-from the stack
+-(In general, the number of states popped equals the number of symbols on the
+-right side of the rule).
+-In effect, these states were the ones
+-put on the stack while recognizing
+-.I x ,
+-.I y ,
+-and
+-.I z ,
+-and no longer serve any useful purpose.
+-After popping these states, a state is uncovered
+-which was the state the parser was in before beginning to
+-process the rule.
+-Using this uncovered state, and the symbol
+-on the left side of the rule, perform what is in
+-effect a shift of A.
+-A new state is obtained, pushed onto the stack, and parsing continues.
+-There are significant differences between the processing of
+-the left hand symbol and an ordinary shift of a token,
+-however, so this action is called a
+-.I goto
+-action.
+-In particular, the lookahead token is cleared by a shift, and
+-is not affected by a goto.
+-In any case, the uncovered state contains an entry such as:
+-.DS
+-      A       goto 20
+-.DE
+-causing state 20 to be pushed
+-onto the stack, and become the current state.
+-.PP
+-In effect, the reduce action ``turns back the clock'' in the parse,
+-popping the states off the stack to go back to the
+-state where the right hand side of the rule was first seen.
+-The parser then behaves as if it had seen the left side at that time.
+-If the right hand side of the rule is empty,
+-no states are popped off of the stack: the uncovered state
+-is in fact the current state.
+-.PP
+-The reduce action is also important in the treatment of user-supplied
+-actions and values.
+-When a rule is reduced, the code supplied with the rule is executed
+-before the stack is adjusted.
+-In addition to the stack holding the states, another stack,
+-running in parallel with it, holds the values returned
+-from the lexical analyzer and the actions.
+-When a shift takes place, the external variable
+-.I yylval
+-is copied onto the value stack.
+-After the return from the user code, the reduction is carried out.
+-When the
+-.I goto
+-action is done, the external variable
+-.I yyval
+-is copied onto the value stack.
+-The pseudo-variables $1, $2, etc., refer to the value stack.
+-.PP
+-The other two parser actions are conceptually much simpler.
+-The
+-.I accept
+-action indicates that the entire input has been seen and
+-that it matches the specification.
+-This action appears only when the lookahead token is 
+-the endmarker, and indicates that the parser has successfully
+-done its job.
+-The
+-.I error
+-action, on the other hand, represents a place where the parser
+-can no longer continue parsing according to the specification.
+-The input tokens it has seen, together with the lookahead token,
+-cannot be followed by anything that would result
+-in a legal input.
+-The parser reports an error, and attempts to recover the situation and
+-resume parsing: the error recovery (as opposed to the detection of error)
+-will be covered in Section 7.
+-.PP
+-It is time for an example!
+-Consider the specification
+-.DS
+-%token  DING  DONG  DELL
+-%%
+-rhyme :       sound  place
+-      ;
+-sound :       DING  DONG
+-      ;
+-place :       DELL
+-      ;
+-.DE
+-.PP
+-When Yacc is invoked with the
+-.B \-v
+-option, a file called
+-.I y.output
+-is produced, with a human-readable description of the parser.
+-The
+-.I y.output
+-file corresponding to the above grammar (with some statistics
+-stripped off the end) is:
+-.DS
+-state 0
+-      $accept  :  \_rhyme  $end 
+-
+-      DING  shift 3
+-      .  error
+-
+-      rhyme  goto 1
+-      sound  goto 2
+-
+-state 1
+-      $accept  :   rhyme\_$end 
+-
+-      $end  accept
+-      .  error
+-
+-state 2
+-      rhyme  :   sound\_place 
+-
+-      DELL  shift 5
+-      .  error
+-
+-      place   goto 4
+-
+-state 3
+-      sound   :   DING\_DONG 
+-
+-      DONG  shift 6
+-      .  error
+-
+-state 4
+-      rhyme  :   sound  place\_    (1)
+-
+-      .   reduce  1
+-
+-state 5
+-      place  :   DELL\_    (3)
+-
+-      .   reduce  3
+-
+-state 6
+-      sound   :   DING  DONG\_    (2)
+-
+-      .   reduce  2
+-.DE
+-Notice that, in addition to the actions for each state, there is a
+-description of the parsing rules being processed in each
+-state.  The \_ character is used to indicate
+-what has been seen, and what is yet to come, in each rule.
+-Suppose the input is
+-.DS
+-DING  DONG  DELL
+-.DE
+-It is instructive to follow the steps of the parser while
+-processing this input.
+-.PP
+-Initially, the current state is state 0.
+-The parser needs to refer to the input in order to decide
+-between the actions available in state 0, so
+-the first token,
+-.I DING ,
+-is read, becoming the lookahead token.
+-The action in state 0 on
+-.I DING
+-is
+-is ``shift 3'', so state 3 is pushed onto the stack,
+-and the lookahead token is cleared.
+-State 3 becomes the current state.
+-The next token,
+-.I DONG ,
+-is read, becoming the lookahead token.
+-The action in state 3 on the token
+-.I DONG
+-is ``shift 6'',
+-so state 6 is pushed onto the stack, and the lookahead is cleared.
+-The stack now contains 0, 3, and 6.
+-In state 6, without even consulting the lookahead,
+-the parser reduces by rule 2.
+-.DS
+-      sound  :   DING  DONG
+-.DE
+-This rule has two symbols on the right hand side, so
+-two states, 6 and 3, are popped off of the stack, uncovering state 0.
+-Consulting the description of state 0, looking for a goto on 
+-.I sound ,
+-.DS
+-      sound   goto 2
+-.DE
+-is obtained; thus state 2 is pushed onto the stack,
+-becoming the current state.
+-.PP
+-In state 2, the next token,
+-.I DELL ,
+-must be read.
+-The action is ``shift 5'', so state 5 is pushed onto the stack, which now has
+-0, 2, and 5 on it, and the lookahead token is cleared.
+-In state 5, the only action is to reduce by rule 3.
+-This has one symbol on the right hand side, so one state, 5,
+-is popped off, and state 2 is uncovered.
+-The goto in state 2 on
+-.I place ,
+-the left side of rule 3,
+-is state 4.
+-Now, the stack contains 0, 2, and 4.
+-In state 4, the only action is to reduce by rule 1.
+-There are two symbols on the right, so the top two states are popped off,
+-uncovering state 0 again.
+-In state 0, there is a goto on
+-.I rhyme
+-causing the parser to enter state 1.
+-In state 1, the input is read; the endmarker is obtained,
+-indicated by ``$end'' in the
+-.I y.output
+-file.
+-The action in state 1 when the endmarker is seen is to accept,
+-successfully ending the parse.
+-.PP
+-The reader is urged to consider how the parser works
+-when confronted with such incorrect strings as
+-.I "DING DONG DONG" ,
+-.I "DING DONG" ,
+-.I "DING DONG DELL DELL" ,
+-etc.
+-A few minutes spend with this and other simple examples will
+-probably be repaid when problems arise in more complicated contexts.
+//GO.SYSIN DD ss4
+echo ss5
+sed 's/.//' >ss5 <<'//GO.SYSIN DD ss5'
+-.SH
+-5: Ambiguity and Conflicts
+-.PP
+-A set of grammar rules is
+-.I ambiguous
+-if there is some input string that can be structured in two or more different ways.
+-For example, the grammar rule
+-.DS
+-expr  :       expr  \'\-\'  expr
+-.DE
+-is a natural way of expressing the fact that one way of forming an arithmetic expression
+-is to put two other expressions together with a minus sign between them.
+-Unfortunately, this grammar rule does not
+-completely specify the way that all complex inputs
+-should be structured.
+-For example, if the input is
+-.DS
+-expr  \-  expr  \-  expr
+-.DE
+-the rule allows this input to be structured as either
+-.DS
+-(  expr  \-  expr  )  \-  expr
+-.DE
+-or as
+-.DS
+-expr  \-  (  expr  \-  expr  )
+-.DE
+-(The first is called
+-.I "left association" ,
+-the second
+-.I "right association" ).
+-.PP
+-Yacc detects such ambiguities when it is attempting to build the parser.
+-It is instructive to consider the problem that confronts the parser when it is
+-given an input such as
+-.DS
+-expr  \-  expr  \-  expr
+-.DE
+-When the parser has read the second expr, the input that it has seen:
+-.DS
+-expr  \-  expr
+-.DE
+-matches the right side of the grammar rule above.
+-The parser could
+-.I reduce
+-the input by applying this rule;
+-after applying the rule;
+-the input is reduced to
+-.I expr (the
+-left side of the rule).
+-The parser would then read the final part of the input:
+-.DS
+-\-  expr
+-.DE
+-and again reduce.
+-The effect of this is to take the left associative interpretation.
+-.PP
+-Alternatively, when the parser has seen
+-.DS
+-expr  \-  expr
+-.DE
+-it could defer the immediate application of the rule, and continue reading
+-the input until it had seen
+-.DS
+-expr  \-  expr  \-  expr
+-.DE
+-It could then apply the rule to the rightmost three symbols, reducing them to
+-.I expr
+-and leaving
+-.DS
+-expr  \-  expr
+-.DE
+-Now the rule can be reduced once more; the effect is to
+-take the right associative interpretation.
+-Thus, having read
+-.DS
+-expr  \-  expr
+-.DE
+-the parser can do two legal things, a shift or a reduction, and has no way of
+-deciding between them.
+-This is called a
+-.I "shift / reduce conflict" .
+-It may also happen that the parser has a choice of two legal reductions;
+-this is called a
+-.I "reduce / reduce conflict" .
+-Note that there are never any ``Shift/shift'' conflicts.
+-.PP
+-When there are shift/reduce or reduce/reduce conflicts, Yacc still produces a parser.
+-It does this by selecting one of the valid steps wherever it has a choice.
+-A rule describing which choice to make in a given situation is called
+-a
+-.I "disambiguating rule" .
+-.PP
+-Yacc invokes two disambiguating rules by default:
+-.IP 1.
+-In a shift/reduce conflict, the default is to do the shift.
+-.IP 2.
+-In a reduce/reduce conflict, the default is to reduce by the
+-.I earlier
+-grammar rule (in the input sequence).
+-.PP
+-Rule 1 implies that reductions are deferred whenever there is a choice,
+-in favor of shifts.
+-Rule 2 gives the user rather crude control over the behavior of the parser
+-in this situation, but reduce/reduce conflicts should be avoided whenever possible.
+-.PP
+-Conflicts may arise because of mistakes in input or logic, or because the grammar rules, while consistent,
+-require a more complex parser than Yacc can construct.
+-The use of actions within rules can also cause conflicts, if the action must
+-be done before the parser can be sure which rule is being recognized.
+-In these cases, the application of disambiguating rules is inappropriate,
+-and leads to an incorrect parser.
+-For this reason, Yacc
+-always reports the number of shift/reduce and reduce/reduce conflicts resolved by Rule 1 and Rule 2.
+-.PP
+-In general, whenever it is possible to apply disambiguating rules to produce a correct parser, it is also
+-possible to rewrite the grammar rules so that the same inputs are read but there are no
+-conflicts.
+-For this reason, most previous parser generators
+-have considered conflicts to be fatal errors.
+-Our experience has suggested that this rewriting is somewhat unnatural,
+-and produces slower parsers; thus, Yacc will produce parsers even in the presence of conflicts.
+-.PP
+-As an example of the power of disambiguating rules, consider a fragment from a programming
+-language involving an ``if-then-else'' construction:
+-.DS
+-stat  :       IF  \'(\'  cond  \')\'  stat
+-      |       IF  \'(\'  cond  \')\'  stat  ELSE  stat
+-      ;
+-.DE
+-In these rules,
+-.I IF
+-and
+-.I ELSE
+-are tokens,
+-.I cond
+-is a nonterminal symbol describing
+-conditional (logical) expressions, and
+-.I stat
+-is a nonterminal symbol describing statements.
+-The first rule will be called the
+-.ul
+-simple-if
+-rule, and the
+-second the
+-.ul
+-if-else
+-rule.
+-.PP
+-These two rules form an ambiguous construction, since input of the form
+-.DS
+-IF  (  C1  )  IF  (  C2  )  S1  ELSE  S2
+-.DE
+-can be structured according to these rules in two ways:
+-.DS
+-IF  (  C1  )  {
+-      IF  (  C2  )  S1
+-      }
+-ELSE  S2
+-.DE
+-or
+-.DS
+-IF  (  C1  )  {
+-      IF  (  C2  )  S1
+-      ELSE  S2
+-      }
+-.DE
+-The second interpretation is the one given in most programming languages
+-having this construct.
+-Each
+-.I ELSE
+-is associated with the last preceding
+-``un-\fIELSE'\fRd''
+-.I IF .
+-In this example, consider the situation where the parser has seen
+-.DS
+-IF  (  C1  )  IF  (  C2  )  S1
+-.DE
+-and is looking at the
+-.I ELSE .
+-It can immediately
+-reduce
+-by the simple-if rule to get
+-.DS
+-IF  (  C1  )  stat
+-.DE
+-and then read the remaining input,
+-.DS
+-ELSE  S2
+-.DE
+-and reduce
+-.DS
+-IF  (  C1  )  stat  ELSE  S2
+-.DE
+-by the if-else rule.
+-This leads to the first of the above groupings of the input.
+-.PP
+-On the other hand, the
+-.I ELSE
+-may be shifted,
+-.I S2
+-read, and then the right hand portion of
+-.DS
+-IF  (  C1  )  IF  (  C2  )  S1  ELSE  S2
+-.DE
+-can be reduced by the if-else rule to get
+-.DS
+-IF  (  C1  )  stat
+-.DE
+-which can be reduced by the simple-if rule.
+-This leads to the second of the above groupings of the input, which
+-is usually desired.
+-.PP
+-Once again the parser can do two valid things \- there is a shift/reduce conflict.
+-The application of disambiguating rule 1 tells the parser to shift in this case,
+-which leads to the desired grouping.
+-.PP
+-This shift/reduce conflict arises only when there is a particular current input symbol,
+-.I ELSE ,
+-and particular inputs already seen, such as
+-.DS
+-IF  (  C1  )  IF  (  C2  )  S1
+-.DE
+-In general, there may be many conflicts, and each one
+-will be associated with an input symbol and
+-a set of previously read inputs.
+-The previously read inputs are characterized by the
+-state
+-of the parser.
+-.PP
+-The conflict messages of Yacc are best understood
+-by examining the verbose (\fB\-v\fR) option output file.
+-For example, the output corresponding to the above
+-conflict state might be:
+-.DS L
+-23: shift/reduce conflict (shift 45, reduce 18) on ELSE
+-
+-state 23
+-
+-        stat  :  IF  (  cond  )  stat\_         (18)
+-        stat  :  IF  (  cond  )  stat\_ELSE  stat
+-
+-       ELSE     shift 45
+-       .        reduce 18
+-
+-.DE
+-The first line describes the conflict, giving the state and the input symbol.
+-The ordinary state description follows, giving
+-the grammar rules active in the state, and the parser actions.
+-Recall that the underline marks the
+-portion of the grammar rules which has been seen.
+-Thus in the example, in state 23 the parser has seen input corresponding
+-to
+-.DS
+-IF  (  cond  )  stat
+-.DE
+-and the two grammar rules shown are active at this time.
+-The parser can do two possible things.
+-If the input symbol is
+-.I ELSE ,
+-it is possible to shift into state
+-45.
+-State 45 will have, as part of its description, the line
+-.DS
+-stat  :  IF  (  cond  )  stat  ELSE\_stat
+-.DE
+-since the
+-.I ELSE
+-will have been shifted in this state.
+-Back in state 23, the alternative action, described by ``\fB.\fR'',
+-is to be done if the input symbol is not mentioned explicitly in the above actions; thus,
+-in this case, if the input symbol is not
+-.I ELSE ,
+-the parser reduces by grammar rule 18:
+-.DS
+-stat  :  IF  \'(\'  cond  \')\'  stat
+-.DE
+-Once again, notice that the numbers following ``shift'' commands refer to other states,
+-while the numbers following ``reduce'' commands refer to grammar
+-rule numbers.
+-In the
+-.I y.output
+-file, the rule numbers are printed after those rules which can be reduced.
+-In most one states, there will be at most reduce action possible in the
+-state, and this will be the default command.
+-The user who encounters unexpected shift/reduce conflicts will probably want to
+-look at the verbose output to decide whether the default actions are appropriate.
+-In really tough cases, the user might need to know more about
+-the behavior and construction of the parser than can be covered here.
+-In this case, one of the theoretical references
+-.[
+-Aho Johnson Surveys Parsing
+-.]
+-.[
+-Aho Johnson Ullman Deterministic Ambiguous
+-.]
+-.[
+-Aho Ullman Principles Design
+-.]
+-might be consulted; the services of a local guru might also be appropriate.
+//GO.SYSIN DD ss5
+echo ss6
+sed 's/.//' >ss6 <<'//GO.SYSIN DD ss6'
+-.SH
+-6: Precedence
+-.PP
+-There is one common situation
+-where the rules given above for resolving conflicts are not sufficient;
+-this is in the parsing of arithmetic expressions.
+-Most of the commonly used constructions for arithmetic expressions can be naturally
+-described by the notion of
+-.I precedence
+-levels for operators, together with information about left
+-or right associativity.
+-It turns out that ambiguous grammars with appropriate disambiguating rules
+-can be used to create parsers that are faster and easier to
+-write than parsers constructed from unambiguous grammars.
+-The basic notion is to write grammar rules
+-of the form
+-.DS
+-expr  :  expr  OP  expr
+-.DE
+-and
+-.DS
+-expr  :  UNARY  expr
+-.DE
+-for all binary and unary operators desired.
+-This creates a very ambiguous grammar, with many parsing conflicts.
+-As disambiguating rules, the user specifies the precedence, or binding
+-strength, of all the operators, and the associativity
+-of the binary operators.
+-This information is sufficient to allow Yacc to resolve the parsing conflicts
+-in accordance with these rules, and construct a parser that realizes the desired
+-precedences and associativities.
+-.PP
+-The precedences and associativities are attached to tokens in the declarations section.
+-This is done by a series of lines beginning with a Yacc keyword: %left, %right,
+-or %nonassoc, followed by a list of tokens.
+-All of the tokens on the same line are assumed to have the same precedence level
+-and associativity; the lines are listed in
+-order of increasing precedence or binding strength.
+-Thus,
+-.DS
+-%left  \'+\'  \'\-\'
+-%left  \'*\'  \'/\'
+-.DE
+-describes the precedence and associativity of the four arithmetic operators.
+-Plus and minus are left associative, and have lower precedence than
+-star and slash, which are also left associative.
+-The keyword %right is used to describe right associative operators,
+-and the keyword %nonassoc is used to describe operators, like
+-the operator .LT. in Fortran, that may not associate with themselves; thus,
+-.DS
+-A  .LT.  B  .LT.  C
+-.DE
+-is illegal in Fortran, and such an operator would be described with the keyword
+-%nonassoc in Yacc.
+-As an example of the behavior of these declarations, the description
+-.DS
+-%right  \'=\'
+-%left  \'+\'  \'\-\'
+-%left  \'*\'  \'/\'
+-
+-%%
+-
+-expr  :       expr  \'=\'  expr
+-      |       expr  \'+\'  expr
+-      |       expr  \'\-\'  expr
+-      |       expr  \'*\'  expr
+-      |       expr  \'/\'  expr
+-      |       NAME
+-      ;
+-.DE
+-might be used to structure the input
+-.DS
+-a  =  b  =  c*d  \-  e  \-  f*g
+-.DE
+-as follows:
+-.DS
+-a = ( b = ( ((c*d)\-e) \- (f*g) ) )
+-.DE
+-When this mechanism is used,
+-unary operators must, in general, be given a precedence.
+-Sometimes a unary operator and a binary operator
+-have the same symbolic representation, but different precedences.
+-An example is unary and binary \'\-\'; unary minus may be given the same
+-strength as multiplication, or even higher, while binary minus has a lower strength than
+-multiplication.
+-The keyword, %prec, changes the precedence level associated with a particular grammar rule.
+-%prec appears immediately after the body of the grammar rule, before the action or closing semicolon,
+-and is followed by a token name or literal.
+-It
+-causes the precedence of the grammar rule to become that of the following token name or literal.
+-For example, to make unary minus have the same precedence as multiplication the rules might resemble:
+-.DS
+-%left  \'+\'  \'\-\'
+-%left  \'*\'  \'/\'
+-
+-%%
+-
+-expr  :       expr  \'+\'  expr
+-      |       expr  \'\-\'  expr
+-      |       expr  \'*\'  expr
+-      |       expr  \'/\'  expr
+-      |       \'\-\'  expr      %prec  \'*\'
+-      |       NAME
+-      ;
+-.DE
+-.PP
+-A token declared
+-by %left, %right, and %nonassoc need not be, but may be, declared by %token as well.
+-.PP
+-The precedences and associativities are used by Yacc to
+-resolve parsing conflicts; they give rise to disambiguating rules.
+-Formally, the rules work as follows:
+-.IP 1.
+-The precedences and associativities are recorded for those tokens and literals
+-that have them.
+-.IP 2.
+-A precedence and associativity is associated with each grammar rule; it is the precedence
+-and associativity of the last token or literal in the body of the rule.
+-If the %prec construction is used, it overrides this default.
+-Some grammar rules may have no precedence and associativity associated with them.
+-.IP 3.
+-When there is a reduce/reduce conflict, or there is a shift/reduce conflict
+-and either the input symbol or the grammar rule has no precedence and associativity,
+-then the two disambiguating rules given at the beginning of the section are used,
+-and the conflicts are reported.
+-.IP 4.
+-If there is a shift/reduce conflict, and both the grammar rule and the input character
+-have precedence and associativity associated with them, then the conflict is resolved
+-in favor of the action (shift or reduce) associated with the higher precedence.
+-If the precedences are the same, then the associativity is used; left
+-associative implies reduce, right associative implies shift, and nonassociating
+-implies error.
+-.PP
+-Conflicts resolved by precedence are not counted in the number of shift/reduce and reduce/reduce
+-conflicts reported by Yacc.
+-This means that mistakes in the specification of precedences may
+-disguise errors in the input grammar; it is a good idea to be sparing
+-with precedences, and use them in an essentially ``cookbook'' fashion,
+-until some experience has been gained.
+-The
+-.I y.output
+-file
+-is very useful in deciding whether the parser is actually doing
+-what was intended.
+//GO.SYSIN DD ss6
+echo ss7
+sed 's/.//' >ss7 <<'//GO.SYSIN DD ss7'
+-.SH
+-7: Error Handling
+-.PP
+-Error handling is an extremely difficult area, and many of the problems are semantic ones.
+-When an error is found, for example, it may be necessary to reclaim parse tree storage,
+-delete or alter symbol table entries, and, typically, set switches to avoid generating any further output.
+-.PP
+-It is seldom acceptable to stop all processing when an error is found; it is more useful to continue
+-scanning the input to find further syntax errors.
+-This leads to the problem of getting the parser ``restarted'' after an error.
+-A general class of algorithms to do this involves discarding a number of tokens
+-from the input string, and attempting to adjust the parser so that input can continue.
+-.PP
+-To allow the user some control over this process,
+-Yacc provides a simple, but reasonably general, feature.
+-The token name ``error'' is reserved for error handling.
+-This name can be used in grammar rules;
+-in effect, it suggests places where errors are expected, and recovery might take place.
+-The parser pops its stack until it enters a state where the token ``error'' is legal.
+-It then behaves as if the token ``error'' were the current lookahead token,
+-and performs the action encountered.
+-The lookahead token is then reset to the token that caused the error.
+-If no special error rules have been specified, the processing halts when an error is detected.
+-.PP
+-In order to prevent a cascade of error messages, the parser, after
+-detecting an error, remains in error state until three tokens have been successfully
+-read and shifted.
+-If an error is detected when the parser is already in error state,
+-no message is given, and the input token is quietly deleted.
+-.PP
+-As an example, a rule of the form
+-.DS
+-stat  :       error
+-.DE
+-would, in effect, mean that on a syntax error the parser would attempt to skip over the statement
+-in which the error was seen.
+-More precisely, the parser will
+-scan ahead, looking for three tokens that might legally follow
+-a statement, and start processing at the first of these; if
+-the beginnings of statements are not sufficiently distinctive, it may make a
+-false start in the middle of a statement, and end up reporting a
+-second error where there is in fact no error.
+-.PP
+-Actions may be used with these special error rules.
+-These actions might attempt to reinitialize tables, reclaim symbol table space, etc.
+-.PP
+-Error rules such as the above are very general, but difficult to control.
+-Somewhat easier are rules such as
+-.DS
+-stat  :       error  \';\'
+-.DE
+-Here, when there is an error, the parser attempts to skip over the statement, but
+-will do so by skipping to the next \';\'.
+-All tokens after the error and before the next \';\' cannot be shifted, and are discarded.
+-When the \';\' is seen, this rule will be reduced, and any ``cleanup''
+-action associated with it performed.
+-.PP
+-Another form of error rule arises in interactive applications, where
+-it may be desirable to permit a line to be reentered after an error.
+-A possible error rule might be
+-.DS
+-input :       error  \'\en\'  {  printf( "Reenter last line: " );  }  input
+-                      {       $$  =  $4;  }
+-.DE
+-There is one potential difficulty with this approach;
+-the parser must correctly process three input tokens before it
+-admits that it has correctly resynchronized after the error.
+-If the reentered line contains an error
+-in the first two tokens, the parser deletes the offending tokens,
+-and gives no message; this is clearly unacceptable.
+-For this reason, there is a mechanism that
+-can be used to force the parser
+-to believe that an error has been fully recovered from.
+-The statement
+-.DS
+-yyerrok ;
+-.DE
+-in an action
+-resets the parser to its normal mode.
+-The last example is better written
+-.DS
+-input :       error  \'\en\'
+-                      {       yyerrok;
+-                              printf( "Reenter last line: " );   }
+-              input
+-                      {       $$  =  $4;  }
+-      ;
+-.DE
+-.PP
+-As mentioned above, the token seen immediately
+-after the ``error'' symbol is the input token at which the
+-error was discovered.
+-Sometimes, this is inappropriate; for example, an
+-error recovery action might
+-take upon itself the job of finding the correct place to resume input.
+-In this case,
+-the previous lookahead token must be cleared.
+-The statement
+-.DS
+-yyclearin ;
+-.DE
+-in an action will have this effect.
+-For example, suppose the action after error
+-were to call some sophisticated resynchronization routine,
+-supplied by the user, that attempted to advance the input to the
+-beginning of the next valid statement.
+-After this routine was called, the next token returned by yylex would presumably
+-be the first token in a legal statement;
+-the old, illegal token must be discarded, and the error state reset.
+-This could be done by a rule like
+-.DS
+-stat  :       error 
+-                      {       resynch();
+-                              yyerrok ;
+-                              yyclearin ;   }
+-      ;
+-.DE
+-.PP
+-These mechanisms are admittedly crude, but do allow for a simple, fairly effective recovery of the parser
+-from many errors;
+-moreover, the user can get control to deal with
+-the error actions required by other portions of the program.
+//GO.SYSIN DD ss7
+echo ss8
+sed 's/.//' >ss8 <<'//GO.SYSIN DD ss8'
+-.SH
+-8: The Yacc Environment
+-.PP
+-When the user inputs a specification
+-to Yacc, the output is a file of C programs, called
+-.I y.tab.c
+-on most
+-systems
+-(due to local file system conventions, the names may differ from
+-installation to installation).
+-The function produced by Yacc is called
+-.I yyparse \|;
+-it is an integer valued function.
+-When it is called, it in turn repeatedly calls
+-.I yylex ,
+-the lexical analyzer
+-supplied by the user (see Section 3)
+-to obtain input tokens.
+-Eventually, either an error is detected, in which case
+-(if no error recovery is possible)
+-.I yyparse
+-returns the value 1,
+-or the lexical analyzer returns the endmarker token
+-and the parser accepts.
+-In this case,
+-.I yyparse
+-returns the value 0.
+-.PP
+-The user must provide a certain amount of environment for this
+-parser in order to obtain a working program.
+-For example, as with every C program, a program called
+-.I main
+-must be defined, that eventually calls
+-.I yyparse .
+-In addition, a routine called
+-.I yyerror
+-prints a message
+-when a syntax error is detected.
+-.PP
+-These two routines must be supplied in one form or another by the
+-user.
+-To ease the initial effort of using Yacc, a library has been
+-provided with default versions of
+-.I main
+-and
+-.I yyerror .
+-The name of this library is system dependent;
+-on many systems the library is accessed by a
+-.B \-ly
+-argument to the loader.
+-To show the triviality of these default programs, the source is
+-given below:
+-.DS
+-main(){
+-      return( yyparse() );
+-      }
+-.DE
+-and
+-.DS
+-# include <stdio.h>
+-
+-yyerror(s) char *s; {
+-      fprintf( stderr, "%s\en", s );
+-      }
+-.DE
+-The argument to
+-.I yyerror
+-is a string containing an error message, usually
+-the string ``syntax error''.
+-The average application will want to do better than this.
+-Ordinarily, the program should keep track of the input line number, and print it
+-along with the message when a syntax error is detected.
+-The external integer variable
+-.I yychar
+-contains the lookahead token number at the time the error was detected;
+-this may be of some interest in giving better diagnostics.
+-Since the
+-.I main
+-program is probably supplied by the user (to read arguments, etc.)
+-the Yacc library is useful only in small
+-projects, or in the earliest stages of larger ones.
+-.PP
+-The external integer variable
+-.I yydebug
+-is normally set to 0.
+-If it is set to a nonzero value, the parser will output a
+-verbose description of its actions, including
+-a discussion of which input symbols have been read, and
+-what the parser actions are.
+-Depending on the operating environment,
+-it may be possible to set this variable by using a debugging system.
+//GO.SYSIN DD ss8
+echo ss9
+sed 's/.//' >ss9 <<'//GO.SYSIN DD ss9'
+-.SH
+-9: Hints for Preparing Specifications
+-.PP
+-This section contains miscellaneous hints on preparing efficient, easy to change,
+-and clear specifications.
+-The individual subsections are more or less
+-independent.
+-.SH
+-Input Style
+-.PP
+-It is difficult to
+-provide rules with substantial actions
+-and still have a readable specification file.
+-The following style hints owe much to Brian Kernighan.
+-.IP a.
+-Use all capital letters for token names, all lower case letters for
+-nonterminal names.
+-This rule comes under the heading of ``knowing who to blame when
+-things go wrong.''
+-.IP b.
+-Put grammar rules and actions on separate lines.
+-This allows either to be changed without
+-an automatic need to change the other.
+-.IP c.
+-Put all rules with the same left hand side together.
+-Put the left hand side in only once, and let all
+-following rules begin with a vertical bar.
+-.IP d.
+-Put a semicolon only after the last rule with a given left hand side,
+-and put the semicolon on a separate line.
+-This allows new rules to be easily added.
+-.IP e.
+-Indent rule bodies by two tab stops, and action bodies by three
+-tab stops.
+-.PP
+-The example in Appendix A is written following this style, as are
+-the examples in the text of this paper (where space permits).
+-The user must make up his own mind about these stylistic questions;
+-the central problem, however, is to make the rules visible through
+-the morass of action code.
+-.SH
+-Left Recursion
+-.PP
+-The algorithm used by the Yacc parser encourages so called ``left recursive''
+-grammar rules: rules of the form
+-.DS
+-name  :       name  rest_of_rule  ;
+-.DE
+-These rules frequently arise when
+-writing specifications of sequences and lists:
+-.DS
+-list  :       item
+-      |       list  \',\'  item
+-      ;
+-.DE
+-and
+-.DS
+-seq   :       item
+-      |       seq  item
+-      ;
+-.DE
+-In each of these cases, the first rule
+-will be reduced for the first item only, and the second rule
+-will be reduced for the second and all succeeding items.
+-.PP
+-With right recursive rules, such as
+-.DS
+-seq   :       item
+-      |       item  seq
+-      ;
+-.DE
+-the parser would be a bit bigger, and the items would be seen, and reduced,
+-from right to left.
+-More seriously, an internal stack in the parser
+-would be in danger of overflowing if a very long sequence were read.
+-Thus, the user should use left recursion wherever reasonable.
+-.PP
+-It is worth considering whether a sequence with zero
+-elements has any meaning, and if so, consider writing
+-the sequence specification with an empty rule:
+-.DS
+-seq   :       /* empty */
+-      |       seq  item
+-      ;
+-.DE
+-Once again, the first rule would always be reduced exactly once, before the
+-first item was read,
+-and then the second rule would be reduced once for each item read.
+-Permitting empty sequences
+-often leads to increased generality.
+-However, conflicts might arise if Yacc is asked to decide
+-which empty sequence it has seen, when it hasn't seen enough to
+-know!
+-.SH
+-Lexical Tie-ins
+-.PP
+-Some lexical decisions depend on context.
+-For example, the lexical analyzer might want to
+-delete blanks normally, but not within quoted strings.
+-Or names might be entered into a symbol table in declarations,
+-but not in expressions.
+-.PP
+-One way of handling this situation is
+-to create a global flag that is
+-examined by the lexical analyzer, and set by actions.
+-For example, suppose a program
+-consists of 0 or more declarations, followed by 0 or more statements.
+-Consider:
+-.DS
+-%{
+-      int dflag;
+-%}
+-  ...  other declarations ...
+-
+-%%
+-
+-prog  :       decls  stats
+-      ;
+-
+-decls :       /* empty */
+-                      {       dflag = 1;  }
+-      |       decls  declaration
+-      ;
+-
+-stats :       /* empty */
+-                      {       dflag = 0;  }
+-      |       stats  statement
+-      ;
+-
+-    ...  other rules ...
+-.DE
+-The flag
+-.I dflag
+-is now 0 when reading statements, and 1 when reading declarations,
+-.ul
+-except for the first token in the first statement.
+-This token must be seen by the parser before it can tell that
+-the declaration section has ended and the statements have
+-begun.
+-In many cases, this single token exception does not
+-affect the lexical scan.
+-.PP
+-This kind of ``backdoor'' approach can be elaborated
+-to a noxious degree.
+-Nevertheless, it represents a way of doing some things
+-that are difficult, if not impossible, to
+-do otherwise.
+-.SH
+-Reserved Words
+-.PP
+-Some programming languages
+-permit the user to
+-use words like ``if'', which are normally reserved,
+-as label or variable names, provided that such use does not
+-conflict with the legal use of these names in the programming language.
+-This is extremely hard to do in the framework of Yacc;
+-it is difficult to pass information to the lexical analyzer
+-telling it ``this instance of `if' is a keyword, and that instance is a variable''.
+-The user can make a stab at it, using the
+-mechanism described in the last subsection,
+-but it is difficult.
+-.PP
+-A number of ways of making this easier are under advisement.
+-Until then, it is better that the keywords be
+-.I reserved \|;
+-that is, be forbidden for use as variable names.
+-There are powerful stylistic reasons for preferring this, anyway.
+//GO.SYSIN DD ss9
+echo ssA
+sed 's/.//' >ssA <<'//GO.SYSIN DD ssA'
+-.SH
+-10: Advanced Topics
+-.PP
+-This section discusses a number of advanced features
+-of Yacc.
+-.SH
+-Simulating Error and Accept in Actions
+-.PP
+-The parsing actions of error and accept can be simulated
+-in an action by use of macros YYACCEPT and YYERROR.
+-YYACCEPT causes
+-.I yyparse
+-to return the value 0;
+-YYERROR causes
+-the parser to behave as if the current input symbol
+-had been a syntax error;
+-.I yyerror
+-is called, and error recovery takes place.
+-These mechanisms can be used to simulate parsers
+-with multiple endmarkers or context-sensitive syntax checking.
+-.SH
+-Accessing Values in Enclosing Rules.
+-.PP
+-An action may refer to values
+-returned by actions to the left of the current rule.
+-The mechanism is simply the same as with ordinary actions,
+-a dollar sign followed by a digit, but in this case the
+-digit may be 0 or negative.
+-Consider
+-.DS
+-sent  :       adj  noun  verb  adj  noun
+-                      {  \fIlook at the sentence\fR . . .  }
+-      ;
+-
+-adj   :       THE             {       $$ = THE;  }
+-      |       YOUNG   {       $$ = YOUNG;  }
+-      . . .
+-      ;
+-
+-noun  :       DOG
+-                      {       $$ = DOG;  }
+-      |       CRONE
+-                      {       if( $0 == YOUNG ){
+-                                      printf( "what?\en" );
+-                                      }
+-                              $$ = CRONE;
+-                              }
+-      ;
+-      . . .
+-.DE
+-In the action following the word CRONE, a check is made that the
+-preceding token shifted was not YOUNG.
+-Obviously, this is only possible when a great deal is known about
+-what might precede the symbol
+-.I noun
+-in the input.
+-There is also a distinctly unstructured flavor about this.
+-Nevertheless, at times this mechanism will save a great
+-deal of trouble, especially when a few combinations are to
+-be excluded from an otherwise regular structure.
+-.SH
+-Support for Arbitrary Value Types
+-.PP
+-By default, the values returned by actions and the lexical analyzer are integers.
+-Yacc can also support
+-values of other types, including structures.
+-In addition, Yacc keeps track of the types, and inserts
+-appropriate union member names so that the resulting parser will
+-be strictly type checked.
+-The Yacc value stack (see Section 4)
+-is declared to be a
+-.I union
+-of the various types of values desired.
+-The user declares the union, and associates union member names
+-to each token and nonterminal symbol having a value.
+-When the value is referenced through a $$ or $n construction,
+-Yacc will automatically insert the appropriate union name, so that
+-no unwanted conversions will take place.
+-In addition, type checking commands such as
+-.I Lint\|
+-.[
+-Johnson Lint Checker 1273
+-.]
+-will be far more silent.
+-.PP
+-There are three mechanisms used to provide for this typing.
+-First, there is a way of defining the union; this must be
+-done by the user since other programs, notably the lexical analyzer,
+-must know about the union member names.
+-Second, there is a way of associating a union member name with tokens
+-and nonterminals.
+-Finally, there is a mechanism for describing the type of those
+-few values where Yacc can not easily determine the type.
+-.PP
+-To declare the union, the user includes in the declaration section:
+-.DS
+-%union  {
+-      body of union ...
+-      }
+-.DE
+-This declares the Yacc value stack,
+-and the external variables
+-.I yylval
+-and
+-.I yyval ,
+-to have type equal to this union.
+-If Yacc was invoked with the
+-.B \-d
+-option, the union declaration
+-is copied onto the
+-.I y.tab.h
+-file.
+-Alternatively,
+-the union may be declared in a header file, and a typedef
+-used to define the variable YYSTYPE to represent
+-this union.
+-Thus, the header file might also have said:
+-.DS
+-typedef union {
+-      body of union ...
+-      } YYSTYPE;
+-.DE
+-The header file must be included in the declarations
+-section, by use of %{ and %}.
+-.PP
+-Once YYSTYPE is defined,
+-the union member names must be associated
+-with the various terminal and nonterminal names.
+-The construction
+-.DS
+-< name >
+-.DE
+-is used to indicate a union member name.
+-If this follows
+-one of the
+-keywords %token,
+-%left, %right, and %nonassoc,
+-the union member name is associated with the tokens listed.
+-Thus, saying
+-.DS
+-%left  <optype>  \'+\'  \'\-\'
+-.DE
+-will cause any reference to values returned by these two tokens to be
+-tagged with
+-the union member name
+-.I optype .
+-Another keyword, %type, is
+-used similarly to associate
+-union member names with nonterminals.
+-Thus, one might say
+-.DS
+-%type  <nodetype>  expr  stat
+-.DE
+-.PP
+-There remain a couple of cases where these mechanisms are insufficient.
+-If there is an action within a rule, the value returned
+-by this action has no
+-.I "a priori"
+-type.
+-Similarly, reference to left context values (such as $0 \- see the
+-previous subsection ) leaves Yacc with no easy way of knowing the type.
+-In this case, a type can be imposed on the reference by inserting
+-a union member name, between < and >, immediately after
+-the first $.
+-An example of this usage is
+-.DS
+-rule  :       aaa  {  $<intval>$  =  3;  } bbb
+-                      {       fun( $<intval>2, $<other>0 );  }
+-      ;
+-.DE
+-This syntax has little to recommend it, but the situation arises rarely.
+-.PP
+-A sample specification is given in Appendix C.
+-The facilities in this subsection are not triggered until they are used:
+-in particular, the use of %type will turn on these mechanisms.
+-When they are used, there is a fairly strict level of checking.
+-For example, use of $n or $$ to refer to something with no defined type
+-is diagnosed.
+-If these facilities are not triggered, the Yacc value stack is used to
+-hold
+-.I int' s,
+-as was true historically.
+//GO.SYSIN DD ssA
+echo ssB
+sed 's/.//' >ssB <<'//GO.SYSIN DD ssB'
+-.SH
+-11: Acknowledgements
+-.PP
+-Yacc owes much to a
+-most stimulating collection of users, who have goaded
+-me beyond my inclination, and frequently beyond my
+-ability, in their endless search for ``one more feature''.
+-Their irritating unwillingness to learn how to
+-do things my way has usually led to my doing things their way;
+-most of the time, they have been right.
+-B. W. Kernighan, P. J. Plauger, S. I. Feldman, C. Imagna,
+-M. E. Lesk,
+-and A. Snyder will recognize some of their ideas in the current version
+-of Yacc.
+-C. B. Haley contributed to the error recovery algorithm.
+-D. M. Ritchie, B. W. Kernighan, and M. O. Harris helped translate this document into English.
+-Al Aho also deserves special credit for bringing
+-the mountain to Mohammed, and other favors.
+-.SG "MH-1273-SCJ-unix"
+-.bp
+-.[
+-$LIST$
+-.]
+-.bp
+//GO.SYSIN DD ssB
+echo ssa
+sed 's/.//' >ssa <<'//GO.SYSIN DD ssa'
+-.SH
+-Appendix A:  A Simple Example
+-.PP
+-This example gives the complete Yacc specification for a small desk calculator;
+-the desk calculator has 26 registers, labeled ``a'' through ``z'', and accepts
+-arithmetic expressions made up of the operators +, \-, *, /,
+-% (mod operator), & (bitwise and), | (bitwise or), and assignment.
+-If an expression at the top level is an assignment, the value is not
+-printed; otherwise it is.
+-As in C, an integer that begins with 0 (zero) is assumed to be octal;
+-otherwise, it is assumed to be decimal.
+-.PP
+-As an example of a Yacc specification, the desk calculator
+-does a reasonable job of showing how precedences and ambiguities
+-are used, and demonstrating simple error recovery.
+-The major oversimplifications are that the
+-lexical analysis phase is much simpler than for most applications, and the
+-output is produced immediately, line by line.
+-Note the way that decimal and octal integers are read in by the grammar rules;
+-This job is probably better done by the lexical analyzer.
+-.sp
+-.nf
+-.ta .5i 1i 1.5i 2i 2.5i
+-
+-%{
+-#  include  <stdio.h>
+-#  include  <ctype.h>
+-
+-int  regs[26];
+-int  base;
+-
+-%}
+-
+-%start  list
+-
+-%token  DIGIT  LETTER
+-
+-%left  \'|\'
+-%left  \'&\'
+-%left  \'+\'  \'\-\'
+-%left  \'*\'  \'/\'  \'%\'
+-%left  UMINUS      /*  supplies  precedence  for  unary  minus  */
+-
+-%%      /*  beginning  of  rules  section  */
+-
+-list  :       /*  empty  */
+-      |       list  stat  \'\en\'
+-      |       list  error  \'\en\'
+-                      {       yyerrok;  }
+-      ;
+-
+-stat  :       expr
+-                      {       printf( "%d\en", $1 );  }
+-      |       LETTER  \'=\'  expr
+-                      {       regs[$1]  =  $3;  }
+-      ;
+-
+-expr  :       \'(\'  expr  \')\'
+-                      {       $$  =  $2;  }
+-      |       expr  \'+\'  expr
+-                      {       $$  =  $1  +  $3;  }
+-      |       expr  \'\-\'  expr
+-                      {       $$  =  $1  \-  $3;  }
+-      |       expr  \'*\'  expr
+-                      {       $$  =  $1  *  $3;  }
+-      |       expr  \'/\'  expr
+-                      {       $$  =  $1  /  $3;  }
+-      |       expr  \'%\'  expr
+-                      {       $$  =  $1  %  $3;  }
+-      |       expr  \'&\'  expr
+-                      {       $$  =  $1  &  $3;  }
+-      |       expr  \'|\'  expr
+-                      {       $$  =  $1  |  $3;  }
+-      |       \'\-\'  expr        %prec  UMINUS
+-                      {       $$  =  \-  $2;  }
+-      |       LETTER
+-                      {       $$  =  regs[$1];  }
+-      |       number          
+-      ;
+-
+-number        :       DIGIT
+-                      {       $$ = $1;    base  =  ($1==0)  ?  8  :  10;  }
+-      |       number  DIGIT
+-                      {       $$  =  base * $1  +  $2;  }
+-      ;
+-
+-%%      /*  start  of  programs  */
+-
+-yylex() {             /*  lexical  analysis  routine  */
+-              /*  returns  LETTER  for  a  lower  case  letter,  yylval = 0  through  25  */
+-              /*  return  DIGIT  for  a  digit,  yylval = 0  through  9  */
+-              /*  all  other  characters  are  returned  immediately  */
+-
+-      int  c;
+-
+-      while(  (c=getchar())  ==  \' \'  )  {  /*  skip  blanks  */  }
+-
+-      /*  c  is  now  nonblank  */
+-
+-      if(  islower(  c  )  )  {       
+-              yylval  =  c  \-  \'a\';
+-              return  (  LETTER  );
+-              }
+-      if(  isdigit(  c  )  )  {       
+-              yylval  =  c  \-  \'0\';
+-              return(  DIGIT  );
+-              }
+-      return(  c  );
+-      }
+-.fi
+-.bp
+//GO.SYSIN DD ssa
+echo ssb
+sed 's/.//' >ssb <<'//GO.SYSIN DD ssb'
+-.SH
+-Appendix B: Yacc Input Syntax
+-.PP
+-This Appendix has a description of the Yacc input syntax, as a Yacc specification.
+-Context dependencies, etc., are not considered.
+-Ironically, the Yacc input specification language
+-is most naturally specified as an LR(2) grammar; the sticky
+-part comes when an identifier is seen in a rule, immediately
+-following an action.
+-If this identifier is followed by a colon, it is the start of the
+-next rule; otherwise
+-it is a continuation of the current rule, which just happens to have
+-an action embedded in it.
+-As implemented, the lexical analyzer looks
+-ahead after seeing an identifier, and
+-decide whether the next token (skipping blanks, newlines, comments, etc.)
+-is a colon.
+-If so, it returns the token C_IDENTIFIER.
+-Otherwise, it returns IDENTIFIER.
+-Literals (quoted strings) are also returned as IDENTIFIERS,
+-but never as part of C_IDENTIFIERs.
+-.sp
+-.nf
+-.ta .6i 1.2i 1.8i 2.4i 3i 3.6i
+-
+-            /*  grammar  for  the  input  to  Yacc  */
+-
+-      /*  basic  entities  */
+-%token        IDENTIFIER      /*   includes  identifiers   and  literals  */
+-%token        C_IDENTIFIER    /*    identifier  (but  not  literal)  followed  by  colon    */
+-%token        NUMBER          /*    [0-9]+    */
+-
+-      /*  reserved  words:    %type  =>  TYPE,  %left  =>  LEFT,  etc.  */
+-
+-%token        LEFT  RIGHT  NONASSOC  TOKEN  PREC  TYPE  START  UNION
+-
+-%token        MARK    /*  the  %%  mark  */
+-%token        LCURL   /*  the  %{  mark  */
+-%token        RCURL   /*  the  %}  mark  */
+-
+-      /*  ascii  character  literals  stand  for  themselves  */
+-
+-%start        spec
+-
+-%%
+-
+-spec  :       defs  MARK  rules  tail
+-      ;
+-
+-tail  :       MARK    {    \fIIn  this  action,  eat  up  the  rest  of  the  file\fR    }
+-      |       /*  empty:  the  second  MARK  is  optional  */
+-      ;
+-
+-defs  :       /*  empty  */
+-      |       defs  def
+-      ;
+-
+-def   :       START  IDENTIFIER
+-      |       UNION  {  \fICopy union  definition  to  output\fR  }
+-      |       LCURL  {  \fICopy  C  code  to  output  file\fR   }  RCURL
+-      |       ndefs  rword  tag  nlist
+-      ;
+-
+-rword :       TOKEN
+-      |       LEFT
+-      |       RIGHT
+-      |       NONASSOC
+-      |       TYPE
+-      ;
+-
+-tag   :       /*  empty:  union  tag  is  optional  */
+-      |       \'<\'  IDENTIFIER  \'>\'
+-      ;
+-
+-nlist :       nmno
+-      |       nlist  nmno
+-      |       nlist  \',\'  nmno
+-      ;
+-
+-nmno  :       IDENTIFIER              /*  NOTE:  literal  illegal  with  %type  */
+-      |       IDENTIFIER  NUMBER      /*  NOTE:  illegal  with  %type  */
+-      ;
+-
+-      /*  rules  section  */
+-
+-rules :       C_IDENTIFIER  rbody  prec
+-      |       rules  rule
+-      ;
+-
+-rule  :       C_IDENTIFIER  rbody  prec
+-      |       '|'  rbody  prec
+-      ;
+-
+-rbody :       /*  empty  */
+-      |       rbody  IDENTIFIER
+-      |       rbody  act
+-      ;
+-
+-act   :       \'{\'  {  \fICopy  action,  translate  $$,  etc.\fR  }  \'}\'
+-      ;
+-
+-prec  :       /*  empty  */
+-      |       PREC  IDENTIFIER
+-      |       PREC  IDENTIFIER  act
+-      |       prec  \';\'
+-      ;
+-.fi
+-.bp
+//GO.SYSIN DD ssb
+echo ssc
+sed 's/.//' >ssc <<'//GO.SYSIN DD ssc'
+-.SH
+-Appendix C: An Advanced Example
+-.PP
+-This Appendix gives an example of a grammar using some
+-of the advanced features discussed in Section 10.
+-The desk calculator example in Appendix A is
+-modified to provide a desk calculator that
+-does floating point interval arithmetic.
+-The calculator understands floating point
+-constants, the arithmetic operations +, \-, *, /,
+-unary \-, and = (assignment), and has 26 floating
+-point variables, ``a'' through ``z''.
+-Moreover, it also understands
+-.I intervals ,
+-written
+-.DS
+-      ( x , y )
+-.DE
+-where
+-.I x
+-is less than or equal to
+-.I y .
+-There are 26 interval valued variables ``A'' through ``Z''
+-that may also be used.
+-The usage is similar to that in Appendix A; assignments
+-return no value, and print nothing, while expressions print
+-the (floating or interval) value.
+-.PP
+-This example explores a number of interesting features
+-of Yacc and C.
+-Intervals are represented by a structure, consisting of the
+-left and right endpoint values, stored as
+-.I double 's.
+-This structure is given a type name, INTERVAL, by using
+-.I typedef .
+-The Yacc value stack can also contain floating point scalars, and
+-integers (used to index into the arrays holding the variable values).
+-Notice that this entire strategy depends strongly on being able to
+-assign structures and unions in C.
+-In fact, many of the actions call functions that return structures
+-as well.
+-.PP
+-It is also worth noting the use of YYERROR to handle error conditions:
+-division by an interval containing 0, and an interval presented in
+-the wrong order.
+-In effect, the error recovery mechanism of Yacc is used to throw away the
+-rest of the offending line.
+-.PP
+-In addition to the mixing of types on the value stack,
+-this grammar also demonstrates an interesting use of syntax to
+-keep track of the type (e.g. scalar or interval) of intermediate
+-expressions.
+-Note that a scalar can be automatically promoted to an interval if
+-the context demands an interval value.
+-This causes a large number of conflicts when the grammar is run through
+-Yacc: 18 Shift/Reduce and 26 Reduce/Reduce.
+-The problem can be seen by looking at the two input lines:
+-.DS
+-      2.5 + ( 3.5 \- 4. )
+-.DE
+-and
+-.DS
+-      2.5 + ( 3.5 , 4. )
+-.DE
+-Notice that the 2.5 is to be used in an interval valued expression
+-in the second example, but this fact is not known until
+-the ``,'' is read; by this time, 2.5 is finished, and the parser cannot go back
+-and change its mind.
+-More generally, it might be necessary to look ahead an arbitrary number of
+-tokens to decide whether to convert a scalar to an interval.
+-This problem is evaded by having two rules for each binary interval
+-valued operator: one when the left operand is a scalar, and one when
+-the left operand is an interval.
+-In the second case, the right operand must be an interval,
+-so the conversion will be applied automatically.
+-Despite this evasion, there are still many cases where the
+-conversion may be applied or not, leading to the above
+-conflicts.
+-They are resolved by listing the rules that yield scalars first
+-in the specification file; in this way, the conflicts will
+-be resolved in the direction of keeping scalar
+-valued expressions scalar valued until they are forced to become
+-intervals.
+-.PP
+-This way of handling multiple types is very instructive, but not very general.
+-If there were many kinds of expression types, instead of just two,
+-the number of rules needed would increase dramatically, and the conflicts
+-even more dramatically.
+-Thus, while this example is instructive, it is better practice in a
+-more normal programming language environment to
+-keep the type information as part of the value, and not as part
+-of the grammar.
+-.PP
+-Finally, a word about the lexical analysis.
+-The only unusual feature is the treatment of floating point constants.
+-The C library routine
+-.I atof
+-is used to do the actual conversion from a character string
+-to a double precision value.
+-If the lexical analyzer detects an error,
+-it responds by returning a token that
+-is illegal in the grammar, provoking a syntax error
+-in the parser, and thence error recovery.
+-.DS L
+-
+-%{
+-
+-#  include  <stdio.h>
+-#  include  <ctype.h>
+-
+-typedef  struct  interval  {
+-      double  lo,  hi;
+-      }  INTERVAL;
+-
+-INTERVAL  vmul(),  vdiv();
+-
+-double  atof();
+-
+-double  dreg[ 26 ];
+-INTERVAL  vreg[ 26 ];
+-
+-%}
+-
+-%start    lines
+-
+-%union    {
+-      int  ival;
+-      double  dval;
+-      INTERVAL  vval;
+-      }
+-
+-%token  <ival>  DREG  VREG    /*  indices  into  dreg,  vreg  arrays  */
+-
+-%token  <dval>  CONST         /*  floating  point  constant  */
+-
+-%type  <dval>  dexp           /*  expression  */
+-
+-%type  <vval>  vexp           /*  interval  expression  */
+-
+-      /*  precedence  information  about  the  operators  */
+-
+-%left \'+\'  \'\-\'
+-%left \'*\'  \'/\'
+-%left UMINUS        /*  precedence  for  unary  minus  */
+-
+-%%
+-
+-lines :       /*  empty  */
+-      |       lines  line
+-      ;
+-
+-line  :       dexp  \'\en\'
+-                      {       printf(  "%15.8f\en",  $1  );  }
+-      |       vexp  \'\en\'
+-                      {       printf(  "(%15.8f  ,  %15.8f  )\en",  $1.lo,  $1.hi  );  }
+-      |       DREG  \'=\'  dexp  \'\en\'
+-                      {       dreg[$1]  =  $3;  }
+-      |       VREG  \'=\'  vexp  \'\en\'
+-                      {       vreg[$1]  =  $3;  }
+-      |       error  \'\en\'
+-                      {       yyerrok;  }
+-      ;
+-
+-dexp  :       CONST
+-      |       DREG
+-                      {       $$  =  dreg[$1];  }
+-      |       dexp  \'+\'  dexp
+-                      {       $$  =  $1  +  $3;  }
+-      |       dexp  \'\-\'  dexp
+-                      {       $$  =  $1  \-  $3;  }
+-      |       dexp  \'*\'  dexp
+-                      {       $$  =  $1  *  $3;  }
+-      |       dexp  \'/\'  dexp
+-                      {       $$  =  $1  /  $3;  }
+-      |       \'\-\'  dexp    %prec  UMINUS
+-                      {       $$  =  \- $2;  }
+-      |       \'(\'  dexp  \')\'
+-                      {       $$  =  $2;  }
+-      ;
+-
+-vexp  :       dexp
+-                      {       $$.hi  =  $$.lo  =  $1;  }
+-      |       \'(\'  dexp  \',\'  dexp  \')\'
+-                      {
+-                      $$.lo  =  $2;
+-                      $$.hi  =  $4;
+-                      if(  $$.lo  >  $$.hi  ){
+-                              printf(  "interval  out  of  order\en"  );
+-                              YYERROR;
+-                              }
+-                      }
+-      |       VREG
+-                      {       $$  =  vreg[$1];    }
+-      |       vexp  \'+\'  vexp
+-                      {       $$.hi  =  $1.hi  +  $3.hi;
+-                              $$.lo  =  $1.lo  +  $3.lo;    }
+-      |       dexp  \'+\'  vexp
+-                      {       $$.hi  =  $1  +  $3.hi;
+-                              $$.lo  =  $1  +  $3.lo;    }
+-      |       vexp  \'\-\'  vexp
+-                      {       $$.hi  =  $1.hi  \-  $3.lo;
+-                              $$.lo  =  $1.lo  \-  $3.hi;    }
+-      |       dexp  \'\-\'  vexp
+-                      {       $$.hi  =  $1  \-  $3.lo;
+-                              $$.lo  =  $1  \-  $3.hi;    }
+-      |       vexp  \'*\'  vexp
+-                      {       $$  =  vmul(  $1.lo,  $1.hi,  $3  );  }
+-      |       dexp  \'*\'  vexp
+-                      {       $$  =  vmul(  $1,  $1,  $3  );  }
+-      |       vexp  \'/\'  vexp
+-                      {       if(  dcheck(  $3  )  )  YYERROR;
+-                              $$  =  vdiv(  $1.lo,  $1.hi,  $3  );  }
+-      |       dexp  \'/\'  vexp
+-                      {       if(  dcheck(  $3  )  )  YYERROR;
+-                              $$  =  vdiv(  $1,  $1,  $3  );  }
+-      |       \'\-\'  vexp    %prec  UMINUS
+-                      {       $$.hi  =  \-$2.lo;    $$.lo  =  \-$2.hi;    }
+-      |       \'(\'  vexp  \')\'
+-                      {       $$  =  $2;  }
+-      ;
+-
+-%%
+-
+-#  define  BSZ  50        /*  buffer  size  for  floating  point  numbers  */
+-
+-      /*  lexical  analysis  */
+-
+-yylex(){
+-      register  c;
+-
+-      while(  (c=getchar())  ==  \' \'  ){  /*  skip  over  blanks  */  }
+-
+-      if(  isupper(  c  )  ){
+-              yylval.ival  =  c  \-  \'A\';
+-              return(  VREG  );
+-              }
+-      if(  islower(  c  )  ){
+-              yylval.ival  =  c  \-  \'a\';
+-              return(  DREG  );
+-              }
+-
+-      if(  isdigit(  c  )  ||  c==\'.\'  ){
+-              /*  gobble  up  digits,  points,  exponents  */
+-
+-              char  buf[BSZ+1],  *cp  =  buf;
+-              int  dot  =  0,  exp  =  0;
+-
+-              for(  ;  (cp\-buf)<BSZ  ;  ++cp,c=getchar()  ){
+-
+-                      *cp  =  c;
+-                      if(  isdigit(  c  )  )  continue;
+-                      if(  c  ==  \'.\'  ){
+-                              if(  dot++  ||  exp  )  return(  \'.\'  );    /*  will  cause  syntax  error  */
+-                              continue;
+-                              }
+-
+-                      if(  c  ==  \'e\'  ){
+-                              if(  exp++  )  return(  \'e\'  );    /*  will  cause  syntax  error  */
+-                              continue;
+-                              }
+-
+-                      /*  end  of  number  */
+-                      break;
+-                      }
+-              *cp  =  \'\e0\';
+-              if(  (cp\-buf)  >=  BSZ  )  printf(  "constant  too  long:  truncated\en"  );
+-              else  ungetc(  c,  stdin  );    /*  push  back  last  char  read  */
+-              yylval.dval  =  atof(  buf  );
+-              return(  CONST  );
+-              }
+-      return(  c  );
+-      }
+-
+-INTERVAL  hilo(  a,  b,  c,  d  )  double  a,  b,  c,  d;  {
+-      /*  returns  the  smallest  interval  containing  a,  b,  c,  and  d  */
+-      /*  used  by  *,  /  routines  */
+-      INTERVAL  v;
+-
+-      if(  a>b  )  {  v.hi  =  a;    v.lo  =  b;  }
+-      else  {  v.hi  =  b;    v.lo  =  a;  }
+-
+-      if(  c>d  )  {
+-              if(  c>v.hi  )  v.hi  =  c;
+-              if(  d<v.lo  )  v.lo  =  d;
+-              }
+-      else  {
+-              if(  d>v.hi  )  v.hi  =  d;
+-              if(  c<v.lo  )  v.lo  =  c;
+-              }
+-      return(  v  );
+-      }
+-
+-INTERVAL  vmul(  a,  b,  v  )  double  a,  b;    INTERVAL  v;  {
+-      return(  hilo(  a*v.hi,  a*v.lo,  b*v.hi,  b*v.lo  )  );
+-      }
+-
+-dcheck(  v  )  INTERVAL  v;  {
+-      if(  v.hi  >=  0.  &&  v.lo  <=  0.  ){
+-              printf(  "divisor  interval  contains  0.\en"  );
+-              return(  1  );
+-              }
+-      return(  0  );
+-      }
+-
+-INTERVAL  vdiv(  a,  b,  v  )  double  a,  b;    INTERVAL  v;  {
+-      return(  hilo(  a/v.hi,  a/v.lo,  b/v.hi,  b/v.lo  )  );
+-      }
+-.DE
+-.bp
+//GO.SYSIN DD ssc
+echo ssd
+sed 's/.//' >ssd <<'//GO.SYSIN DD ssd'
+-.SH
+-Appendix D: Old Features Supported but not Encouraged
+-.PP
+-This Appendix mentions synonyms and features which are supported for historical
+-continuity, but, for various reasons, are not encouraged.
+-.IP 1.
+-Literals may also be delimited by double quotes ``"''.
+-.IP 2.
+-Literals may be more than one character long.
+-If all the characters are alphabetic, numeric, or \_, the type number of the literal is defined,
+-just as if the literal did not have the quotes around it.
+-Otherwise, it is difficult to find the value for such literals.
+-.IP
+-The use of multi-character literals is likely to mislead those unfamiliar with
+-Yacc, since it suggests that Yacc is doing a job which must be actually done by the lexical analyzer.
+-.IP 3.
+-Most places where % is legal, backslash ``\e'' may be used.
+-In particular, \e\e is the same as %%, \eleft the same as %left, etc.
+-.IP 4.
+-There are a number of other synonyms:
+-.DS
+-%< is the same as %left
+-%> is the same as %right
+-%binary and %2 are the same as %nonassoc
+-%0 and %term are the same as %token
+-%= is the same as %prec
+-.DE
+-.IP 5.
+-Actions may also have the form
+-.DS
+-={ . . . }
+-.DE
+-and the curly braces can be dropped if the action is a
+-single C statement.
+-.IP 6.
+-C code between %{ and %} used to be permitted at the
+-head of the rules section, as well as in the
+-declaration section.
+//GO.SYSIN DD ssd
diff --git a/doc/tack/6500.html b/doc/tack/6500.html
new file mode 100644 (file)
index 0000000..5473ebd
--- /dev/null
@@ -0,0 +1,2168 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:16 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>A backend table for the 6500 microprocessor</title>
+</head>
+<body>
+
+<h1 align=center>A backend table for the 6500 microprocessor</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The MOS Technology MCS6500">2. The MOS Technology MCS6500</a><br>
+<a href="#3. The MCS6500 CPU programmable registers">3. The MCS6500 CPU programmable registers</a><br>
+<a href="#3.1. The accumulator A.">3.1. The accumulator A.</a><br>
+<a href="#3.2. The index register X.">3.2. The index register X.</a><br>
+<a href="#3.3. The index register Y.">3.3. The index register Y.</a><br>
+<a href="#3.4. The program counter PC">3.4. The program counter PC</a><br>
+<a href="#3.5. The stack pointer SP">3.5. The stack pointer SP</a><br>
+<a href="#3.6. The status register">3.6. The status register</a><br>
+<a href="#4. The MCS6500 memory layout.">4. The MCS6500 memory layout.</a><br>
+<a href="#4.1. Top page.">4.1. Top page.</a><br>
+<a href="#4.2. Zero page.">4.2. Zero page.</a><br>
+<a href="#4.3. The stack.">4.3. The stack.</a><br>
+<a href="#5. The memory adressing modes">5. The memory adressing modes</a><br>
+<a href="#5.1. direct addressing.">5.1. direct addressing.</a><br>
+<a href="#5.2. Base page, indexed addressing.">5.2. Base page, indexed addressing.</a><br>
+<a href="#5.3. Absolute indexed addressing.">5.3. Absolute indexed addressing.</a><br>
+<a href="#5.4. Indirect addressing.">5.4. Indirect addressing.</a><br>
+<a href="#5.4.1. Pre-indexed indirect addressing.">5.4.1. Pre-indexed indirect addressing.</a><br>
+<a href="#5.4.2. Post-indexed indirect addressing.">5.4.2. Post-indexed indirect addressing.</a><br>
+<a href="#6. What the CPU has and doesn&rsquo;t has.">6. What the CPU has and doesn&rsquo;t has.</a><br>
+<a href="#1. Description of the machine table.">1. Description of the machine table.</a><br>
+<a href="#1.1. Macro definitions.">1.1. Macro definitions.</a><br>
+<a href="#1.2. Constant definitions.">1.2. Constant definitions.</a><br>
+<a href="#2. Register definitions.">2. Register definitions.</a><br>
+<a href="#2.1. Token definitions">2.1. Token definitions</a><br>
+<a href="#2.2. Token expression definitions.">2.2. Token expression definitions.</a><br>
+<a href="#2.3. Code rules.">2.3. Code rules.</a><br>
+<a href="#2.3.1. The EM pattern.">2.3.1. The EM pattern.</a><br>
+<a href="#2.3.2. The stack pattern.">2.3.2. The stack pattern.</a><br>
+<a href="#2.3.3. The code part.">2.3.3. The code part.</a><br>
+<a href="#2.3.3.1. Stack cleanup.">2.3.3.1. Stack cleanup.</a><br>
+<a href="#2.3.3.2. Register allocation.">2.3.3.2. Register allocation.</a><br>
+<a href="#2.3.3.3. Code to be generated.">2.3.3.3. Code to be generated.</a><br>
+<a href="#2.3.4. stack replacement.">2.3.4. stack replacement.</a><br>
+<a href="#2.3.5. EM replacement.">2.3.5. EM replacement.</a><br>
+<a href="#2.3.6. Move definitions.">2.3.6. Move definitions.</a><br>
+<a href="#2.3.7. Test definitions.">2.3.7. Test definitions.</a><br>
+<a href="#2.3.8. Stack definitions.">2.3.8. Stack definitions.</a><br>
+<a href="#3. Some remarks.">3. Some remarks.</a><br>
+<a href="#1. Introduction.">1. Introduction.</a><br>
+<a href="#2. The instructions.">2. The instructions.</a><br>
+<a href="#2.1. The load instructions.">2.1. The load instructions.</a><br>
+<a href="#2.1.1. The lol instruction with indirect offsetting.">2.1.1. The lol instruction with indirect offsetting.</a><br>
+<a href="#2.1.2. The lol instruction whose offset is to big.">2.1.2. The lol instruction whose offset is to big.</a><br>
+<a href="#2.2. The store instructions.">2.2. The store instructions.</a><br>
+<a href="#2.2.1. The stl instruction with indirect offsetting.">2.2.1. The stl instruction with indirect offsetting.</a><br>
+<a href="#2.2.2. The stl instruction whose offset is to big.">2.2.2. The stl instruction whose offset is to big.</a><br>
+<a href="#2.3. Integer arithmetic instructions.">2.3. Integer arithmetic instructions.</a><br>
+<a href="#2.3.1. The adi instruction.">2.3.1. The adi instruction.</a><br>
+<a href="#2.3.2. The mli instruction.">2.3.2. The mli instruction.</a><br>
+<a href="#2.4. The unsgned arithmetic instructions.">2.4. The unsgned arithmetic instructions.</a><br>
+<a href="#2.4.1. Unsigned addition.">2.4.1. Unsigned addition.</a><br>
+<a href="#2.5. Floating point arithmetic.">2.5. Floating point arithmetic.</a><br>
+<a href="#2.6. Pointer arithmetic instructions.">2.6. Pointer arithmetic instructions.</a><br>
+<a href="#2.7. Increment, decrement and zero instructions.">2.7. Increment, decrement and zero instructions.</a><br>
+<a href="#2.8. Convert instructions.">2.8. Convert instructions.</a><br>
+<a href="#2.8.1. The in line conversion.">2.8.1. The in line conversion.</a><br>
+<a href="#2.9. Logical instructions.">2.9. Logical instructions.</a><br>
+<a href="#2.9.1. The logical and on 2-byte groups.">2.9.1. The logical and on 2-byte groups.</a><br>
+<a href="#2.10. Set manipulation instructions.">2.10. Set manipulation instructions.</a><br>
+<a href="#2.11. Array instructions.">2.11. Array instructions.</a><br>
+<a href="#2.12. Compare instructions.">2.12. Compare instructions.</a><br>
+<a href="#2.13. Branch instructions.">2.13. Branch instructions.</a><br>
+<a href="#2.14. Procedure call instructions.">2.14. Procedure call instructions.</a><br>
+<a href="#2.15. Miscellaneous instructions.">2.15. Miscellaneous instructions.</a><br>
+<a href="#1. Introduction.">1. Introduction.</a><br>
+<a href="#1. Testing Pascal statements.">1. Testing Pascal statements.</a><br>
+<a href="#2. The results.">2. The results.</a><br>
+<a href="#3. Pascal statements which don&rsquo;t have a C equivalent.">3. Pascal statements which don&rsquo;t have a C equivalent.</a><br>
+<a href="#4. Length tests.">4. Length tests.</a><br>
+<a href="#1. Summary">1. Summary</a><br>
+<a href="#1. REFERENCES.">1. REFERENCES.</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Jan van Dalen</i></p>
+
+<p>The backend table is part of the Amsterdam Compiler Kit
+(ACK). It translates the intermediate language family EM to
+a machine code for the MCS6500 microprocessor family.</p>
+
+<p align=center><b>THE MCS6500 MICROPROCESSOR.</b></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>Why a back end table for the MCS6500 microprocessor
+family. Although the MCS6500 microprocessor family has an
+simple instruction set and internal structure, it is used in
+a variety of microcomputers and homecomputers. This is
+because of is low cost. As an example the Apple II, a well
+known and width spread microprocessor, uses the MCS6502 CPU.
+Also the BBC homecomputer, whose popularity is growing day
+by day uses the MCS6502 CPU. The BBC homecomputer is based
+on the MCS6502 CPU although better and stronger
+microprocessors are available. The designers of Acorn
+computer Industries have probably choosen for the MCS6502
+because of the amount of software available for this CPU.
+Since its width spreaded use, a variaty of software will be
+needed for it. One can think of games!!, administration
+programs, teaching programs, basic interpreters and other
+application programs. Even do it will not be possible to run
+the total compiler kit on a MCS6500 based computer, it is
+possible to write application programs in a high level
+language, such as Pascal or C on a minicomputer. These
+application programs can be tested and compiled on that
+minicomputer and put in a ROM (Read Only Memory), for
+example, cso that it an be executed by a MCS6500 CPU. The
+strategy of writing testprograms on a minicomputer, compile
+it and then execute it on a MCS6500 based microprocessor is
+used by the development of the back end. The minicomputer
+used is M68000 based one, manufactured by Bleasdale Computer
+Systems Ltd.. The micro- or homecomputer used is a BBC
+microcomputer, manufactured by Acorn Computer Ltd..</p>
+<a name="2. The MOS Technology MCS6500"></a>
+<h2>2. The MOS Technology MCS6500</h2>
+
+<p>The MCS6500 is as a family of CPU devices developed by
+MOS Technology [1]. The members of the MCS6500 family are
+the same chips in a different housing. The MCS6502, the big
+brother in the family, can handle 64k bytes of memory, while
+for example the MCS6504 can only handle 8k bytes of memory.
+This difference is due to the fact that the MCS6502 is in a
+40 pins house and the MCS6504 has a 28 pins house, so less
+address lines are available.</p>
+<a name="3. The MCS6500 CPU programmable registers"></a>
+<h2>3. The MCS6500 CPU programmable registers</h2>
+
+<p>The MCS6500 series is based on the same chip so all have
+the same programmable registers.</p>
+<a name="3.1. The accumulator A."></a>
+<h2>3.1. The accumulator A.</h2>
+
+<p>The accumulator A is the only register on which the
+arithmetic and logical instructions can be used. For
+example, the instruction ADC (add with carry) adds the
+contents of the accumulator A and a byte from memory or
+data.</p>
+<a name="3.2. The index register X."></a>
+<h2>3.2. The index register X.</h2>
+
+<p>As the name suggests this register can be used for some
+indirect addressing modes. The modes are explaned below.</p>
+<a name="3.3. The index register Y."></a>
+<h2>3.3. The index register Y.</h2>
+
+<p>This register is, just as the index register X, used for
+certain indirect addressing modes. These addressing modes
+are different from the modes which use index register X.</p>
+<a name="3.4. The program counter PC"></a>
+<h2>3.4. The program counter PC</h2>
+
+<p>This is the only 16-bit register available. It is used
+to point to the next instruction to be carried out.</p>
+<a name="3.5. The stack pointer SP"></a>
+<h2>3.5. The stack pointer SP</h2>
+
+<p>The stack pointer is an 8-bit register, so the stack can
+contain at most 256 bytes. The CPU always appends 00000001
+as highbyte of any stack address, which means that memory
+locations <b>0100</b> through <b>01FF</b> are permanently
+assigned to the stack.</p>
+<a name="3.6. The status register"></a>
+<h2>3.6. The status register</h2>
+
+<p>The status register maintains six status flags and a
+master interrupt control bit.<br>
+These are the six status flags: Carry (c) Zero (z) Overflow
+(o) Sign (n) Decimal mode (d) Break (b)</p>
+
+<p>The bit (i) is the master interrupt control bit.</p>
+<a name="4. The MCS6500 memory layout."></a>
+<h2>4. The MCS6500 memory layout.</h2>
+
+<p>In the MCS6500 memory space three area&rsquo;s have
+special meaning. These area&rsquo;s are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="6%"></td>
+<td width="18%">
+
+<p>Top page.</p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>Zero page.</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>The stack.</p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p>MCS6500 memory is divided up into pages. These pages
+consist 256 bytes. So in a memory address the highbyte
+denotes the page number and the lowbyte the offset within
+the page.</p>
+<a name="4.1. Top page."></a>
+<h2>4.1. Top page.</h2>
+
+<p>When a MCS6500 is restared it jumps indirect via memory
+address <b>FFFC.</b> At <b>FFFC</b> (lowbyte) and
+<b>FFFD</b> (highbyte) there must be the address of the
+bootstrap subroutine. When a break instruction (BRK) occurs
+or an interrupt takes place, the MCS6500 jumps indirect
+through memory address <b>FFFE. FFFE</b> and <b>FFFF</b>
+thus, must contain the address of the interrupt routine. The
+former only goes for maskeble interrupt. There also exist a
+nonmaskeble interrupt. This cause the MCS6500 to jump
+indirect through memory address <b>FFFA.</b> So the top six
+bytes of memory are used by the operating system and
+therefore not available for the back end.</p>
+<a name="4.2. Zero page."></a>
+<h2>4.2. Zero page.</h2>
+
+<p>This page has a special meaning in the sence that
+addressing this page uses special opcodes. Since a page
+consists of 256 bytes, only one byte is needed for
+addressing zero page. So an instruction which uses zero page
+occupies two bytes. It also uses less clock cycle&rsquo;s
+while carrying out the instruction. Zero page is also needed
+when indirect addressing is used. This means that when
+indirect addressing is used, the address must reside in zero
+page (two consecutive bytes). In this case (the back end),
+zero page is used, for example to hold the local base, the
+second local base, the stack pointer etc.</p>
+<a name="4.3. The stack."></a>
+<h2>4.3. The stack.</h2>
+
+<p>The stack is described in paragraph 3.5 about the
+MCS6500 programmable registers.</p>
+<a name="5. The memory adressing modes"></a>
+<h2>5. The memory adressing modes</h2>
+
+<p>MCS6500 memory reference instructions use direct
+addressing, indexed addressing, and indirect addressing.</p>
+<a name="5.1. direct addressing."></a>
+<h2>5.1. direct addressing.</h2>
+
+<p>Three-byte instructions use the second and third bytes
+of the object code to provide a direct 16-bit address:
+therefore, 65.536 bytes of memory can be addressed directly.
+The commonly used memory reference instructions also have a
+two-byte object code variation, where the second byte
+directly addresses one of the first 256 bytes.</p>
+<a name="5.2. Base page, indexed addressing."></a>
+<h2>5.2. Base page, indexed addressing.</h2>
+
+<p>In this case, the instruction has two bytes of object
+code. The contents of either the X or Y index registers are
+added to the second object code byte in order to compute a
+memory address. This may be illustrated as follows:</p>
+
+<p>Base page, indexed addressing, as illustrated above, is
+wraparound - which means that there is no carry. If the sum
+of the index register and second object code byte contents
+is more than <b>FF</b> , the carry bit will be dicarded.
+This may be illustrated as follows:</p>
+<a name="5.3. Absolute indexed addressing."></a>
+<h2>5.3. Absolute indexed addressing.</h2>
+
+<p>In this case, the contents of either the X or Y register
+are added to a 16-bit direct address provided by the second
+and third bytes of an instruction&rsquo;s object code. This
+may be illustrated as follows:</p>
+<a name="5.4. Indirect addressing."></a>
+<h2>5.4. Indirect addressing.</h2>
+
+<p>Instructions that use simple indirect addressing have
+three bytes of object code. The second and third object code
+bytes provide a 16-bit address; therefore, the indirect
+address can be located anywhere in memory. This is
+straightforward indirect addressing.</p>
+<a name="5.4.1. Pre-indexed indirect addressing."></a>
+<h2>5.4.1. Pre-indexed indirect addressing.</h2>
+
+<p>In this case, the object code consists of two bytes and
+the second object code byte provides an 8-bit address.
+Instructions that use pre-indexed indirect addressing add
+the contents of the X index register and the second object
+code byte to access a memory location in the first 256 bytes
+of memory, where the indirect address will be found:</p>
+
+<p>When using pre-indexed indirect addressing, once again
+wraparound addition is used, which means that when the X
+index register contents are added to the second object code
+byte, any carry will be discarded. Note that only the X
+index register can be used with pre-indexed addressing.</p>
+<a name="5.4.2. Post-indexed indirect addressing."></a>
+<h2>5.4.2. Post-indexed indirect addressing.</h2>
+
+<p>In this case, the object code consists of two bytes and
+the second object code byte provides an 8-bit address. Now
+the second object code byte indentifies a location in the
+first 256 bytes of memory where an indirect address will be
+found. The contents of the Y index register are added to
+this indirect address. This may be illustrated as
+follows:</p>
+
+<p>Note that only the Y index register can be used with
+post-indexed indirect addressing.</p>
+<a name="6. What the CPU has and doesn&rsquo;t has."></a>
+<h2>6. What the CPU has and doesn&rsquo;t has.</h2>
+
+<p>Although the designers of the MCS6500 CPUs family state
+that there is nothing very significant about the short stack
+(only 256 bytes) this stack caused problems for the back
+end. The designers say that a 256-byte stack usually is
+sufficient for any typical microcomputer, this is only true
+if the stack is used only for return addresses of the JSR
+(jump to subroutine) instruction. But since the EM machine
+is suppost to be a stack machine and high level languages
+need the ability of parameters and locals in there
+procedures and function, this short stack is unsufficiant.
+So an software stack is implemented in this back end,
+requiring two additional subroutines for stack handling.
+These two stack handling subroutines slow down the
+processing time of a program since the stack is used
+heavely.</p>
+
+<p>Since parameters and locals of EM procedures are
+offseted from the localbase of that procedure, indirect
+addressing is havily used. Offsets are positive (for
+parameters) and negative (for local variables). As explaned
+before the addressing modes the MCS6500 have a post indexed
+indirect addressing mode. This addressing mode can only
+handle positive offsets. This raises a problem for accessing
+the local variables I have chosen for the next solution. A
+second local base is introduced. This second local base is
+the real local base subtracted by a constant BASE. In the
+present situation of the back end the value of BASE is 240.
+This means that there are 240 bytes reseved for local
+variables to be indirect addressed and 14 bytes for the
+parameters.</p>
+
+<p align=center><b>THE CODE GENERATOR.</b></p>
+<a name="1. Description of the machine table."></a>
+<h2>1. Description of the machine table.</h2>
+
+<p>The machine description table consists of the following
+sections:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="44%">
+
+<p>The macro definitions.</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>Constant definitions.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>Register definitions.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>Token definitions.</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>Token expressions.</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>Code rules.</p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7.</p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>Move definitions.</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8.</p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>Test definitions.</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>9.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>Stack definitions.</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<a name="1.1. Macro definitions."></a>
+<h2>1.1. Macro definitions.</h2>
+
+<p>The macro definitions at the top of the table are
+expanded by the preprocessor on occurence in the rest of the
+table.</p>
+<a name="1.2. Constant definitions."></a>
+<h2>1.2. Constant definitions.</h2>
+
+<p>There are three constants which must be defined at
+first. The are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>EM_WSIZE:</p>
+</td>
+<td width="4%"></td>
+<td width="78%">
+
+<p>Number of bytes in a machine word. This is the number of
+bytes a simple <b>loc</b> instruction will put on the
+stack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>EM_PSIZE:</p>
+</td>
+<td width="4%"></td>
+<td width="78%">
+
+<p>Number of bytes in a pointer. This is the number of
+bytes a <b>lal</b> instruction will put on the stack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>EM_BSIZE:</p>
+</td>
+<td width="4%"></td>
+<td width="78%">
+
+<p>Number of bytes in the hole between AB and LB. The
+calling sequence only saves LB on the stack so this constant
+is equal to the pointer size.</p>
+</td>
+</table>
+<a name="2. Register definitions."></a>
+<h2>2. Register definitions.</h2>
+
+<p>The only important register definition is the definition
+of the registerpair AX. Since the rest of the
+machine&rsquo;s registers Y, PC, ST serve special purposes,
+the code generator cannot use them.</p>
+<a name="2.1. Token definitions"></a>
+<h2>2.1. Token definitions</h2>
+
+<p>There is a fake token. This token is put in the table,
+since the code generator generator complains if it cannot
+find one.</p>
+<a name="2.2. Token expression definitions."></a>
+<h2>2.2. Token expression definitions.</h2>
+
+<p>The token expression is also a fake one. This token
+expression is put in the table, since the code generator
+generator complains if it cannot find one.</p>
+<a name="2.3. Code rules."></a>
+<h2>2.3. Code rules.</h2>
+
+<p>The code rule section is the largest section in the
+table. They specify EM patterns, stack patterns, code to be
+generated, etc. The syntax is:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>code</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>EM pattern &rsquo;|&rsquo; stack pattern &rsquo;|&rsquo;
+code &rsquo;|&rsquo; stack replacement &rsquo;|&rsquo; EM
+replacement &rsquo;|&rsquo;</p>
+</td>
+</table>
+
+<p>All patterns are optional, however there must be at
+least one pattern present. If the EM pattern is missing the
+rule becomes a rewriting rule or a <b>coercion</b> to be
+used when code generation cannot continue because of an
+invalid stack pattern. The code rules are preceeded by the
+word CODE:.</p>
+<a name="2.3.1. The EM pattern."></a>
+<h2>2.3.1. The EM pattern.</h2>
+
+<p>The EM pattern consists of a list of EM mnemonics
+followed by a boolean expression. Examples:</p>
+
+<p><b>loe</b></p>
+
+<p>will match a single <b>loe</b> instruction,</p>
+
+<p><b>loc loc cif</b> $1==2 &amp;&amp; $2==8</p>
+
+<p>is a pattern that will match</p>
+
+<p><b>loc</b> 2<b><br>
+loc</b> 8<b><br>
+cif</b></p>
+
+<p>and</p>
+
+<p><b>lol inc stl</b> $1==$3</p>
+
+<p>will match for example</p>
+
+<p><b>lol</b> 6<b><br>
+inc<br>
+stl</b> 6</p>
+
+<p>A missing boolean expession evaluates to TRUE.</p>
+
+<p>The code generator will match the longest EM pattern on
+every occasion, if two patterns of the same length match the
+first in the table will be chosen, while all patterns of
+length greater than or equal to three are considered to be
+of the same length.</p>
+<a name="2.3.2. The stack pattern."></a>
+<h2>2.3.2. The stack pattern.</h2>
+
+<p>The only stack pattern that can occur is R16, which
+means that the registerpair AX contains the word on top of
+the stack. If this is not the case a coersion occurs. This
+coersion generates a &quot;jsr Pop&quot;, which means that
+the top of the stack is popped and stored in the
+registerpair AX.</p>
+<a name="2.3.3. The code part."></a>
+<h2>2.3.3. The code part.</h2>
+
+<p>The code part consists of three parts, stack cleanup,
+register allocation, and code to be generated. All of these
+may be omitted.</p>
+<a name="2.3.3.1. Stack cleanup."></a>
+<h2>2.3.3.1. Stack cleanup.</h2>
+
+<p>When generating something like a branch instruction it
+might be needed to empty the fake stack, that is, remove the
+AX registerpair. This is done by the instruction
+remove(ALL)</p>
+<a name="2.3.3.2. Register allocation."></a>
+<h2>2.3.3.2. Register allocation.</h2>
+
+<p>If the machine code to be generated uses the
+registerpair AX, this is signaled to the code generator by
+the allocate(R16) instruction. If the registerpair AX
+resides on the fake stack, this will result in a &quot;jsr
+Push&quot;, which means that the registerpair AX is pushed
+on the stack and will be free for further use. If
+registerpair AX is not on the fake stack nothing
+happens.</p>
+<a name="2.3.3.3. Code to be generated."></a>
+<h2>2.3.3.3. Code to be generated.</h2>
+
+<p>Code to be generated is specified as a list of items of
+the following kind:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>A string in double quotes(&quot;This is a string&quot;).
+This is copied to the codefile and a newline (&rsquo;0) is
+appended. Inside the string all normal C string conventions
+are allowed, and substitutions can be made of the following
+sorts.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>a)</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>$1, $2 etc. These are the operand of the corresponding
+EM instructions and are printed according to there type. To
+put a real &rsquo;$&rsquo; inside the string it must be
+doubled (&rsquo;$$&rsquo;).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>b)</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>%[1], %[2.reg], %[b.1] etc. these have there obvious
+meaning. If they describe a complete token (%[1]) the
+printformat for the token is used. If they stand fo a basic
+term in an expression they will be printed according to
+their type. To put a real &rsquo;%&rsquo; inside the string
+it must be doubled (&rsquo;%%&rsquo;).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>c)</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>%( arbitrary expression %). This allows inclusion of
+arbitrary expressions inside strings. Usually not needed
+very often, so that the akward notation is not too bad. Note
+that %(%[1]%) is equivalent to %[1].</p>
+</td>
+</table>
+<a name="2.3.4. stack replacement."></a>
+<h2>2.3.4. stack replacement.</h2>
+
+<p>The stack replacement is a possibly empty list of items
+to be pushed on the fake stack. Three things can occur:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>%[1] is used if the registerpair AX was on the fake
+stack and is to be pushed back onto it.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>%[a] is used if the registerpair AX is allocated with
+allocate(R16) and is to be pushed onto the fake stack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>It can also be empty.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<a name="2.3.5. EM replacement."></a>
+<h2>2.3.5. EM replacement.</h2>
+
+<p>In exeptional cases it might be useful to leave part of
+the an EM pattern undone. For example, a <b>sdl</b>
+instruction might be split into two <b>stl</b> instructions
+when there is no 4-byte quantity on the stack. The EM
+replacement part allows one to express this. Example:</p>
+
+<p><b>stl</b> $1 <b>stl</b> $1+2</p>
+
+<p>The instructions are inserted in the stream so they can
+match the first part of a pattern in the next step. Note
+that since the code generator traverses the EM instructions
+in a strict linear fashion, it is impossible to let the EM
+replacement match later parts of a pattern. So if there is a
+pattern</p>
+
+<p><b>loc stl</b> $1==0 and the input is</p>
+
+<p><b>loc</b> 0 <b>sdl</b> 4</p>
+
+<p>the <b>loc</b> 0 will be processed first, then the
+<b>sdl</b> might be split into two <b>stl</b></p>
+<a name="2.3.6. Move definitions."></a>
+<h2>2.3.6. Move definitions.</h2>
+
+<p>This definition is a fake. This definition is put in the
+table, since the code generator generator complains if it
+cannot find one.</p>
+<a name="2.3.7. Test definitions."></a>
+<h2>2.3.7. Test definitions.</h2>
+
+<p>Test definitions aren&rsquo;t used by the table.</p>
+<a name="2.3.8. Stack definitions."></a>
+<h2>2.3.8. Stack definitions.</h2>
+
+<p>When the generator has to push the registerpair AX, it
+must know how to do so. The machine code to be generated is
+defined here.</p>
+<a name="3. Some remarks."></a>
+<h2>3. Some remarks.</h2>
+
+<p>The above description of the machine table is a
+description of the table for the MCS6500. It uses only a
+part of the possibilities which the code generator generator
+offers. For a more precise and detailed description see
+[2].</p>
+
+<p align=center><b>THE BACK END TABLE.</b></p>
+<a name="1. Introduction."></a>
+<h2>1. Introduction.</h2>
+
+<p>The code rules are divided in 15 groups. These groups
+are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>Load instructions.</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="38%">
+
+<p>Store instructions.</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p>Integer arithmetic instructions.</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="66%">
+
+<p>Unsigned arithmetic instructions.</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p>Floating point arithmetic instructions.</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p>Pointer arithmetic instructions.</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p>Increment, decrement and zero instructions.</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8.</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>Convert instructions.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>9.</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>Logical instructions.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>10.</p>
+</td>
+<td width="4%"></td>
+<td width="60%">
+
+<p>Set manipulation instructions.</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>11.</p>
+</td>
+<td width="4%"></td>
+<td width="38%">
+
+<p>Array instructions.</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>12.</p>
+</td>
+<td width="4%"></td>
+<td width="42%">
+
+<p>Compare instructions.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>13.</p>
+</td>
+<td width="4%"></td>
+<td width="40%">
+
+<p>Branch instructions.</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>14.</p>
+</td>
+<td width="4%"></td>
+<td width="56%">
+
+<p>Procedure call instructions.</p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>15.</p>
+</td>
+<td width="4%"></td>
+<td width="54%">
+
+<p>Miscellaneous instructions.</p>
+</td>
+<td width="35%">
+</td>
+</table>
+
+<p>From all of these groups one or two typical EM pattern
+will be explained in the next paragraphs. Comment is placed
+between /* and */ (/* This is a comment */).</p>
+<a name="2. The instructions."></a>
+<h2>2. The instructions.</h2>
+<a name="2.1. The load instructions."></a>
+<h2>2.1. The load instructions.</h2>
+
+<p>In this group a typical instruction is <b>lol</b> A
+<b>lol</b> instruction pushes the word at local base +
+offset, where offset is the instructions argument, onto the
+stack. Since the MCS6500 can only offset by 256 bytes, as
+explaned at the memory addressing modes, there is a need for
+two code rules in the table. One which can offset directly
+and one that must explicit calculate the address of the
+local.</p>
+<a name="2.1.1. The lol instruction with indirect offsetting."></a>
+<h2>2.1.1. The lol instruction with indirect offsetting.</h2>
+
+<p>In this case an indirect offsetted load from the second
+local base is possible. The table content is:</p>
+
+<p><b>lol</b> IN($1) | |<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;ldy #BASE+$1&quot; /* load Y with the offset from the
+second<br>
+local base */<br>
+&quot;lda (LBl),y&quot; /* load indirect the lowbyte of the
+word */<br>
+&quot;tax&quot; /* move register A to register X */<br>
+&quot;iny&quot; /* increment register Y (offset) */<br>
+&quot;lda (LBl),y&quot; /* load indirect the highbyte of the
+word */<br>
+| %[a] | | /* push the word onto the fake stack */</p>
+<a name="2.1.2. The lol instruction whose offset is to big."></a>
+<h2>2.1.2. The lol instruction whose offset is to big.</h2>
+
+<p>In this case, the library subroutine &quot;Lol&quot; is
+used. This subroutine expects the offset in registerpair AX,
+then calculates the address of the local or parameter, and
+loads it into registerpair AX. The table content is:</p>
+
+<p><b>lol</b> | |<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;lda #[$1].h&quot; /* load highbyte of offset into
+register A */<br>
+&quot;ldx #[$1].l&quot; /* load lowbyte of offset into
+register X */<br>
+&quot;jsr Lol&quot; /* perform the subroutine */<br>
+| %[a] | | /* push word onto the fake stack */</p>
+<a name="2.2. The store instructions."></a>
+<h2>2.2. The store instructions.</h2>
+
+<p>In this group a typical instruction is <b>stl.</b> A
+<b>stl</b> instruction poppes a word from the stack and
+stores it in the word at local base + offset, where offset
+is the instructions argument. Here also is the need for two
+code rules in the table as a result of the offset
+limits.</p>
+<a name="2.2.1. The stl instruction with indirect offsetting."></a>
+<h2>2.2.1. The stl instruction with indirect offsetting.</h2>
+
+<p>In this case it an indirect offsetted store from the
+second local base is possible. The table content is:</p>
+
+<p><b>stl</b> IN($1) | R16 | /* expect registerpair AX on
+top of the<br>
+fake stack */<br>
+&quot;ldy #BASE+1+$1&quot; /* load Y with the offset from
+the<br>
+second local base */<br>
+&quot;sta (LBl),y&quot; /* store the highbyte of the word
+from A */<br>
+&quot;txa&quot; /* move register X to register A */<br>
+&quot;dey&quot; /* decrement offset */<br>
+&quot;sta (LBl),y&quot; /* store the lowbyte of the word
+from A */<br>
+| | |</p>
+<a name="2.2.2. The stl instruction whose offset is to big."></a>
+<h2>2.2.2. The stl instruction whose offset is to big.</h2>
+
+<p>In this case the library subroutine &rsquo;Stl&rsquo; is
+used. This subroutine expects the offset in registerpair AX,
+then calculates the address, poppes the word stores it at
+its place. The table content is:</p>
+
+<p><b>stl</b> | |<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;lda #[$1].h&quot; /* load highbyte of offset in
+register A */<br>
+&quot;ldx #[$1].l&quot; /* load lowbyte of offset in
+register X */<br>
+&quot;jsr Stl&quot; /* perform the subroutine */<br>
+| | |</p>
+<a name="2.3. Integer arithmetic instructions."></a>
+<h2>2.3. Integer arithmetic instructions.</h2>
+
+<p>In this group typical instructions are <b>adi</b> and
+<b>mli.</b> These instructions, in this table, are
+implemented for 2-byte and 4-byte integers. The only
+arithmetic instructions available on the MCS6500 are the ADC
+(add with carry), and SBC (subtract with not(carry)).
+Not(carry) here means that in a subtraction, the one&rsquo;s
+complement of the carry is taken. The absence of multiply
+and division instructions forces the use of subroutines to
+handle these cases. Because there are no registers left to
+perform on the multiply and division, zero page is used
+here. The 4-byte integer arithmetic is implemented, because
+in C there exists the integer type long. A user is freely to
+use the type long, but will pay in performance.</p>
+<a name="2.3.1. The adi instruction."></a>
+<h2>2.3.1. The adi instruction.</h2>
+
+<p>In case of the <b>adi</b> 2 (and <b>sbi</b> 2)
+instruction there are many EM patterns, so that the
+instruction can be performed in line in most cases. For the
+worst case there exists a subroutine in the library which
+deals with the EM instruction. In case of a <b>adi</b> 4 (or
+<b>sbi</b> 4) there only is a subroutine to deal with it. A
+table content is:</p>
+
+<p><b>lol lol adi</b> (IN($1) &amp;&amp; IN($2) &amp;&amp;
+$3==2) | | /* is it in range */<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;ldy #BASE+$1+1&quot; /* load Y with offset for first
+operand */<br>
+&quot;lda (LBl),y&quot; /* load indirect highbyte first
+operand */<br>
+&quot;pha&quot; /* save highbyte first operand on hard_stack
+*/<br>
+&quot;dey&quot; /* decrement offset first operand */<br>
+&quot;lda (LBl),y&quot; /* load indirect lowbyte first
+operand */<br>
+&quot;ldy #BASE+$2&quot; /* load Y with offset for second
+operand */<br>
+&quot;clc&quot; /* clear carry for addition */<br>
+&quot;adc (LBl),y&quot; /* add the lowbytes of the operands
+*/<br>
+&quot;tax&quot; /* store lowbyte of result in place */<br>
+&quot;iny&quot; /* increment offset second operand */<br>
+&quot;pla&quot; /* get highbyte first operand */<br>
+&quot;adc (LBl),y&quot; /* add the highbytes of the operands
+*/<br>
+| %[a] | | /* push the result onto the fake stack */</p>
+<a name="2.3.2. The mli instruction."></a>
+<h2>2.3.2. The mli instruction.</h2>
+
+<p>The <b>mli</b> 2 instruction uses most the subroutine
+&rsquo;Mlinp&rsquo;. This subroutine expects the
+multiplicand in zero page at locations ARTH, ARTH+1, while
+the multiplier is in zero page locations ARTH+2, ARTH+3. For
+a description of the algorithms used for multiplication and
+division, see [3]. A table content is:</p>
+
+<p><b>lol lol mli</b> (IN($1) &amp;&amp; IN($2) &amp;&amp;
+$3==2) | |<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;ldy #BASE+$1&quot; /* load Y with offset of
+multiplicand */<br>
+&quot;lda (LBl),y&quot; /* load indirect lowbyte of
+multiplicand */<br>
+&quot;sta ARTH&quot; /* store lowbyte in zero page */<br>
+&quot;iny&quot; /* increment offset of multiplicand */<br>
+&quot;lda (LBl),y&quot; /* load indirect highbyte of
+multiplicand */<br>
+&quot;sta ARTH+1&quot; /* store highbyte in zero page */<br>
+&quot;ldy #BASE+$2&quot; /* load Y with offset of multiplier
+*/<br>
+&quot;lda (LBl),y&quot; /* load indirect lowbyte of
+multiplier */<br>
+&quot;sta ARTH+2&quot; /* store lowbyte in zero page */<br>
+&quot;iny&quot; /* increment offset of multiplier */<br>
+&quot;lda (LBl),y&quot; /* load indirect highbyte of
+multiplier */<br>
+&quot;sta ARTH+3&quot; /* store highbyte in zero page */<br>
+&quot;jsr Mlinp&quot; /* perform the multiply */<br>
+| %[a] | | /* push result onto fake stack */</p>
+<a name="2.4. The unsgned arithmetic instructions."></a>
+<h2>2.4. The unsgned arithmetic instructions.</h2>
+
+<p>Since unsigned addition an subtraction is performed in
+the same way as signed addition and subtraction, these cases
+are dealt with by an EM replacement. For mutiplication and
+division there are special subroutines.</p>
+<a name="2.4.1. Unsigned addition."></a>
+<h2>2.4.1. Unsigned addition.</h2>
+
+<p>This is an example of the EM replacement strategy.</p>
+
+<p><b>lol lol adu</b> | | | | <b>lol</b> $1 <b>lol</b> $2
+<b>adi</b> $3 |</p>
+<a name="2.5. Floating point arithmetic."></a>
+<h2>2.5. Floating point arithmetic.</h2>
+
+<p>Floating point arithmetic isn&rsquo;t implemented in
+this table.</p>
+<a name="2.6. Pointer arithmetic instructions."></a>
+<h2>2.6. Pointer arithmetic instructions.</h2>
+
+<p>A typical pointer arithmetic instruction is <b>adp</b>
+2. This instruction adds an offset and a pointer. A table
+content is:</p>
+
+<p><b>adp</b> | | | | <b>loc</b> $1 <b>adi</b> 2 |</p>
+<a name="2.7. Increment, decrement and zero instructions."></a>
+<h2>2.7. Increment, decrement and zero instructions.</h2>
+
+<p>In this group a typical instruction is <b>inl</b> ,
+which increments a local or parameter. The MCS6500
+doesn&rsquo;t have an instruction to increment the
+accumulator A, so the &rsquo;ADC&rsquo; instruction must be
+used. A table content is:</p>
+
+<p><b>inl</b> IN($1) | |<br>
+allocate(R16) /* allocate registerpair AX */<br>
+&quot;ldy #BASE+$1&quot; /* load Y with offset of the local
+*/<br>
+&quot;clc&quot; /* clear carry for addition */<br>
+&quot;lda (LBl),y&quot; /* load indirect lowbyte of local
+*/<br>
+&quot;adc #1&quot; /* increment lowbyte */<br>
+&quot;sta (LBl),y&quot; /* restore indirect the incremented
+lowbyte */<br>
+&quot;bcc 1f&quot; /* if carry is clear then ready */<br>
+&quot;iny&quot; /* increment offset of local */<br>
+&quot;lda (LBl),y&quot; /* load indirect highbyte of local
+*/<br>
+&quot;adc #0&quot; /* add carry to highbyte */<br>
+&quot;sta (LBl),y\n1:&quot; /* restore indirect the highbyte
+*/</p>
+
+<p>If the offset of the local or parameter is to big, first
+the local or parameter is fetched, than incremented, and
+then restored.</p>
+<a name="2.8. Convert instructions."></a>
+<h2>2.8. Convert instructions.</h2>
+
+<p>In this case there are two convert instructions which
+really do something. One of them is in line code, and deals
+with the extension of a character (1-byte) to an integer.
+The other one is a subroutine which handles the conversion
+between 2-byte integers and 4-byte integers.</p>
+<a name="2.8.1. The in line conversion."></a>
+<h2>2.8.1. The in line conversion.</h2>
+
+<p>The table content is:</p>
+
+<p><b>loc loc cii</b> $1==1 &amp;&amp; $2==2 | R16 |<br>
+&quot;txa&quot; /* see if sign extension is needed */<br>
+&quot;bpl 1f&quot; /* there is no need for sign extension
+*/<br>
+&quot;lda #0FFh&quot; /* sign extension here */<br>
+&quot;bne 2f&quot; /* conversion ready */<br>
+&quot;1: lda #0\n2:&quot; /* no sign extension here */</p>
+<a name="2.9. Logical instructions."></a>
+<h2>2.9. Logical instructions.</h2>
+
+<p>A typical instruction in this group is the logical
+<b>and</b> on two 2-byte words. The logical <b>and</b> on
+groups of more than two bytes (max 254) is also possible and
+uses a library subroutine.</p>
+<a name="2.9.1. The logical and on 2-byte groups."></a>
+<h2>2.9.1. The logical and on 2-byte groups.</h2>
+
+<p>The table content is:</p>
+
+<p><b>and</b> $1==2 | R16 | /* one group must be on the
+fake stack */<br>
+&quot;sta ARTH+1&quot; /* temporary save of first group
+highbyte */<br>
+&quot;stx ARTH&quot; /* temporary save of first group
+lowbyte */<br>
+&quot;jsr Pop&quot; /* pop second group from the stack
+*/<br>
+&quot;and ARTH+1&quot; /* logical and on highbytes */<br>
+&quot;pha&quot; /* temporary save the result&rsquo;s
+highbyte */<br>
+&quot;txa&quot; /* logical and can only be done in A */<br>
+&quot;and ARTH&quot; /* logical and on lowbytes */<br>
+&quot;tax&quot; /* restore results lowbyte */<br>
+&quot;pla&quot; /* restore results highbyte */<br>
+| %[1] | | /* push result onto fake stack */</p>
+<a name="2.10. Set manipulation instructions."></a>
+<h2>2.10. Set manipulation instructions.</h2>
+
+<p>A typical EM pattern in this group is <b>loc inn zeq</b>
+$1&gt;0 &amp;&amp; $1&lt;16 &amp;&amp; $2==2. This EM
+pattern works on sets of 16 bits. Sets can be bigger (max
+256 bytes = 2048 bits), but than a library routine is used
+instead of in line code. The table content of the above EM
+pattern is:</p>
+
+<p><b>loc inn zeq</b> $1&gt;0 &amp;&amp; $1&lt;16
+&amp;&amp; $2==2 | R16 |<br>
+&quot;ldy #$1+1&quot; /* load Y with bit number */<br>
+&quot;stx ARTH&quot; /* cannot rotate X, so use zero page
+*/<br>
+&quot;1: lsr a&quot; /* right shift A */<br>
+&quot;ror ARTH&quot; /* right rotate zero page location
+*/<br>
+&quot;dey&quot; /* decrement Y */<br>
+&quot;bne 1b&quot; /* shift $1 times */<br>
+&quot;bcc $1&quot; /* no carry, so bit is zero */</p>
+<a name="2.11. Array instructions."></a>
+<h2>2.11. Array instructions.</h2>
+
+<p>In this group a typical EM pattern is <b>lae lar</b>
+defined(rom(1,3)) | | | | <b>lae</b> $1 <b>aar</b> $2
+<b>loi</b> rom(1,3). This pattern uses the <b>aar</b>
+instruction, which is part of a typical EM pattern:</p>
+
+<p><b>lae aar</b> $2==2 &amp;&amp; rom(1,3)==2 &amp;&amp;
+rom(1,1)==0 | R16 | /* registerpair AX contains the index in
+the array */<br>
+&quot;pha&quot; /* save highbyte of index */<br>
+&quot;txa&quot; /* move lowbyte of index to A */<br>
+&quot;asl a&quot; /* shift left lowbyte == 2 times lowbyte
+*/<br>
+&quot;tax&quot; /* restore lowbyte */<br>
+&quot;pla&quot; /* restore highbyte */<br>
+&quot;rol a&quot; /* rotate left highbyte == 2 times
+highbyte */<br>
+| %[1] | adi 2 | /* push new index, add to lowerbound array
+*/</p>
+<a name="2.12. Compare instructions."></a>
+<h2>2.12. Compare instructions.</h2>
+
+<p>In this group all EM patterns are performed by calling a
+subroutine. Subroutines are used here because comparison is
+only possible byte by byte. This means a lot of code, and
+since compare are used frequently a lot of in line code
+would be generated, and thus reducing the space left for the
+software stack. These subroutines can be found in the
+library.</p>
+<a name="2.13. Branch instructions."></a>
+<h2>2.13. Branch instructions.</h2>
+
+<p>A typical branch instruction is <b>beq.</b> The table
+content for it is:</p>
+
+<p><b>beq</b> | R16 |<br>
+&quot;sta BRANCH+1&quot; /* save highbyte second operand in
+zero page */<br>
+&quot;stx BRANCH&quot; /* save lowbyte second operand in
+zero page */<br>
+&quot;jsr Pop&quot; /* pop the first operand */<br>
+&quot;cmp BRANCH+1&quot; /* compare the highbytes */<br>
+&quot;bne 1f&quot; /* there not equal so go on */<br>
+&quot;cpx BRANCH&quot; /* compare the lowbytes */<br>
+&quot;beq $1\n1:&quot; /* lowbytes are also equal, so branch
+*/</p>
+
+<p>Another typical instruction in this group is <b>zeq.</b>
+The table content is:</p>
+
+<p><b>zeq</b> | R16 |<br>
+&quot;tay&quot; /* move A to Y for setting testbits */<br>
+&quot;bmi $1&quot; /* highbyte s minus so branch */<br>
+&quot;txa&quot; /* move X to A for setting testbits */<br>
+&quot;beq $1\n1:&quot; /* lowbyte also zero, thus branch
+*/</p>
+<a name="2.14. Procedure call instructions."></a>
+<h2>2.14. Procedure call instructions.</h2>
+
+<p>In this group one code generation might seem a little
+akward. It is the EM instruction <b>cai</b> which generates
+a &rsquo;jsr Indir&rsquo;. This is because there is no
+indirect jump_subroutine in the MCS6500. The only solution
+is to store the address in zero page, and then do a
+&rsquo;jsr&rsquo; to a known label. At this label there must
+be an indirect jump instruction, which perform a jump to the
+address stored in zero page. In this case the label is
+Indir, and the address is stored in zero page at the
+addresses ADDR, ADDR+1. The tabel content is:</p>
+
+<p><b>cai</b> | R16 |<br>
+&quot;stx ADDR&quot; /* store lowbyte of address in zero
+page */<br>
+&quot;sta ADDR+1&quot; /* store highbyte of address in zero
+page */<br>
+&quot;jsr Indir&quot; /* use the indirect jump */<br>
+| | |</p>
+<a name="2.15. Miscellaneous instructions."></a>
+<h2>2.15. Miscellaneous instructions.</h2>
+
+<p>In this group, as the name suggests, there is no typical
+EM instruction or EM pattern. Most of the MCS6500 code to be
+generated uses a library subroutine or is
+straightforward.</p>
+
+<p align=center><b>PERFORMANCE.</b></p>
+<a name="1. Introduction."></a>
+<h2>1. Introduction.</h2>
+
+<p>To measure the performance of the back end table some
+timing tests are done. What to time? In this case, the
+execution time of several Pascal statements are timed.
+Statements in C, which have a Pascal equivalence are timed
+also. The statements are timed as follows. A test program is
+been written, which executes two nested for_loops from 1 to
+1.000. Within these for_loops the statement, which is to be
+tested, is placed, so the statement will be executed
+1.000.000 times. Then the same program is executed without
+the test statement. The time difference between the two
+executions is the time neccesairy to execute the test
+statement 1.000.000 times. The total time to execute the
+test statement requires thus the time difference divided by
+1.000.000.</p>
+<a name="1. Testing Pascal statements."></a>
+<h2>1. Testing Pascal statements.</h2>
+
+<p>The next statements are tested.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>int1 := 0;</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>int1 := int2 - 1;</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>int1 := int1 + 1;</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4)</p>
+</td>
+<td width="6%"></td>
+<td width="44%">
+
+<p>int1 := icon1 - icon2;</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5)</p>
+</td>
+<td width="6%"></td>
+<td width="48%">
+
+<p>int1 := icon2 div icon1;</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6)</p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p>int1 := int2 * int3;</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7)</p>
+</td>
+<td width="6%"></td>
+<td width="38%">
+
+<p>bool := (int1 &lt; 0);</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8)</p>
+</td>
+<td width="6%"></td>
+<td width="38%">
+
+<p>bool := (int1 &lt; 3);</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>9)</p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p>bool := ((int1 &gt; 3) or (int1 &lt; 3))</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>10)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>case int1 of 1: bool := false; 2: bool := true end;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>11)</p>
+</td>
+<td width="4%"></td>
+<td width="54%">
+
+<p>if int1 = 0 then int2 := 3;</p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>12)</p>
+</td>
+<td width="4%"></td>
+<td width="70%">
+
+<p>while int1 &gt; 0 do int1 := int1 - 1;</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>13)</p>
+</td>
+<td width="4%"></td>
+<td width="20%">
+
+<p>m := a[k];</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>14)</p>
+</td>
+<td width="4%"></td>
+<td width="38%">
+
+<p>let2 := [&rsquo;a&rsquo;..&rsquo;c&rsquo;];</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>15)</p>
+</td>
+<td width="4%"></td>
+<td width="12%">
+
+<p>P3(x);</p>
+</td>
+<td width="77%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>16)</p>
+</td>
+<td width="4%"></td>
+<td width="26%">
+
+<p>dum := F3(x);</p>
+</td>
+<td width="63%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>17)</p>
+</td>
+<td width="4%"></td>
+<td width="38%">
+
+<p>s.overhead := 5400;</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>18)</p>
+</td>
+<td width="4%"></td>
+<td width="54%">
+
+<p>with s do overhead := 5400;</p>
+</td>
+<td width="35%">
+</td>
+</table>
+
+<p>These statement were tested in a procedure test.</p>
+
+<p>procedure test;<br>
+var i, j, ... : integer;<br>
+bool : boolean;<br>
+let2 : set of char;<br>
+begin<br>
+for i := 1 to 1000<br>
+for j := 1 to 1000<br>
+STATEMENT<br>
+end;</p>
+
+<p>STATEMENT is one of the statements as shown above, or it
+is the empty statement. The assignment of used variables, if
+neccesairy, is done before the first for_loop. In case of
+the statement which uses the procedure call, statement 15, a
+dummy procedure is declared whose body is empty. In case of
+the statement which uses the function, statement 16, this
+function returns its argument. for the timing of C
+statements a similar test program was written.</p>
+
+<p>main()<br>
+{<br>
+int i, j, ...;<br>
+for (i = 1; i &lt;= 1000; i++)<br>
+for (j = 1; j &lt;= 1000; j++)<br>
+STATEMENT<br>
+}</p>
+<a name="2. The results."></a>
+<h2>2. The results.</h2>
+
+<p>Here are tables with the results of the time
+measurments. Times are in microseconds (10^-6). Some
+statements appear twice in the tables. In the second case an
+array of 200 integers was declerated before the variable to
+be tested, so this variable cannot be accessed by indirect
+addressing from the second local base. This results in a
+larger execution time of the statement to be tested. The
+column 68000 contains the times measured on a Bleasdale,
+M68000 based, computer. The times in column pdp are measured
+on a DEC pdp11/44, where the times from column 6500 come
+from a BBC microcomputer.</p>
+
+<p align=center><img src="grohtml-101481.png"></p>
+
+<p align=center><img src="grohtml-101482.png"></p>
+<a name="3. Pascal statements which don&rsquo;t have a C equivalent."></a>
+<h2>3. Pascal statements which don&rsquo;t have a C equivalent.</h2>
+
+<p>At first, the two statements who perform an operation on
+constants are left out. These are left out while the C front
+end does constant folding, while the Pascal front end
+doesn&rsquo;t. So in C the statements int1 = icon1 + icon2;
+and int1 = icon1 / icont2; will use the same amount of time
+since the expression is evaluated by the front end. The two
+other statements (let2 :=
+[&rsquo;a&rsquo;..&rsquo;c&rsquo;]; and <b>with</b> s
+<b>do</b> overhead := 5400;), aren&rsquo;t included in the C
+statement timing table, because there constructs do not
+exist in C. Although in C there can be direct bit
+manipulation, and thus can be used to implement sets I have
+not used it here. The <b>with</b> statement does not exists
+in C and there is nothing with the slightest resemblance to
+it.</p>
+
+<p>At first sight in the table , it looked if there is no
+much difference in the times for the M68000 and the
+pdp11/44, in comparison with the times needed by the
+MCS6500. To verify this impression, I calculated the
+correlation coefficient between the times of the M68000 and
+pdp11/44. It turned out to be 0.997 for both the Pascal time
+tests and the C time tests. Since the correlation
+coefficient is near to one and the difference between the
+times is small, they can be considered to be the same as
+seen from the times of the MCS6500. Then I have tried to
+make a grafic of the times from the M68000 and the MCS6500.
+Well, there was&rsquo;t any correlation to been seen, taken
+all the times. The only correlation one could see, with some
+effort, was in the times for the first three Pascal
+statements. The two first C statements show also a
+correlation, which two points always do.</p>
+
+<p>Also the three Pascal statements <b>case</b> , <b>if</b>
+, and <b>while</b> have a correlation coefficient of 0.999.
+This is probably because the <b>case</b> statement uses a
+subroutine in both cases and the other two statements
+<b>if</b> and, <b>while</b> generate in line code. The last
+two Pascal statements use the same time, since the front end
+wil generate the same EM code for both.</p>
+
+<p>The independence between the rest of the test times is
+because in these cases the object code for the MCS6500 uses
+library subroutines, while the other processors can handle
+the EM code with in line code.</p>
+
+<p>It is clear that the MCS6500 is a slower device, it
+needs longer execution times, the need of more library
+subroutines, but there is no constant factor between it
+execution times and those of other processors.</p>
+
+<p>The slowing down of the MCS6500 as result of the need of
+a library subroutine is illustrated by the muliplication
+statement. The MCS6500 needs a library subroutine, while the
+other two processors have a machine instruction to perform
+the multiply. This results in a factor of 48.5, when the
+operands can be accessed indirect by the MCS6500. When the
+MCS6500 cannot access the operands indirectly the situation
+is even worse. The slight differences between the MCS6500
+execution times for Pascal statements and C statements is
+probably the result of the front end, and thus beyond the
+scope of this discussion.</p>
+
+<p>Another timing test is done in C on the statement k = i
++ j + 1983. This statement is tested on many UNIX*</p>
+
+<p align=center><img src="grohtml-101483.png"></p>
+
+<p>systems. For a complete list see appendix A. The slowest
+one is the IBM XT, which runs on a 8088 microprocessor. The
+fasted one is the Amdahl computer. Here is short table to
+illustrate the performance of the MCS6500.</p>
+
+<p align=center><img src="grohtml-101484.png"></p>
+
+<p>The MCS6500 is three times slower than the IBM XT, but
+threehundred times slower than the Amdahl. The reason why
+the times on the IBM XT and the MCS6500 are the same for
+short&rsquo;s and int&rsquo;s, is that most C compilers make
+the types short and integer the same size on 16-bit
+machines. In this project the MCS6500 is regarded as a
+16-bit machine.</p>
+<a name="4. Length tests."></a>
+<h2>4. Length tests.</h2>
+
+<p>I have also compiled several programs written in Pascal
+and C to see if there is a resemblance between the number of
+bytes generated in the machine&rsquo;s language. In the
+tables:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>length:</p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p>The number of bytes of the source program.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>68000:</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>The number of bytes of the a.out file for a M68000.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>pdp:</p>
+</td>
+<td width="10%"></td>
+<td width="82%">
+
+<p>The number of bytes of the a.out file for a
+pdp11/44.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>6500:</p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p>The number of bytes of the a.out file for a MCS6500.</p>
+</td>
+</table>
+
+<p>These are the results:</p>
+
+<p align=center><img src="grohtml-101485.png"></p>
+
+<p align=center><img src="grohtml-101486.png"></p>
+
+<p>In contrast to the execution times of the test
+statements, the object code files sizes show a constant
+factor between them. After calculating the correlation
+coefficient, I have calculated the line fitted between
+sizes.</p>
+
+<p align=center><img src="grohtml-101487.png"></p>
+
+<p align=center><img src="grohtml-101488.png"></p>
+
+<p align=center><img src="grohtml-101489.png"></p>
+
+<p>As seen from the tables above the correlation
+coefficient for Pascal programs is better than the ones for
+C programs. Thus the line fits best for Pascal programs.
+With the formula of the best fitted line one can now
+estimate the size of the object code, which a program needs,
+for a MCS6500 without having the compiler at hand. One also
+can see from these formula that the object code generated
+for a MCS6500 is about 1.8 times more than for the other
+processors. Since the number of bytes in the source file
+havily depends on the programmer, how many spaces he or she
+uses, the size of the indenting in structured programs,
+etc., there is no correlation between the size of the source
+file and the size of the object file. Also the use of
+comments has its influence on the size.</p>
+
+<p align=center><b>SUMMARY.</b></p>
+<a name="1. Summary"></a>
+<h2>1. Summary</h2>
+
+<p>In this chapter some final conclusions are made.</p>
+
+<p>In spite of its simplicity, the MCS6500 is strong enough
+to implement a EM machine. A serious deficy of the MCS6500
+is the missing of 16-bit general purpose registers, and
+especially the missing of a 16-bit stackpointer. As pointed
+out before, one 16-bit register can be simulated by a pair
+of 8-bit registers, in fact, the accumulator A to hold the
+highbyte, and the index register X to hold the lowbyte of
+the word. By lack of a 16-bit stackpointer, zero page must
+be used to hold a stackpointer and there are also two
+subroutines needed for manipulating the stack (Push and
+Pop).</p>
+
+<p>As seen at the time tests, the simple instruction set of
+the MCS6500 forces the use of library subroutines. These
+library subroutines increas the execution time of the
+programs.</p>
+
+<p>The sizes of the object code files show a strong
+correlation in contrast to the execution times. With this
+correlatiuon one canestimate the size of a program if it is
+to be used on a MCS6500.</p>
+<a name="1. REFERENCES."></a>
+<h2>1. REFERENCES.</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Osborn, A., Jacobson, S., and Kane, J. The Mos
+Technology MCS6500. <b>An Introduction to Microcomputers
+,</b> Volume II, Some Real Products (june 1977) chap. 9.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A hardware description of some real existing CPU&rsquo;s,
+such as the Intel Z80, MCS6500, etc. is given in this
+book.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>van Staveren, H. The table driven code generator from
+the Amsterdam Compiler Kit. Vrije Universiteit, Amsterdam,
+(July 11, 1983).</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The defining document for writing a back end table.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Tanenbaum, A.S. Structured Computer Organization.
+Prentice Hall. (1976).</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>In this book computers are described as a hierarchy of
+levels, with each one performing some well-defined
+function.</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/6500.pdf b/doc/tack/6500.pdf
new file mode 100644 (file)
index 0000000..c5b0f7b
Binary files /dev/null and b/doc/tack/6500.pdf differ
diff --git a/doc/tack/LLgen.html b/doc/tack/LLgen.html
new file mode 100644 (file)
index 0000000..758edc8
--- /dev/null
@@ -0,0 +1,1166 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:11 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>LLgen, an extended LL(1) parser generator</title>
+</head>
+<body>
+
+
+<h1 align=center>LLgen, an extended LL(1) parser generator</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The Extended Context-Free Syntax">2. The Extended Context-Free Syntax</a><br>
+<a href="#3. Grammar Specifications">3. Grammar Specifications</a><br>
+<a href="#4. Actions">4. Actions</a><br>
+<a href="#5. Error Recovery">5. Error Recovery</a><br>
+<a href="#6. Ambiguities and conflicts">6. Ambiguities and conflicts</a><br>
+<a href="#7. The LLgen working environment">7. The LLgen working environment</a><br>
+<a href="#8. Programs with more than one parser">8. Programs with more than one parser</a><br>
+<a href="#References">References</a><br>
+<a href="#References">References</a><br>
+<a href="#Appendix A : LLgen Input Syntax">Appendix A : LLgen Input Syntax</a><br>
+<a href="#Appendix B : An example">Appendix B : An example</a><br>
+<a href="#Appendix C. How to use LLgen .">Appendix C. How to use LLgen .</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Ceriel J. H. Jacobs</i><br>
+Dept. of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</p>
+
+<p><i>LLgen</i> provides a tool for generating an efficient
+recursive descent parser with no backtrack from an Extended
+Context Free syntax. The <i>LLgen</i> user specifies the
+syntax, together with code describing actions associated
+with the parsing process. <i>LLgen</i> turns this
+specification into a number of subroutines that handle the
+parsing process.</p>
+
+<p>The grammar may be ambiguous. <i>LLgen</i> contains both
+static and dynamic facilities to resolve these
+ambiguities.</p>
+
+<p>The specification can be split into several files, for
+each of which <i>LLgen</i> generates an output file
+containing the corresponding part of the parser.
+Furthermore, only output files that differ from their
+previous version are updated. Other output files are not
+affected in any way. This allows the user to recompile only
+those output files that have changed.</p>
+
+<p>The subroutine produced by <i>LLgen</i> calls a user
+supplied routine that must return the next token. This way,
+the input to the parser can be split into single characters
+or higher level tokens.</p>
+
+<p>An error recovery mechanism is generated almost
+completely automatically. It is based on so called
+<b>default choices</b>, which are implicitly or explicitly
+specified by the user.</p>
+
+<p><i>LLgen</i> has succesfully been used to create
+recognizers for Pascal, C, and Modula-2.</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><i>LLgen</i> provides a tool for generating an efficient
+recursive descent parser with no backtrack from an Extended
+Context Free syntax. A parser generated by <i>LLgen</i> will
+be called <i>LLparse</i> for the rest of this document. It
+is assumed that the reader has some knowledge of LL(1)
+grammars and recursive descent parsers. For a survey on the
+subject, see reference (2).</p>
+
+<p>Extended LL(1) parsers are an extension of LL(1)
+parsers. They are derived from an Extended Context-Free
+(ECF) syntax instead of a Context-Free (CF) syntax. ECF
+syntax is described in section 2. Section 3 provides an
+outline of a specification as accepted by <i>LLgen</i> and
+also discusses the lexical conventions of grammar
+specification files. Section 4 provides a description of the
+way the <i>LLgen</i> user can associate actions with the
+syntax. These actions must be written in the programming
+language C, <small><small>4</small></small> which also is
+the target language of <i>LLgen</i>. The error recovery
+technique is discussed in section 5. This section also
+discusses what the user can do about it. Section 6 discusses
+the facilities <i>LLgen</i> offers to resolve ambiguities
+and conflicts. <i>LLgen</i> offers facilities to resolve
+them both at parser generation time and during the execution
+of <i>LLparse</i>. Section 7 discusses the <i>LLgen</i>
+working environment. It also discusses the lexical analyzer
+that must be supplied by the user. This lexical analyzer
+must read the input stream and break it up into basic input
+items, called <b>tokens</b> for the rest of this document.
+Appendix A gives a summary of the <i>LLgen</i> input syntax.
+Appendix B gives an example. It is very instructive to
+compare this example with the one given in reference (3). It
+demonstrates the struggle <i>LLparse</i> and other LL(1)
+parsers have with expressions. Appendix C gives an example
+of the <i>LLgen</i> features allowing the user to recompile
+only those output files that have changed, using the
+<i>make</i> program. <small><small>1</small></small></p>
+<a name="2. The Extended Context-Free Syntax"></a>
+<h2>2. The Extended Context-Free Syntax</h2>
+
+<p>The extensions of an ECF syntax with respect to an
+ordinary CF syntax are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>An ECF syntax contains the repetition operator:
+&quot;N&quot; (N represents a positive integer).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>An ECF syntax contains the closure set operator without
+and with upperbound: &quot;*&quot; and &quot;*N&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>An ECF syntax contains the positive closure set operator
+without and with upperbound: &quot;+&quot; and
+&quot;+N&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>An ECF syntax contains the optional operator:
+&quot;?&quot;, which is a shorthand for &quot;*1&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>An ECF syntax contains parentheses &quot;[&quot; and
+&quot;]&quot; which can be used for grouping.</p>
+</td>
+</table>
+
+<p>We can describe the syntax of an ECF syntax with an ECF
+syntax :</p>
+<pre>     grammar         : rule +
+                     ;
+</pre>
+
+<p>This grammar rule states that a grammar consists of one
+or more rules.</p>
+<pre>     rule            : nonterminal &rsquo;:&rsquo; productionrule &rsquo;;&rsquo;
+                     ;
+</pre>
+
+<p>A rule consists of a left hand side, the nonterminal,
+followed by &quot;:&quot;, the <b>produce symbol</b>,
+followed by a production rule, followed by a &quot;;&quot;,
+indicating the end of the rule.</p>
+<pre>     productionrule  : production [ &rsquo;|&rsquo; production ]*
+                     ;
+</pre>
+
+<p>A production rule consists of one or more alternative
+productions separated by &quot;|&quot;. This symbol is
+called the <b>alternation symbol</b>.</p>
+<pre>     production      : term *
+                     ;
+</pre>
+
+<p>A production consists of a possibly empty list of terms.
+So, empty productions are allowed.</p>
+<pre>     term            : element repeats
+                     ;
+</pre>
+
+<p>A term is an element, possibly with a repeat
+specification.</p>
+<pre>     element         : LITERAL
+                     | IDENTIFIER
+                     | &rsquo;[&rsquo; productionrule &rsquo;]&rsquo;
+                     ;
+</pre>
+
+<p>An element can be a LITERAL, which basically is a single
+character between apostrophes, it can be an IDENTIFIER,
+which is either a nonterminal or a token, and it can be a
+production rule between square parentheses.</p>
+<pre>     repeats         : &rsquo;?&rsquo;
+                     | [ &rsquo;*&rsquo; | &rsquo;+&rsquo; ] NUMBER ?
+                     | NUMBER ?
+                     ;
+</pre>
+
+<p>These are the repeat specifications discussed above.
+Notice that this specification may be empty.</p>
+
+<p>The class of ECF languages is identical with the class
+of CF languages. However, in many cases recursive
+definitions of language features can now be replaced by
+iterative ones. This tends to reduce the number of
+nonterminals and gives rise to very efficient recursive
+descent parsers.</p>
+<a name="3. Grammar Specifications"></a>
+<h2>3. Grammar Specifications</h2>
+
+<p>The major part of a <i>LLgen</i> grammar specification
+consists of an ECF syntax specification. Names in this
+syntax specification refer to either tokens or nonterminal
+symbols. <i>LLgen</i> requires token names to be declared as
+such. This way it can be avoided that a typing error in a
+nonterminal name causes it to be accepted as a token name.
+The token declarations will be discussed later. A name will
+be regarded as a nonterminal symbol, unless it is declared
+as a token name. If there is no production rule for a
+nonterminal symbol, <i>LLgen</i> will complain.</p>
+
+<p>A grammar specification may also include some C
+routines, for instance the lexical analyzer and an error
+reporting routine. Thus, a grammar specification file can
+contain declarations, grammar rules and C-code.</p>
+
+<p>Blanks, tabs and newlines are ignored, but may not
+appear in names or keywords. Comments may appear wherever a
+name is legal (which is almost everywhere). They are
+enclosed in /* ... */, as in C. Comments do not nest.</p>
+
+<p>Names may be of arbitrary length, and can be made up of
+letters, underscore &quot;_&quot; and non-initial digits.
+Upper and lower case letters are distinct. Only the first 50
+characters are significant. Notice however, that the names
+for the tokens will be used by the C-preprocessor. The
+number of significant characters therefore depends on the
+underlying C-implementation. A safe rule is to make the
+identifiers distinct in the first six characters, case
+ignored.</p>
+
+<p>There are two kinds of tokens: those that are declared
+and are denoted by a name, and literals.</p>
+
+<p>A literal consists of a character enclosed in
+apostrophes &quot;&rsquo;&quot;. The &quot;\&quot; is an
+escape character within literals. The following escapes are
+recognized :</p>
+
+<p align=center><img src="grohtml-100191.png"></p>
+
+<p>Names representing tokens must be declared before they
+are used. This can be done using the
+&quot;<b>%token</b>&quot; keyword, by writing</p>
+<pre>%token  name1, name2, . . . ;
+</pre>
+
+<p><i>LLparse</i> is designed to recognize special
+nonterminal symbols called <b>start symbols</b>.
+<i>LLgen</i> allows for more than one start symbol. Thus,
+grammars with more than one entry point are accepted. The
+start symbols must be declared explicitly using the
+&quot;<b>%start</b>&quot; keyword. It can be used whenever a
+declaration is legal, f.i.:</p>
+<pre>%start LLparse, specification ;
+</pre>
+
+<p>declares &quot;specification&quot; as a start symbol and
+associates the identifier &quot;LLparse&quot; with it.
+&quot;LLparse&quot; will now be the name of the C-function
+that must be called to recognize
+&quot;specification&quot;.</p>
+<a name="4. Actions"></a>
+<h2>4. Actions</h2>
+
+<p><i>LLgen</i> allows arbitrary insertions of actions
+within the right hand side of a production rule in the ECF
+syntax. An action consists of a number of C statements,
+enclosed in the brackets &quot;{&quot; and
+&quot;}&quot;.</p>
+
+<p><i>LLgen</i> generates a parsing routine for each rule
+in the grammar. The actions supplied by the user are just
+inserted in the proper place. There may also be declarations
+before the statements in the action, as the &quot;{&quot;
+and &quot;}&quot; are copied into the target code along with
+the action. The scope of these declarations terminates with
+the closing bracket &quot;}&quot; of the action.</p>
+
+<p>In addition to actions, it is also possible to declare
+local variables in the parsing routine, which can then be
+used in the actions. Such a declaration consists of a number
+of C variable declarations, enclosed in the brackets
+&quot;{&quot; and &quot;}&quot;. It must be placed right in
+front of the &quot;:&quot; in the grammar rule. The scope of
+these local variables consists of the complete grammar
+rule.</p>
+
+<p>In order to facilitate communication between the actions
+and <i>LLparse</i>, the parsing routines can be given C-like
+parameters. Each parameter must be declared separately, and
+each of these declarations must end with a semicolon. For
+the last parameter, the semicolon is optional.</p>
+
+<p>So, for example</p>
+<pre>expr(int *pval;) { int fact; } :
+                /*
+                 * Rule with one parameter, a pointer to an int.
+                 * Parameter specifications are ordinary C declarations.
+                 * One local variable, of type int.
+                 */
+        factor (&amp;fact)          { *pval = fact; }
+                /*
+                 * factor is another nonterminal symbol.
+                 * One actual parameter is supplied.
+                 * Notice that the parameter passing mechanism is that
+                 * of C.
+                 */
+        [ &rsquo;+&rsquo; factor (&amp;fact)    { *pval += fact; } ]*
+                /*
+                 * remember the &rsquo;*&rsquo; means zero or more times
+                 */
+        ;
+
+</pre>
+
+<p>is a rule to recognize a number of factors, separated by
+&quot;+&quot;, and to compute their sum.</p>
+
+<p><i>LLgen</i> generates C code, so the parameter passing
+mechanism is that of C, as is shown in the example
+above.</p>
+
+<p>Actions often manipulate attributes of the token just
+read. For instance, when an identifier is read, its name
+must be looked up in a symbol table. Therefore, <i>LLgen</i>
+generates code such that at a number of places in the
+grammar rule it is defined which token has last been read.
+After a token, the last token read is this token. After a
+&quot;[&quot; or a &quot;|&quot;, the last token read is the
+next token to be accepted by <i>LLparse</i>. At all other
+places, it is undefined which token has last been read. The
+last token read is available in the global integer variable
+<i>LLsymb</i>.</p>
+
+<p>The user may also specify C-code wherever a
+<i>LLgen</i>-declaration is legal. Again, this code must be
+enclosed in the brackets &quot;{&quot; and &quot;}&quot;.
+This way, the user can define global declarations and
+C-functions. To avoid name-conflicts with identifiers
+generated by <i>LLgen</i>, <i>LLparse</i> only uses names
+beginning with &quot;LL&quot;; the user should avoid such
+names.</p>
+<a name="5. Error Recovery"></a>
+<h2>5. Error Recovery</h2>
+
+<p>The error recovery technique used by <i>LLgen</i> is a
+modification of the one presented in reference (7). It is
+based on <b>default choices</b>, which just are what the
+word says, default choices at every point in the grammar
+where there is a choice. Thus, in an alternation, one of the
+productions is marked as a default choice, and in a term
+with a non-fixed repetition specification there will also be
+a default choice (between doing the term (once more) and
+continuing with the rest of the production in which the term
+appears).</p>
+
+<p>When <i>LLparse</i> detects an error after having parsed
+the string <i>s</i>, the default choices enable it to
+compute one syntactically correct continuation, consisting
+of the tokens <i>t</i> <small><small>1</small></small>
+...<i>t <small><small>n</small></small></i> , such that
+<i>st</i> <small><small>1</small></small> ...<i>t
+<small><small>n</small></small></i> is a string of tokens
+that is a member of the language defined by the grammar.
+Notice, that the computation of this continuation must
+terminate, which implies that the default choices may not
+invoke recursive rules.</p>
+
+<p>At each point in this continuation, a certain number of
+other tokens could also be syntactically correct, f.i. the
+token <i>t</i> is syntactically correct at point <i>t
+<small><small>i</small></small></i> in this continuation, if
+the string <i>st</i> <small><small>1</small></small> ...<i>t
+<small><small>i</small></small> ts</i>
+<small><small>1</small></small> is a string of the language
+defined by the grammar for some string <i>s</i>
+<small><small>1</small></small> and i &gt;= 0.</p>
+
+<p>The set <i>T</i> containing all these tokens (including
+<i>t</i> <small><small>1</small></small> ,...,<i>t
+<small><small>n</small></small></i> ) is computed. Next,
+<i>LLparse</i> discards zero or more tokens from its input,
+until a token <i>t</i> &isin; <i>T</i> is found. The error
+is then corrected by inserting i (i &gt;= 0) tokens <i>t</i>
+<small><small>1</small></small> ...<i>t
+<small><small>i</small></small></i> , such that the string
+<i>st</i> <small><small>1</small></small> ...<i>t
+<small><small>i</small></small> ts</i>
+<small><small>1</small></small> is a string of the language
+defined by the grammar, for some <i>s</i>
+<small><small>1</small></small> . Then, normal parsing is
+resumed.</p>
+
+<p>The above is difficult to implement in a recursive
+decent parser, and is not the way <i>LLparse</i> does it,
+but the effect is the same. In fact, <i>LLparse</i>
+maintains a list of tokens that may not be discarded, which
+is adjusted as <i>LLparse</i> proceeds. This list is just a
+representation of the set <i>T</i> mentioned above. When an
+error occurs, <i>LLparse</i> discards tokens until a token
+<i>t</i> that is a member of this list is found. Then, it
+continues parsing, following the default choices, inserting
+tokens along the way, until this token <i>t</i> is legal.
+The selection of the default choices must guarantee that
+this will always happen.</p>
+
+<p>The default choices are explicitly or implicitly
+specified by the user. By default, the default choice in an
+alternation is the alternative with the shortest possible
+terminal production. The user can select one of the other
+productions in the alternation as the default choice by
+putting the keyword &quot;<b>%default</b>&quot; in front of
+it.</p>
+
+<p>By default, for terms with a repetition count containing
+&quot;*&quot; or &quot;?&quot; the default choice is to
+continue with the rest of the rule in which the term
+appears, and</p>
+<pre>                term+
+</pre>
+
+<p>is treated as</p>
+<pre>                term term* .
+</pre>
+
+<p>It is also clear, that it can never be the default
+choice to do the term (once more), because this could cause
+the parser to loop, inserting tokens forever. However, when
+the user does not want the parser to skip tokens that would
+not have been skipped if the term would have been the
+default choice, the skipping of such a term can be prevented
+by using the keyword &quot;<b>%persistent</b>&quot;. For
+instance, the rule</p>
+<pre>commandlist : command* ;
+</pre>
+
+<p>could be changed to</p>
+<pre>commandlist : [ %persistent command ]* ;
+</pre>
+
+<p>The effects of this in case of a syntax error are
+twofold: The set <i>T</i> mentioned above will be extended
+as if &quot;command&quot; were in the default production, so
+that fewer tokens will be skipped. Also, if the first token
+that is not skipped is a member of the subset of <i>T</i>
+arising from the grammar rule for &quot;command&quot;,
+<i>LLparse</i> will enter that rule. So, in fact the default
+choice is determined dynamically (by <i>LLparse</i>). Again,
+<i>LLgen</i> checks (statically) that <i>LLparse</i> will
+always terminate, and if not, <i>LLgen</i> will
+complain.</p>
+
+<p>An important property of this error recovery method is
+that, once a rule is started, it will be finished. This
+means that all actions in the rule will be executed
+normally, so that the user can be sure that there will be no
+inconsistencies in his data structures because of syntax
+errors. Also, as the method is in fact error correcting, the
+actions in a rule only have to deal with syntactically
+correct input.</p>
+<a name="6. Ambiguities and conflicts"></a>
+<h2>6. Ambiguities and conflicts</h2>
+
+<p>As <i>LLgen</i> generates a recursive descent parser
+with no backtrack, it must at all times be able to determine
+what to do, based on the current input symbol.
+Unfortunately, this cannot be done for all grammars. Two
+kinds of conflicts can arise :</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>the grammar rule is of the form &quot;production1 |
+production2&quot;, and <i>LLparse</i> cannot decide which
+production to chose. This we call an <b>alternation
+conflict</b>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>the grammar rule is of the form &quot;[ productionrule
+]...&quot;, where ... specifies a non-fixed repetition
+count, and <i>LLparse</i> cannot decide whether to choose
+&quot;productionrule&quot; once more, or to continue. This
+we call a <b>repetition conflict</b>.</p>
+</td>
+</table>
+
+<p>There can be several causes for conflicts: the grammar
+may be ambiguous, or the grammar may require a more complex
+parser than <i>LLgen</i> can construct. The conflicts can be
+examined by inspecting the verbose (-<b>v</b>) option output
+file. The conflicts can be resolved by rewriting the grammar
+or by using <b>conflict resolvers</b>. The mechanism
+described here is based on the attributed parsing of
+reference (6).</p>
+
+<p>An alternation conflict can be resolved by putting an
+<b>if condition</b> in front of the first conflicting
+production. It consists of a &quot;<b>%if</b>&quot; followed
+by a C-expression between parentheses. <i>LLparse</i> will
+then evaluate this expression whenever a token is met at
+this point on which there is a conflict, so the conflict
+will be resolved dynamically. If the expression evaluates to
+non-zero, the first conflicting production is chosen,
+otherwise one of the remaining ones is chosen.</p>
+
+<p>An alternation conflict can also be resolved using the
+keywords &quot;<b>%prefer</b>&quot; or
+&quot;<b>%avoid</b>&quot;. &quot;<b>%prefer</b>&quot; is
+equivalent in behaviour to &quot;<b>%if</b> (1)&quot;.
+&quot;<b>%avoid</b>&quot; is equivalent to &quot;<b>%if</b>
+(0)&quot;. In these cases however,
+&quot;<b>%prefer</b>&quot; and &quot;<b>%avoid</b>&quot;
+should be used, as they resolve the conflict statically and
+thus give rise to better C-code.</p>
+
+<p>A repetition conflict can be resolved by putting a
+<b>while condition</b> right after the opening parentheses.
+This while condition consists of a &quot;<b>%while</b>&quot;
+followed by a C-expression between parentheses. Again,
+<i>LLparse</i> will then evaluate this expression whenever a
+token is met at this point on which there is a conflict. If
+the expression evaluates to non-zero, the repeating part is
+chosen, otherwise the parser continues with the rest of the
+rule. Appendix B will give an example of these features.</p>
+
+<p>A useful aid in writing conflict resolvers is the
+&quot;<b>%first</b>&quot; keyword. It is used to declare a
+C-macro that forms an expression returning 1 if the
+parameter supplied can start a specified nonterminal,
+f.i.:</p>
+<pre>%first fmac, nonterm ;
+
+</pre>
+
+<p>declares &quot;fmac&quot; as a macro with one parameter,
+whose value is a token number. If the parameter X can start
+the nonterminal &quot;nonterm&quot;, &quot;fmac(X)&quot; is
+true, otherwise it is false.</p>
+<a name="7. The LLgen working environment"></a>
+<h2>7. The LLgen working environment</h2>
+
+<p><i>LLgen</i> generates a number of files: one for each
+input file, and two other files: <i>Lpars.c</i> and
+<i>Lpars.h</i>. <i>Lpars.h</i> contains
+&quot;#-define&quot;s for the tokennames. <i>Lpars.c</i>
+contains the error recovery routines and tables. Only those
+output files that differ from their previous version are
+updated. See appendix C for a possible application of this
+feature.</p>
+
+<p>The names of the output files are constructed as
+follows: in the input file name, the suffix after the last
+point is replaced by a &quot;c&quot;. If no point is present
+in the input file name, &quot;.c&quot; is appended to it.
+<i>LLgen</i> checks that the filename constructed this way
+in fact represents a previous version, or does not exist
+already.</p>
+
+<p>The user must provide some environment to obtain a
+complete program. Routines called <i>main</i> and
+<i>LLmessage</i> must be defined. Also, a lexical analyzer
+must be provided.</p>
+
+<p>The routine <i>main</i> must be defined, as it must be
+in every C-program. It should eventually call one of the
+startsymbol routines.</p>
+
+<p>The routine <i>LLmessage</i> must accept one parameter,
+whose value is a token number, zero or -1.<br>
+A zero parameter indicates that the current token (the one
+in the external variable <i>LLsymb</i>) is deleted.<br>
+A -1 parameter indicates that the parser expected end of
+file, but didn&rsquo;t get it. The parser will then skip
+tokens until end of file is detected.<br>
+A parameter that is a token number (a positive parameter)
+indicates that this token is to be inserted in front of the
+token currently in <i>LLsymb</i>. The user can give the
+token the proper attributes. Also, the user must take care,
+that the token currently in <i>LLsymb</i> is again returned
+by the <b>next</b> call to the lexical analyzer, with the
+proper attributes. So, the lexical analyzer must have a
+facility to push back one token.</p>
+
+<p>The user may also supply his own error recovery
+routines, or handle errors differently. For this purpose,
+the name of a routine to be called when an error occurs may
+be declared using the keyword <b>%onerror</b>. This routine
+takes two parameters. The first one is either the token
+number of the token expected, or 0. In the last case, the
+error occurred at a choice. In both cases, the routine must
+ensure that the next call to the lexical analyser returns
+the token that replaces the current one. Of course, that
+could well be the current one, in which case <i>LLparse</i>
+recovers from the error. The second parameter contains a
+list of tokens that are not skipped at the error point. The
+list is in the form of a null-terminated array of integers,
+whose address is passed.</p>
+
+<p>The user must supply a lexical analyzer to read the
+input stream and break it up into tokens, which are passed
+to <i>LLparse.</i> It should be an integer valued function,
+returning the token number. The name of this function can be
+declared using the &quot;<b>%lexical</b>&quot; keyword. This
+keyword can be used wherever a declaration is legal and may
+appear only once in the grammar specification, f.i.:</p>
+<pre>%lexical scanner ;
+</pre>
+
+<p>declares &quot;scanner&quot; as the name of the lexical
+analyzer. The default name for the lexical analyzer is
+&quot;yylex&quot;. The reason for this funny name is that a
+useful tool for constructing lexical analyzers is the
+<i>Lex</i> program, <small><small>5</small></small> which
+generates a routine of that name.</p>
+
+<p>The token numbers are chosen by <i>LLgen</i>. The token
+number for a literal is the numerical value of the character
+in the local character set. If the tokens have a name, the
+&quot;# define&quot; mechanism of C is used to give them a
+value and to allow the lexical analyzer to return their
+token numbers symbolically. These &quot;# define&quot;s are
+collected in the file <i>Lpars.h</i> which can be &quot;#
+include&quot;d in any file that needs the token-names. The
+maximum token number chosen is defined in the macro
+<i>LL_MAXTOKNO</i>.</p>
+
+<p>The lexical analyzer must signal the end of input to
+<i>LLparse</i> by returning a number less than or equal to
+zero.</p>
+<a name="8. Programs with more than one parser"></a>
+<h2>8. Programs with more than one parser</h2>
+
+<p><i>LLgen</i> offers a simple facility for having more
+than one parser in a program: in this case, the user can
+change the names of global procedures, variables, etc, by
+giving a different prefix, like this:</p>
+<pre>%prefix XX ;
+</pre>
+
+<p>The effect of this is that all global names start with
+XX instead of LL, for the parser that has this prefix. This
+holds for the variables <i>LLsymb</i>, which now is called
+<i>XXsymb</i>, for the routine <i>LLmessage</i>, which must
+now be called <i>XXmessage</i>, and for the macro
+<i>LL_MAXTOKNO</i>, which is now called <i>XX_MAXTOKNO</i>.
+<i>LL.output</i> is now <i>XX.output</i>, and <i>Lpars.c</i>
+and <i>Lpars.h</i> are now called <i>XXpars.c</i> and
+<i>XXpars.h</i>.</p>
+<a name="References"></a>
+<h2>References</h2>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>S. I. Feldman, &ldquo;Make - A Program for Maintaining
+Computer Programs,&rdquo; <i>Software - Practice and
+Experience,</i> 10, 8, pp. 255-265 (August 1979).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>M. Griffiths, &ldquo;LL(1) Grammars and Analysers&rdquo;
+in <i>Compiler Construction, An Advanced Course,</i> ed. F.
+L. Bauer and J. Eickel, Springer-Verlag, New York, N.Y.
+(1974).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>S. C. Johnson, &ldquo;Yacc: Yet Another Compiler
+Compiler,&rdquo; Comp. Sci. Tech. Rep. No. 32, Bell
+Laboratories, Murray Hill, New Jersey (1975).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>B. W. Kernighan and D. M. Ritchie, <i>The C Programming
+Language,</i> Prentice-Hall, Inc., Englewood Cliffs, New
+Jersey (1978).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>M. E. Lesk, &ldquo;Lex - A Lexical Analyser
+Generator,&rdquo; Comp. Sci. Tech. Rep. No. 39, Bell
+Laboratories, Murray Hill, New Jersey (October 1975).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>D. R. Milton, L. W. Kirchhoff, and B. R. Rowland,
+&ldquo;An ALL(1) Compiler Generator,&rdquo; <i>SIGPLAN
+Notices,</i> 14, 8, pp. 152-157 (August 1979).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>J. Rohrich, &ldquo;Methods for the Automatic
+Construction of Error Correcting Parsers,&rdquo; <i>Acta
+Informatica,</i> 13, pp. 115-139 (1980).</p>
+</td>
+</table>
+<a name="Appendix A : LLgen Input Syntax"></a>
+<h2>Appendix A : LLgen Input Syntax</h2>
+
+<p>This appendix has a description of the <i>LLgen</i>
+input syntax, as a <i>LLgen</i> specification. As a matter
+of fact, the current version of <i>LLgen</i> is written with
+<i>LLgen</i>.</p>
+<pre>/*
+ * First the declarations of the terminals
+ * The order is not important
+ */
+
+%token  IDENTIFIER;            /* terminal or nonterminal name */
+%token  NUMBER;
+%token  LITERAL;
+
+/*
+ * Reserved words
+ */
+
+%token  TOKEN;         /* %token */
+%token  START;         /* %start */
+%token  PERSISTENT;    /* %persistent */
+%token  IF;            /* %if */
+%token  WHILE;         /* %while */
+%token  AVOID;         /* %avoid */
+%token  PREFER;        /* %prefer */
+%token  DEFAULT;       /* %default */
+%token  LEXICAL;       /* %lexical */
+%token  PREFIX;        /* %prefix */
+%token  ONERROR;       /* %onerror */
+%token  FIRST;         /* %first */
+
+/*
+ * Declare LLparse to be a C-routine that recognizes &quot;specification&quot;
+ */
+
+%start  LLparse, specification;
+
+specification
+        : declaration*
+        ;
+
+declaration
+        : START
+                IDENTIFIER &rsquo;,&rsquo; IDENTIFIER
+          &rsquo;;&rsquo;
+        | &rsquo;{&rsquo;
+                /* Read C-declaration here */
+          &rsquo;}&rsquo;
+        | TOKEN
+                IDENTIFIER
+                [ &rsquo;,&rsquo; IDENTIFIER ]*
+          &rsquo;;&rsquo;
+        | FIRST
+                IDENTIFIER &rsquo;,&rsquo; IDENTIFIER
+          &rsquo;;&rsquo;
+        | LEXICAL
+                IDENTIFIER
+          &rsquo;;&rsquo;
+        | PREFIX
+                IDENTIFIER
+          &rsquo;;&rsquo;
+        | ONERROR
+                IDENTIFIER
+       &rsquo;;&rsquo;
+        | rule
+        ;
+
+rule    : IDENTIFIER parameters? ldecl?
+                &rsquo;:&rsquo; productions
+          &rsquo;;&rsquo;
+        ;
+
+ldecl   : &rsquo;{&rsquo;
+                /* Read C-declaration here */
+          &rsquo;}&rsquo;
+        ;
+
+productions
+        : simpleproduction
+          [ &rsquo;|&rsquo; simpleproduction ]*
+        ;
+
+simpleproduction
+        : DEFAULT?
+       [ IF &rsquo;(&rsquo; /* Read C-expression here */ &rsquo;)&rsquo;
+          | PREFER
+          | AVOID
+          ]?
+          [ element repeats ]*
+        ;
+
+element : &rsquo;{&rsquo;
+                /* Read action here */
+          &rsquo;}&rsquo;
+        | &rsquo;[&rsquo; [ WHILE &rsquo;(&rsquo; /* Read C-expression here */ &rsquo;)&rsquo; ]?
+                PERSISTENT?
+                productions
+          &rsquo;]&rsquo;
+        | LITERAL
+        | IDENTIFIER parameters?
+        ;
+
+parameters
+        : &rsquo;(&rsquo; /* Read C-parameters here */ &rsquo;)&rsquo;
+        ;
+
+repeats : /* empty */
+        | [ &rsquo;*&rsquo; | &rsquo;+&rsquo; ] NUMBER?
+        | NUMBER
+        | &rsquo;?&rsquo;
+        ;
+
+</pre>
+<a name="Appendix B : An example"></a>
+<h2>Appendix B : An example</h2>
+
+<p>This example gives the complete <i>LLgen</i>
+specification of a simple desk calculator. It has 26
+registers, labeled &quot;a&quot; through &quot;z&quot;, and
+accepts arithmetic expressions made up of the C operators +,
+-, *, /, %, &amp;, and |, with their usual priorities. The
+value of the expression is printed. As in C, an integer that
+begins with 0 is assumed to be octal; otherwise it is
+assumed to be decimal.</p>
+
+<p>Although the example is short and not very complicated,
+it demonstrates the use of if and while conditions. In the
+example they are in fact used to reduce the number of
+nonterminals, and to reduce the overhead due to the
+recursion that would be involved in parsing an expression
+with an ordinary recursive descent parser. In an ordinary
+LL(1) grammar there would be one nonterminal for each
+operator priority. The example shows how we can do it all
+with one nonterminal, no matter how many priority levels
+there are.</p>
+<pre>{
+#include &lt;stdio.h&gt;
+#include &lt;ctype.h&gt;
+#define MAXPRIO      5
+#define prio(op)     (ptab[op])
+
+struct token {
+        int     t_tokno;        /* token number */
+        int     t_tval;         /* Its attribute */
+} stok = { 0,0 }, tok;
+
+int     nerrors = 0;
+int     regs[26];               /* Space for the registers */
+int     ptab[128];              /* Attribute table */
+
+struct token
+nexttok() {  /* Read next token and return it */
+        register        c;
+        struct token    new;
+
+       while ((c = getchar()) == &rsquo; &rsquo; || c == &rsquo;\t&rsquo;) { /* nothing */ }
+        if (isdigit(c)) new.t_tokno = DIGIT;
+        else if (islower(c)) new.t_tokno = IDENT;
+        else new.t_tokno = c;
+        if (c &gt;= 0) new.t_tval = ptab[c];
+        return new;
+}   }
+
+%token  DIGIT, IDENT;
+%start  parse, list;
+
+list    : stat* ;
+
+stat    {       int     ident, val; } :
+        %if (stok = nexttok(),
+             stok.t_tokno == &rsquo;=&rsquo;)
+                    /* The conflict is resolved by looking one further
+                     * token ahead. The grammar is LL(2)
+                     */
+          IDENT
+                                {       ident = tok.t_tval; }
+          &rsquo;=&rsquo; expr(1,&amp;val) &rsquo;\n&rsquo;
+                                {       if (!nerrors) regs[ident] = val; }
+        | expr(1,&amp;val) &rsquo;\n&rsquo;
+                                {       if (!nerrors) printf(&quot;%d\n&quot;,val); }
+        | &rsquo;\n&rsquo;
+        ;
+
+expr(int level; int *val;) {       int     expr; } :
+          factor(val)
+          [ %while (prio(tok.t_tokno) &gt;= level)
+                    /* Swallow operators as long as their priority is
+                     * larger than or equal to the level of this invocation
+                     */
+              &rsquo;+&rsquo; expr(prio(&rsquo;+&rsquo;)+1,&amp;expr)
+                                {       *val += expr; }
+                    /* This states that &rsquo;+&rsquo; groups left to right. If it
+                     * should group right to left, the rule should read:
+                     * &rsquo;+&rsquo; expr(prio(&rsquo;+&rsquo;),&amp;expr)
+                     */
+            | &rsquo;-&rsquo; expr(prio(&rsquo;-&rsquo;)+1,&amp;expr)
+                                {       *val -= expr; }
+            | &rsquo;*&rsquo; expr(prio(&rsquo;*&rsquo;)+1,&amp;expr)
+                                {       *val *= expr; }
+            | &rsquo;/&rsquo; expr(prio(&rsquo;/&rsquo;)+1,&amp;expr)
+                                {       *val /= expr; }
+            | &rsquo;%&rsquo; expr(prio(&rsquo;%&rsquo;)+1,&amp;expr)
+                                {       *val %= expr; }
+            | &rsquo;&amp;&rsquo; expr(prio(&rsquo;&amp;&rsquo;)+1,&amp;expr)
+                                {       *val &amp;= expr; }
+            | &rsquo;|&rsquo; expr(prio(&rsquo;|&rsquo;)+1,&amp;expr)
+                                {       *val |= expr; }
+          ]*
+                    /* Notice the &quot;*&quot; here. It is important.
+                     */
+     ;
+
+factor(int *val;):
+            &rsquo;(&rsquo; expr(1,val) &rsquo;)&rsquo;
+          | &rsquo;-&rsquo; expr(MAXPRIO+1,val)
+                                {       *val = -*val; }
+          | number(val)
+          | IDENT
+                                {       *val = regs[tok.t_tval]; }
+        ;
+
+number(int *val;) {       int base; }
+        : DIGIT
+                                {       base = (*val=tok.t_tval)==0?8:10; }
+          [ DIGIT
+                                {       *val = base * *val + tok.t_tval; }
+          ]*        ;
+
+%lexical scanner ;
+{
+scanner() {
+        if (stok.t_tokno) { /* a token has been inserted or read ahead */
+                tok = stok;
+                stok.t_tokno = 0;
+                return tok.t_tokno;
+        }
+        if (nerrors &amp;&amp; tok.t_tokno == &rsquo;\n&rsquo;) {
+                printf(&quot;ERROR\n&quot;);
+                nerrors = 0;
+        }
+        tok = nexttok();
+        return tok.t_tokno;
+}
+
+LLmessage(insertedtok) {
+        nerrors++;
+        if (insertedtok) { /* token inserted, save old token */
+                stok = tok;
+                tok.t_tval = 0;
+                if (insertedtok &lt; 128) tok.t_tval = ptab[insertedtok];
+        }
+}
+
+main() {
+        register *p;
+
+       for (p = ptab; p &lt; &amp;ptab[128]; p++) *p = 0;
+        /* for letters, their attribute is their index in the regs array */
+        for (p = &amp;ptab[&rsquo;a&rsquo;]; p &lt;= &amp;ptab[&rsquo;z&rsquo;]; p++) *p = p - &amp;ptab[&rsquo;a&rsquo;];
+        /* for digits, their attribute is their value */
+        for (p = &amp;ptab[&rsquo;0&rsquo;]; p &lt;= &amp;ptab[&rsquo;9&rsquo;]; p++) *p = p - &amp;ptab[&rsquo;0&rsquo;];
+        /* for operators, their attribute is their priority */
+        ptab[&rsquo;*&rsquo;] = 4;
+        ptab[&rsquo;/&rsquo;] = 4;
+        ptab[&rsquo;%&rsquo;] = 4;
+        ptab[&rsquo;+&rsquo;] = 3;
+        ptab[&rsquo;-&rsquo;] = 3;
+        ptab[&rsquo;&amp;&rsquo;] = 2;
+        ptab[&rsquo;|&rsquo;] = 1;
+        parse();
+     exit(nerrors);
+}   }
+</pre>
+<a name="Appendix C. How to use LLgen ."></a>
+<h2>Appendix C. How to use LLgen .</h2>
+
+<p>This appendix demonstrates how <i>LLgen</i> can be used
+in combination with the <i>make</i> program, to make
+effective use of the <i>LLgen</i>-feature that it only
+changes output files when neccessary. <i>Make</i> uses a
+&quot;makefile&quot;, which is a file containing
+dependencies and associated commands. A dependency usually
+indicates that some files depend on other files. When a file
+depends on another file and is older than that other file,
+the commands associated with the dependency are
+executed.</p>
+
+<p>So, <i>make</i> seems just the program that we always
+wanted. However, it is not very good in handling programs
+that generate more than one file. As usual, there is a way
+around this problem. A sample makefile follows:</p>
+<pre># The grammar exists of the files decl.g, stat.g and expr.g.
+# The &quot;.o&quot;-files are the result of a C-compilation.
+
+GFILES = decl.g stat.g expr.g
+OFILES = decl.o stat.o expr.o Lpars.o
+LLOPT =
+
+# As make does&rsquo;nt handle programs that generate more than one
+# file well, we just don&rsquo;t tell make about it.
+# We just create a dummy file, and touch it whenever LLgen is
+# executed. This way, the dummy in fact depends on the grammar
+# files.
+# Then, we execute make again, to do the C-compilations and
+# such.
+
+all: dummy
+        make parser
+
+dummy:  $(GFILES)
+        LLgen $(LLOPT) $(GFILES)
+        touch dummy
+
+parser: $(OFILES)
+        $(CC) -o parser $(LDFLAGS) $(OFILES)
+
+# Some dependencies without actions :
+# make already knows what to do about them
+
+Lpars.o:        Lpars.h
+stat.o:         Lpars.h
+decl.o:         Lpars.h
+expr.o:         Lpars.h
+
+</pre>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/LLgen.pdf b/doc/tack/LLgen.pdf
new file mode 100644 (file)
index 0000000..2222280
Binary files /dev/null and b/doc/tack/LLgen.pdf differ
diff --git a/doc/tack/The Amsterdam Compiler Kit.pdf b/doc/tack/The Amsterdam Compiler Kit.pdf
new file mode 100644 (file)
index 0000000..a748130
Binary files /dev/null and b/doc/tack/The Amsterdam Compiler Kit.pdf differ
diff --git a/doc/tack/ack.html b/doc/tack/ack.html
new file mode 100644 (file)
index 0000000..df716cc
--- /dev/null
@@ -0,0 +1,1353 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:05 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Ack Description File</title>
+</head>
+<body>
+
+<h1 align=center>Ack Description File</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Which descriptions are used">2. Which descriptions are used</a><br>
+<a href="#3. Using the description file">3. Using the description file</a><br>
+<a href="#4. Conventions used in description files">4. Conventions used in description files</a><br>
+<a href="#5. Example">5. Example</a><br>
+
+<hr>
+
+<p><b>Reference Manual</b></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><small>The program <i>ack</i>(I) internally maintains a
+table of possible transformations and a table of string
+variables. The transformation table contains one entry for
+each possible transformation of a file. Which
+transformations are used depends on the suffix of the source
+file. Each transformation table entry tells which input
+suffixes are allowed and what suffix/name the output file
+has. When the output file does not already satisfy the
+request of the user (indicated with the flag
+<b>&minus;c.suffix</b>), the table is scanned starting with
+the next transformation in the table for another
+transformation that has as input suffix the output suffix of
+the previous transformation. A few special transformations
+are recognized, among them is the combiner, which is a
+program combining several files into one. When no stop
+suffix was specified (flag <b>&minus;c.suffix</b>)
+<i>ack</i> stops after executing the combiner with as
+arguments the &minus; possibly transformed &minus; input
+files and libraries. <i>Ack</i> will only perform the
+transformations in the order in which they are presented in
+the table.</small></p>
+
+<p><small>The string variables are used while creating the
+argument list and program call name for a particular
+transformation.</small></p>
+<a name="2. Which descriptions are used"></a>
+<h2>2. Which descriptions are used</h2>
+
+<p><small><i>Ack</i> always uses two description files: one
+to define the front-end transformations and one for the
+machine dependent back-end transformations. Each description
+has a name. First the way of determining the name of the
+descriptions needed is described.</small></p>
+
+<p><small>When the shell environment variable ACKFE is set
+<i>ack</i> uses that to determine the front-end table name,
+otherwise it uses <b>fe</b>.</small></p>
+
+<p><small>The way the backend table name is determined is
+more convoluted.<br>
+First, when the last filename in the program call name is
+not one of <i>ack</i> or the front-end call-names, this
+filename is used as the backend description name. Second,
+when the <b>&minus;m</b> is present the <b>&minus;m</b> is
+chopped of this flag and the rest is used as the backend
+description name. Third, when both failed the shell
+environment variable ACKM is used. Last, when also ACKM was
+not present the default backend is used, determined by the
+definition of ACKM in h/local.h. The presence and value of
+the definition of ACKM is determined at compile time of
+<i>ack</i>.</small></p>
+
+<p><small>Now, we have the names, but that is only the
+first step. <i>Ack</i> stores a few descriptions at compile
+time. This descriptions are simply files read in at compile
+time. At the moment of writing this document, the
+descriptions included are: pdp, fe, i86, m68k2, vax2 and
+int. The name of a description is first searched for
+internally, then in lib/descr/<i>name</i>, then in
+lib/<i>name</i>/descr, and finally in the current directory
+of the user.</small></p>
+<a name="3. Using the description file"></a>
+<h2>3. Using the description file</h2>
+
+<p><small>Before starting on a narrative of the description
+file, the introduction of a few terms is necessary. All
+these terms are used to describe the scanning of zero
+terminated strings, thereby producing another string or
+sequence of strings.</small></p>
+
+<p><small>Backslashing</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>All characters preceded by \ are modified to
+prevent recognition at further scanning. This modification
+is undone before a string is passed to the outside world as
+argument or message. When reading the description files the
+sequences \\, \# and \&lt;newline&gt; have a special
+meaning. \\ translates to a single \, \# translates to a
+single # that is not recognized as the start of comment, but
+can be used in recognition and finally, \&lt;newline&gt;
+translates to nothing at all, thereby allowing continuation
+lines.</small></p>
+</td>
+</table>
+
+<p><small>Variable replacement</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The scan recognizes the sequences {{, {NAME} and
+{NAME?text} Where NAME can be any combination if characters
+excluding ? and } and text may be anything excluding }. ( \}
+is allowed of course ) The first sequence produces an
+unescaped single {. The second produces the contents of the
+NAME, definitions are done by <i>ack</i> and in description
+files. When the NAME is not defined an error message is
+produced on the diagnostic output. The last sequence
+produces the contents of NAME if it is defined and text
+otherwise.</small></p>
+</td>
+</table>
+
+<p><small>Expression replacement</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Syntax: (<i>suffix sequence</i>:<i>suffix
+sequence</i>=<i>text</i>)<br>
+Example: (.c.p.e:.e=tail_em)<br>
+If the two suffix sequences have a common member &minus; .e
+in this case &minus; the text is produced. When no common
+member is present the empty string is produced. Thus the
+example given is a constant expression. Normally, one of the
+suffix sequences is produced by variable replacement.
+<i>Ack</i> sets three variables while performing the diverse
+transformations: HEAD, TAIL and RTS. All three variables
+depend on the properties <i>rts</i> and <i>need</i> from the
+transformations used. Whenever a transformation is used for
+the first time, the text following the <i>need</i> is
+appended to both the HEAD and TAIL variable. The value of
+the variable RTS is determined by the first transformation
+used with a <i>rts</i> property.</small></p>
+<!-- INDENTATION -->
+<p><small>Two runtime flags have effect on the value of one
+or more of these variables. The flag <b>&minus;.suffix</b>
+has the same effect on these three variables as if a file
+with that <b>suffix</b> was included in the argument list
+and had to be translated. The flag <b>&minus;r.suffix</b>
+only has that effect on the TAIL variable. The program call
+names <i>acc</i> and <i>cc</i> have the effect of an
+automatic <b>&minus;.c</b> flag. <i>Apc</i> and <i>pc</i>
+have the effect of an automatic <b>&minus;.p</b>
+flag.</small></p>
+</td>
+</table>
+
+<p><small>Line splitting</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The string is transformed into a sequence of
+strings by replacing the blank space by string separators
+(nulls).</small></p>
+</td>
+</table>
+
+<p><small>IO replacement</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The &gt; in the string is replaced by the output
+file name. The &lt; in the string is replaced by the input
+file name. When multiple input files are present the string
+is duplicated for each input file name.</small></p>
+</td>
+</table>
+
+<p><small>Each description is a sequence of variable
+definitions followed by a sequence of transformation
+definitions. Variable definitions use a line each,
+transformations definitions consist of a sequence of lines.
+Empty lines are discarded, as are lines with nothing but
+comment. Comment is started by a # character, and continues
+to the end of the line. Three special two-characters
+sequences exist: \#, \\ and \&lt;newline&gt;. Their effect
+is described under &rsquo;backslashing&rsquo; above. Each
+&minus; nonempty &minus; line starts with a keyword,
+possibly preceded by blank space. The keyword can be
+followed by a further specification. The two are separated
+by blank space.</small></p>
+
+<p><small>Variable definitions use the keyword <i>var</i>
+and look like this:</small></p>
+<pre><small>   var NAME=text
+</small></pre>
+
+<p><small>The name can be any identifier, the text may
+contain any character. Blank space before the equal sign is
+not part of the NAME. Blank space after the equal is
+considered as part of the text. The text is scanned for
+variable replacement before it is associated with the
+variable name.</small></p>
+
+<p><small>The start of a transformation definition is
+indicated by the keyword <i>name</i>. The last line of such
+a definition contains the keyword <i>end</i>. The lines in
+between associate properties to a transformation and may be
+presented in any order. The identifier after the <i>name</i>
+keyword determines the name of the transformation. This name
+is used for debugging and by the <b>&minus;R</b> flag. The
+keywords are used to specify which input suffices are
+recognized by that transformation, the program to run, the
+arguments to be handed to that program and the name or
+suffix of the resulting output file. Two keywords are used
+to indicate which run-time startoffs and libraries are
+needed. The possible keywords are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small><i>from</i></small></p>
+</td>
+<td width="91%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>followed by a sequence of suffices. Each file with
+one of these suffices is allowed as input file. Preprocessor
+transformations do not need the <i>from</i> keyword. All
+other transformations do.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><i>to</i></small></p>
+</td>
+<td width="95%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>followed by the suffix of the output file name or
+in the case of a linker the output file name.</small></p>
+</td>
+</table>
+
+<p><small><i>program</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>followed by name of the load file of the program,
+a pathname most likely starts with either a / or {EM}. This
+keyword must be present, the remainder of the line is
+subject to backslashing and variable
+replacement.</small></p>
+</td>
+</table>
+
+<p><small><i>mapflag</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The mapflags are used to grab flags given to
+<i>ack</i> and pass them on to a specific transformation.
+This feature uses a few simple pattern matching and
+replacement facilities. Multiple occurrences of this keyword
+are allowed. This text following the keyword is subjected to
+backslashing. The keyword is followed by a match expression
+and a variable assignment separated by blank space. As soon
+as both description files are read, <i>ack</i> looks at all
+transformations in these files to find a match for the flags
+given to <i>ack</i>. The flags <b>&minus;m</b>,
+<b>&minus;o</b>, <b>&minus;O</b>, <b>&minus;r</b>,
+<b>&minus;v</b>, <b>&minus;g</b>, &minus;<b>&minus;c</b>,
+<b>&minus;t</b>, <b>&minus;k</b>, <b>&minus;R</b> and
+&minus;<b>&minus;.</b> are specific to <i>ack</i> and not
+handed down to any transformation. The matching is performed
+in the order in which the entries appear in the definition.
+The scanning stops after first match is found. When a match
+is found, the variable assignment is executed. A * in the
+match expression matches any sequence of characters, a * in
+the right hand part of the assignment is replaced by the
+characters matched by the * in the expression. The right
+hand part is also subject to variable replacement. The
+variable will probably be used in the program arguments. The
+<b>&minus;l</b> flags are special, the order in which they
+are presented to <i>ack</i> must be preserved. The
+identifier LNAME is used in conjunction with the scanning of
+<b>&minus;l</b> flags. The value assigned to LNAME is used
+to replace the flag. The example further on shows the use of
+all this.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small><i>args</i></small></p>
+</td>
+<td width="91%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The keyword is followed by the program call
+arguments. It is subject to backslashing, variable
+replacement, expression replacement, line splitting and IO
+replacement. The variables assigned to by <i>mapflags</i>
+will probably be used here. The flags not recognized by
+<i>ack</i> or any of the transformations are passed to the
+linker and inserted before all other arguments.</small></p>
+</td>
+</table>
+
+<p><small><i>stdin</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This keyword indicates that the transformation
+reads from standard input.</small></p>
+</td>
+</table>
+
+<p><small><i>stdout</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This keyword indicates that the transformation
+writes on standard output.</small></p>
+</td>
+</table>
+
+<p><small><i>optimizer</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>The presence of this keyword indicates that this
+transformation is an optimizer. It can be followed by a
+number, indicating the &quot;level&quot; of the optimizer
+(see description of the -O option in the ack(1ACK) manual
+page).</small></p>
+</td>
+</table>
+
+<p><small><i>priority</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This &minus; optional &minus; keyword is followed
+by a number. Positive priority means that the transformation
+is likely to be used, negative priority means that the
+transformation is unlikely to be used. Priorities can also
+be set with a ack(1ACK) command line option. Priorities come
+in handy when there are several implementations of a certain
+transformation. They can then be used to select a default
+one.</small></p>
+</td>
+</table>
+
+<p><small><i>linker</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This keyword indicates that this transformation is
+the linker.</small></p>
+</td>
+</table>
+
+<p><small><i>combiner</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This keyword indicates that this transformation is
+a combiner. A combiner is a program combining several files
+into one, but is not a linker. An example of a combiner is
+the global optimizer.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small><i>prep</i></small></p>
+</td>
+<td width="91%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This &minus; optional &minus; keyword is followed
+an option indicating its relation to the preprocessor. The
+possible options are:</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>always</small></p>
+<td width="13%"></td>
+<td width="6%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>the input files must be preprocessed<br>
+cond</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>the input files must be preprocessed when
+starting with #<br>
+is</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%"></td>
+<td width="10%">
+
+<p><small>this transformation is the
+preprocessor</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small><i>rts</i></small></p>
+</td>
+<td width="93%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This &minus; optional &minus; keyword indicates
+that the rest of the line must be used to set the variable
+RTS, if it was not already set. Thus the variable RTS is set
+by the first transformation executed which such a property
+or as a result from <i>ack</i>&rsquo;s program call name
+(acc, cc, apc or pc) or by the <b>&minus;.suffix</b>
+flag.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small><i>need</i></small></p>
+</td>
+<td width="91%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This &minus; optional &minus; keyword indicates
+that the rest of the line must be concatenated to the HEAD
+and TAIL variables. This is done once for every
+transformation used or indicated by one of the program call
+names mentioned above or indicated by the
+<b>&minus;.suffix</b> flag.</small></p></td>
+</table>
+<a name="4. Conventions used in description files"></a>
+<h2>4. Conventions used in description files</h2>
+
+<p><small><i>Ack</i> reads two description files. A few of
+the variables defined in the machine specific file are used
+by the descriptions of the front-ends. Other variables, set
+by <i>ack</i>, are of use to all
+transformations.</small></p>
+
+<p><small><i>Ack</i> sets the variable EM to the home
+directory of the Amsterdam Compiler Kit. The variable SOURCE
+is set to the name of the argument that is currently being
+massaged, this is useful for debugging. The variable SUFFIX
+is set to the suffix of the argument that is currently being
+massaged.<br>
+The variable M indicates the directory in lib/{M}/tail_.....
+and NAME is the string to be defined by the preprocessor
+with &minus;D{NAME}. The definitions of {w}, {s}, {l}, {d},
+{f} and {p} indicate EM_WSIZE, EM_SSIZE, EM_LSIZE, EM_DSIZE,
+EM_FSIZE and EM_PSIZE respectively.<br>
+The variable INCLUDES is used as the last argument to
+<i>cpp</i>. It is used to add directories to the list of
+directories containing #include files.</small></p>
+
+<p><small>The variables HEAD, TAIL and RTS are set by
+<i>ack</i> and used to compose the arguments for the
+linker.</small></p>
+<a name="5. Example"></a>
+<h2>5. Example</h2>
+
+<p><small>Description for front-end</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>name cpp</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># the C-preprocessor</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># no from, it&rsquo;s governed by the P
+property</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>to .i</small></p>
+</td>
+<td width="20%">
+
+<p><small># result files have suffix i</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>program {EM}/lib/cpp</small></p>
+</td>
+<td width="20%">
+
+<p><small># pathname of loadfile</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;I* CPP_F={CPP_F?}
+&minus;I*</small></p>
+</td>
+<td width="20%">
+
+<p><small># grab &minus;I.. &minus;U.. and</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;U* CPP_F={CPP_F?}
+&minus;U*</small></p>
+</td>
+<td width="20%">
+
+<p><small># &minus;D.. to use as arguments</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;D* CPP_F={CPP_F?}
+&minus;D*</small></p>
+</td>
+<td width="20%">
+
+<p><small># in the variable CPP_F</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>args {CPP_F?} {INCLUDES?} &minus;D{NAME}
+&minus;DEM_WSIZE={w} &minus;DEM_PSIZE={p} \</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>&minus;DEM_SSIZE={s} &minus;DEM_LSIZE={l}
+&minus;DEM_FSIZE={f} &minus;DEM_DSIZE={d} &lt;</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># The arguments are: first the
+&minus;[IUD]...</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># then the include dir&rsquo;s for this
+machine</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># then the NAME and size values
+finally</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># followed by the input file name</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>stdout</small></p>
+</td>
+<td width="20%">
+
+<p><small># Output on stdout</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>prep is</small></p>
+</td>
+<td width="20%">
+
+<p><small># Is preprocessor</small></p>
+</td>
+</table>
+
+<p><small>end</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>name cem</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># the C-compiler proper</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>from .c</small></p>
+</td>
+<td width="20%">
+
+<p><small># used for files with suffix .c</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>to .k</small></p>
+</td>
+<td width="20%">
+
+<p><small># produces compact code files</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>program {EM}/lib/em_cem</small></p>
+</td>
+<td width="20%">
+
+<p><small># pathname of loadfile</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;p CEM_F={CEM_F?}
+&minus;Xp</small></p>
+</td>
+<td width="20%">
+
+<p><small># pass &minus;p as &minus;Xp to cem</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;L CEM_F={CEM_F?}
+&minus;l</small></p>
+</td>
+<td width="20%">
+
+<p><small># pass &minus;L as &minus;l to cem</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>args &minus;Vw{w}i{w}p{p}f{f}s{s}l{l}d{d}
+{CEM_F?}</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># the arguments are the object sizes
+in</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># the &minus;V... flag and possibly &minus;l and
+&minus;Xp</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>stdin</small></p>
+</td>
+<td width="20%">
+
+<p><small># input from stdin</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>stdout</small></p>
+</td>
+<td width="20%">
+
+<p><small># output on stdout</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>prep always</small></p>
+</td>
+<td width="20%">
+
+<p><small># use cpp</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>rts .c</small></p>
+</td>
+<td width="20%">
+
+<p><small># use the C run-time system</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>need .c</small></p>
+</td>
+<td width="20%">
+
+<p><small># use the C libraries</small></p>
+</td>
+</table>
+
+<p><small>end</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>name decode</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># make human readable files from compact
+code</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>from .k.m</small></p>
+</td>
+<td width="20%">
+
+<p><small># accept files with suffix .k or .m</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>to .e</small></p>
+</td>
+<td width="20%">
+
+<p><small># produce .e files</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>program {EM}/lib/em_decode</small></p>
+</td>
+<td width="20%">
+
+<p><small># pathname of loadfile</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>args &lt;</small></p>
+</td>
+<td width="20%">
+
+<p><small># the input file name is the only
+argument</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>stdout</small></p>
+</td>
+<td width="20%">
+
+<p><small># the output comes on stdout</small></p>
+</td>
+</table>
+
+<p><small>end</small></p>
+<pre><small>Example of a backend, in this case the EM assembler/loader.
+
+
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var w=2</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># wordsize 2</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var p=2</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># pointersize 2</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var s=2</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># short size 2</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var l=4</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># long size 4</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var f=4</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># float size 4</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var d=8</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># double size 8</small></p>
+</td>
+</table>
+
+<p><small>var M=em22</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var NAME=em22</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># for cpp (NAME=em22 results in #define em22
+1)</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var LIB=lib/{M}/tail_</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># part of file name for libraries</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var RT=lib/{M}/head_</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># part of file name for run-time
+startoff</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var SIZE_FLAG=&minus;sm</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># default internal table size flag</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>var INCLUDES=&minus;I{EM}/include</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># use {EM}/include for #include files</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>name asld</small></p>
+</td>
+<td width="72%"></td>
+<td width="20%">
+
+<p><small># Assembler/loader</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>from .k.m.a</small></p>
+</td>
+<td width="20%">
+
+<p><small># accepts compact code and archives</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>to e.out</small></p>
+</td>
+<td width="20%">
+
+<p><small># output file name</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>program {EM}/lib/em_ass</small></p>
+</td>
+<td width="20%">
+
+<p><small># load file pathname</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;l* LNAME={EM}/{LIB}*</small></p>
+</td>
+<td width="20%">
+
+<p><small># e.g. &minus;ly becomes</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small>#{EM}/mach/int/lib/tail_y</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>mapflag &minus;+* ASS_F={ASS_F?} &minus;+* #
+recognize &minus;+ and &minus;&minus;</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>mapflag &minus;&minus;* ASS_F={ASS_F?}
+&minus;&minus;*</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+
+<p><small>mapflag &minus;s* SIZE_FLAG=&minus;s*</small></p>
+</td>
+<td width="20%">
+
+<p><small># overwrite old value of SIZE_FLAG</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>args {SIZE_FLAG} \</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc)
+&minus;o &gt; &lt; \</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>(.p:{TAIL}={EM}/{LIB}pc) \</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>(.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g)
+\</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>(.c.p:{TAIL}={EM}/{LIB}mon)</small></p>
+</td>
+<td width="20%">
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># &minus;s[sml] must be first
+argument</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># the next line contains the choice for head_cc
+or head_pc</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># and the specification of in- and
+output.</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="72%">
+</td>
+<td width="20%">
+
+<p><small># the last three args lines choose
+libraries</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>linker</small></p>
+</td>
+<td width="20%">
+</td>
+</table>
+
+<p><small>end</small></p>
+
+<p><small>The command <i>ack &minus;mem22 &minus;v &minus;v
+&minus;I../h &minus;L &minus;ly prog.c</i> would result in
+the following calls (with exec(II)):</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>1)</small></p>
+</td>
+<td width="92%">
+
+<p><small>/lib/cpp &minus;I../h &minus;I/usr/em/include
+&minus;Dem22 &minus;DEM_WSIZE=2 &minus;DEM_PSIZE=2
+\</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p><small>&minus;DEM_SSIZE=2 &minus;DEM_LSIZE=4
+&minus;DEM_FSIZE=4 &minus;DEM_DSIZE=8 prog.c</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>2)</small></p>
+</td>
+<td width="92%">
+
+<p><small>/usr/em/lib/em_cem &minus;Vw2i2p2f4s2l4d8
+&minus;l</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>3)</small></p>
+</td>
+<td width="92%">
+
+<p><small>/usr/em/lib/em_ass &minus;sm
+/usr/em/lib/em22/head_cc &minus;o e.out prog.k</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p><small>/usr/em/lib/em22/tail_y
+/usr/em/lib/em22/tail_cc.1s</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p><small>/usr/em/lib/em22/tail_cc.2g
+/usr/em/lib/em22/tail_mon</small></p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/ack.pdf b/doc/tack/ack.pdf
new file mode 100644 (file)
index 0000000..24da57f
Binary files /dev/null and b/doc/tack/ack.pdf differ
diff --git a/doc/tack/ansi_C.html b/doc/tack/ansi_C.html
new file mode 100644 (file)
index 0000000..4dadd47
--- /dev/null
@@ -0,0 +1,1254 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:14 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Amsterdam Compiler Kit-ANSI C compiler compliance statements</title>
+</head>
+<body>
+
+<h1 align=center>Amsterdam Compiler Kit-ANSI C compiler compliance statements</h1>
+<a href="#References">References</a><br>
+
+<hr>
+
+<p>This document specifies the implementation-defined
+behaviour of the ANSI-C front end of the Amsterdam Compiler
+Kit as required by ANS X3.159-1989. Since the
+implementation-defined behaviour sometimes depends on the
+machine compiling on or for, some items will be left
+unspecified in this document&dagger;.</p>
+
+<p align=center><img src="grohtml-101091.png"></p>
+
+<p>The compiler assumes that it runs on a UNIX system.</p>
+
+<p><b>ANS A.6.3.1:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Diagnostics are placed on the standard error output.
+They have the following specification:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>&quot;&lt;file&gt;&quot;, line &lt;nr&gt;:
+[(&lt;class&gt;)] &lt;diagnostic&gt;<br>
+There are three classes of diagnostics: &quot;error&quot;,
+&quot;strict&quot; and &quot;warning&quot;. When the class
+is &quot;error&quot;, the &lt;class&gt; is absent.<br>
+The class &quot;strict&quot; is used for violations of the
+standard which are not severe enough to stop compilation. An
+example is the the occurrence of non white-space after an
+&rsquo;#else&rsquo; or &rsquo;#endif&rsquo; pre-processing
+directive. The class &quot;warning&quot; is used for legal
+but dubious constructions. An example is overflow of
+constant expressions.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.2:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The function &rsquo;main&rsquo; can have two arguments.
+The first argument is an integer specifying the number of
+arguments on the command line. The second argument is a
+pointer to an array of pointers to the arguments (as
+strings).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p>Interactive devices are terminals.</p>
+</td>
+<td width="21%">
+</td>
+</table>
+
+<p><b>ANS A.6.3.3:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The number of significant characters is an option. By
+default it is 64. There is a distinction between upper and
+lower case.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.4:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The compiler assumes ASCII-characters in both the source
+and execution character set.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>There are no multi-byte characters.</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p>There 8 bits in a character.</p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Character constants with values that can not be
+represented in 8 bits are truncated.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Character constants that are more than 1 character wide
+will have the first character specified in the least
+significant byte.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="66%">
+
+<p>The only supported locale is &quot;C&quot;.</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A plain &rsquo;char&rsquo; has the same range of values
+as &rsquo;signed char&rsquo;.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.5:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The compiler assumes that it works on and compiles for a
+2-complement binary-number system. Shorts will use 2 bytes
+and longs will use 4 bytes. The size of integers are machine
+dependent.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Converting an integer to a shorter signed integer is
+implemented by ignoring the high-order byte(s) of the
+former. Converting a unsigned integer to a signed integer of
+the same type is only done in administration. This means
+that the bit-pattern remains unchanged.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The result of bitwise operations on signed integers are
+what can be expected on a 2-complement machine.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>If either operand is negative, whether the result of the
+/ operator is the largest integer less than or equal to the
+algebraic quotient or the smallest integer greater than or
+equal to the algebraic quotient is machine dependent, as is
+the sign of the result of the % operator.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The right-shift of a negative value is negative.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.6:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The representation of floating-point values is
+machine-dependent. When native floating-point is not present
+an IEEE-emulation is used. The compiler uses high-precision
+floating-point for constant folding.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Truncation is always to the nearest floating-point
+number that can be represented.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.7:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The type returned by the sizeof-operator (also known as
+size_t) is &rsquo;unsigned int&rsquo;. This is done for
+backward compatibility reasons.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Casting an integer to a pointer or vice versa has no
+effect in bit-pattern when the sizes are equal. Otherwise
+the value will be truncated or zero-extended (depending on
+the direction of the conversion and the relative sizes).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When a pointer is as large as an integer, the type of a
+&rsquo;ptrdiff_t&rsquo; will be &rsquo;int&rsquo;. Otherwise
+the type will be &rsquo;long&rsquo;.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.8:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Since the front end has only limited control over the
+registers, it can only make it more likely that variables
+that are declared as registers also end up in registers. The
+only things that can possibly be put into registers are :
+&rsquo;int&rsquo;, &rsquo;long&rsquo;, &rsquo;float&rsquo;,
+&rsquo;double&rsquo;, &rsquo;long double&rsquo; and
+pointers.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.9:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When a member of a union object is accessed using a
+member of a different type, the resulting value will usually
+be garbage. The compiler makes no effort to catch these
+errors.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The alignment of types is a compile-time option. The
+alignment of a structure-member is the alignment of its
+type. Usually, the alignment is passed on to the compiler by
+the &rsquo;ack&rsquo; program. When a user wants to do this
+manually, he/she should be prepared for trouble.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A &quot;plain&quot; &rsquo;int&rsquo; bit-field is taken
+as a &rsquo;signed int&rsquo;. This means that a field with
+a size of 1 bit can only store the values 0 and -1.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The order of allocation of bit-fields is a compile-time
+option. By default, high-order bits are allocated first.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>An enum has the same size as a &quot;plain&quot;
+&rsquo;int&rsquo;.</p>
+</td>
+<td width="0%">
+</td>
+</table>
+
+<p><b>ANS A.6.3.10:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>An access to a volatile declared variable is done by
+just mentioning the variable. E.g. the statement
+&quot;x;&quot; where x is declared volatile, constitutes an
+access.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>There is no fixed limit on the number of declarators
+that may modify an arithmetic, structure or union type,
+although specifying too many may cause the compiler to run
+out of memory.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.12:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The maximum number of cases in a switch-statement is in
+the order of 1e9, although the compiler may run out of
+memory somewhat earlier.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.13:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Since both the pre-processor and the compiler assume
+ASCII-characters, a single character constant in a
+conditional-inclusion directive matches the same value in
+the execution character set.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The pre-processor recognizes -I... command-line options.
+The directories thus specified are searched first. After
+that, depending on the command that the preprocessor is
+called with, machine/system-dependant directories are
+searched. After that, ~em/include/_tail_ac and /usr/include
+are visited.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Quoted names are first looked for in the directory in
+which the file which does the include resides.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The characters in a h- or q- char-sequence are taken to
+be UNIX paths.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Neither the compiler nor the preprocessor know any
+pragmas.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Since the compiler runs on UNIX, __DATE__ and __TIME__
+will always be defined.</p>
+</td>
+</table>
+
+<p><b>ANS A.6.3.14:</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>NULL is defined as ((void *)0). This in order to flag
+dubious constructions like &quot;int x = NULL;&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The diagnostic printed by &rsquo;assert&rsquo; is as
+follows:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="17%"></td>
+<td width="82%">
+<p>&quot;Assertion &quot;&lt;expr&gt;&quot; failed, file
+&quot;&lt;file&gt;&quot;, line &lt;line&gt;&quot;,</p></td>
+</table>
+</td>
+</table>
+
+<p>where &lt;expr&gt; is the argument to the assert macro,
+printed as string. (the &lt;file&gt; and &lt;line&gt; should
+be clear)</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>The sets for character test macros.</p>
+</td>
+<td width="19%">
+</td>
+</table>
+
+<p align=center><img src="grohtml-101092.png"></p>
+
+<p>As an addition, there is an isascii() macro, which tests
+whether a character is an ascii character. Characters in the
+range from \000 to \177 are ascii characters.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The behaviour of mathematic functions on domain
+error:</p>
+</td>
+</table>
+
+<p align=center><img src="grohtml-101093.png"></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Underflow range errors do not cause errno to be set.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The function fmod() returns 0.0 and sets errno to EDOM
+when the second argument is 0.0.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The set of signals for the signal() function depends on
+the UNIX-system which the compiler is compiling for. The
+default handling, semantics and behaviour of these signals
+are those specified by the operating system vendor. The
+default handling is not reset when SIGILL is received.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A text-stream need not end in a new-line character.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>White space characters before a new-line appear when
+read in.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>There may be any number of null characters appended to a
+binary stream.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The file position indicator of an append mode stream is
+initially positioned at the beginning of the file.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A write on a text stream does not cause the associated
+file to be truncated beyond that point.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The buffering intended by the standard is fully
+supported.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>A zero-length file actually exists.</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A file name can consist of any character, except for the
+&rsquo;\0&rsquo; and the &rsquo;/&rsquo;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p>A file can be open multiple times.</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When a remove() is done on an open file, reading and
+writing behave just as can be expected from a non-removed
+file. When the associated stream is closed, all written data
+will be lost.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When a file exists prior to a call to rename(), the
+behaviour is that of the underlying UNIX system. Normally,
+the call would fail.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The %p conversion in fprintf() has the same effect as
+%#x or %#lx, depending on the sizes of pointer and
+integer.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The %p conversion in fscanf() has the same effect as %x
+or %lx, depending on the sizes of pointer and integer.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A - character that is neither the first nor the last
+character in the scanlist for %[ conversion is taken to be a
+range indicator. When the first character has a higher
+ASCII-value than the second, the - will just be put into the
+scanlist.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The value of errno when fgetpos() or ftell() failed is
+that of lseek(). This means:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="14%">
+
+<p>EBADF &minus;</p>
+</td>
+<td width="6%"></td>
+<td width="56%">
+
+<p>when the stream is not valid</p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="16%">
+
+<p>ESPIPE &minus;</p>
+</td>
+<td width="4%"></td>
+<td width="70%">
+
+<p>when fildes is associated with a pipe (and on some
+systems: sockets)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="16%">
+
+<p>EINVAL &minus;</p>
+</td>
+<td width="4%"></td>
+<td width="70%">
+
+<p>the resulting file pointer would be negative</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The messages generated by perror() depend on the value
+of errno. The mapping of errors to strings is done by
+strerror().</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When the requested size is zero, malloc(), calloc() and
+realloc() return a null-pointer.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>When abort() is called, output buffers will be flushed.
+Temporary files (made with the tmpfile() function) will have
+disappeared when SIGABRT is not caught or ignored.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The exit() function returns the low-order eight bits of
+its argument to the environment.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The predefined environment names are controlled by the
+user. Setting environment variables is done through the
+putenv() function. This function accepts a pointer to char
+as its argument. To set f.i. the environment variable TERM
+to a230 one writes</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="17%"></td>
+<td width="82%">
+<p>putenv(&quot;TERM=a230&quot;);</p></td>
+</table>
+</td>
+</table>
+
+<p>The argument to putenv() is stored in an internal table,
+so malloc&rsquo;ed strings can not be freed until another
+call to putenv() (which sets the same environment variable)
+is made. The function returns 1 if it fails, 0
+otherwise.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The argument to system is passed as argument to /bin/sh
+-c.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The strings returned by strerror() depend on errno in
+the following way:</p>
+</td>
+</table>
+
+<p align=center><img src="grohtml-101094.png"></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>everything else causes strerror() to return &quot;unknown
+error&quot;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The local time zone is per default MET (GMT + 1:00:00).
+This can be changed through the TZ environment variable, or
+by some changes in the sources.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The clock() function returns the number of ticks since
+process startup.</p>
+</td>
+</table>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[1]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>ANS X3.159-1989 <i>American National Standard for
+Information Systems - Programming Language C</i></p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/ansi_C.pdf b/doc/tack/ansi_C.pdf
new file mode 100644 (file)
index 0000000..9447fa8
Binary files /dev/null and b/doc/tack/ansi_C.pdf differ
diff --git a/doc/tack/basic.html b/doc/tack/basic.html
new file mode 100644 (file)
index 0000000..f2c1057
--- /dev/null
@@ -0,0 +1,3850 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:11 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The ABC compiler</title>
+</head>
+<body>
+
+<h1 align=center>The ABC compiler</h1>
+<a href="#INTRODUCTION.">INTRODUCTION.</a><br>
+<a href="#SYNTAX NOTATION">SYNTAX NOTATION</a><br>
+<a href="#1. GENERAL INFORMATION">1. GENERAL INFORMATION</a><br>
+<a href="#1.1. LINE FORMAT">1.1. LINE FORMAT</a><br>
+<a href="#1.2. CONSTANTS">1.2. CONSTANTS</a><br>
+<a href="#1.3. VARIABLES">1.3. VARIABLES</a><br>
+<a href="#1.4. EXPRESSIONS">1.4. EXPRESSIONS</a><br>
+<a href="#Arithmetic">Arithmetic</a><br>
+<a href="#Relational">Relational</a><br>
+<a href="#Logical">Logical</a><br>
+<a href="#Functional">Functional</a><br>
+<a href="#String operations">String operations</a><br>
+<a href="#1.5. ERROR MESSAGES">1.5. ERROR MESSAGES</a><br>
+<a href="#2. B-EM STATEMENTS">2. B-EM STATEMENTS</a><br>
+<a href="#2.1. CALL">2.1. CALL</a><br>
+<a href="#2.2. CLOSE">2.2. CLOSE</a><br>
+<a href="#2.3. DATA">2.3. DATA</a><br>
+<a href="#2.4. DEF FN">2.4. DEF FN</a><br>
+<a href="#2.5. DEFINT/SNG/DBL/STR">2.5. DEFINT/SNG/DBL/STR</a><br>
+<a href="#2.6. DIM">2.6. DIM</a><br>
+<a href="#2.7. END">2.7. END</a><br>
+<a href="#2.8. ERR and ERL">2.8. ERR and ERL</a><br>
+<a href="#2.9. ERROR">2.9. ERROR</a><br>
+<a href="#2.10. FIELD">2.10. FIELD</a><br>
+<a href="#2.11. FOR...NEXT">2.11. FOR...NEXT</a><br>
+<a href="#2.12. GET">2.12. GET</a><br>
+<a href="#2.13. GOSUB...RETURN">2.13. GOSUB...RETURN</a><br>
+<a href="#2.14. GOTO">2.14. GOTO</a><br>
+<a href="#2.15. IF...THEN">2.15. IF...THEN</a><br>
+<a href="#2.16. INPUT">2.16. INPUT</a><br>
+<a href="#2.17. INPUT [#]">2.17. INPUT [#]</a><br>
+<a href="#2.18. LET">2.18. LET</a><br>
+<a href="#2.19. LINE INPUT">2.19. LINE INPUT</a><br>
+<a href="#2.20. LINE INPUT [#]">2.20. LINE INPUT [#]</a><br>
+<a href="#2.21. LSET and RSET">2.21. LSET and RSET</a><br>
+<a href="#2.22. MID$">2.22. MID$</a><br>
+<a href="#2.23. ON ERROR GOTO">2.23. ON ERROR GOTO</a><br>
+<a href="#2.24. ON...GOSUB and ON ...GOTO">2.24. ON...GOSUB and ON ...GOTO</a><br>
+<a href="#2.25. OPEN">2.25. OPEN</a><br>
+<a href="#2.26. OPTION BASE">2.26. OPTION BASE</a><br>
+<a href="#2.27. POKE">2.27. POKE</a><br>
+<a href="#2.28. PRINT">2.28. PRINT</a><br>
+<a href="#2.29. PRINT USING">2.29. PRINT USING</a><br>
+<a href="#2.30. PUT">2.30. PUT</a><br>
+<a href="#2.31. RANDOMIZE">2.31. RANDOMIZE</a><br>
+<a href="#2.32. READ">2.32. READ</a><br>
+<a href="#2.33. REM">2.33. REM</a><br>
+<a href="#2.34. RESTORE">2.34. RESTORE</a><br>
+<a href="#2.35. STOP">2.35. STOP</a><br>
+<a href="#2.36. SWAP">2.36. SWAP</a><br>
+<a href="#2.37. TRON/TROFF">2.37. TRON/TROFF</a><br>
+<a href="#2.38. WHILE...WEND">2.38. WHILE...WEND</a><br>
+<a href="#2.39. WRITE">2.39. WRITE</a><br>
+<a href="#2.40. WRITE #">2.40. WRITE #</a><br>
+<a href="#3. FUNCTIONS">3. FUNCTIONS</a><br>
+<a href="#APPENDIX A DIFFERENCES WITH MICROSOFT BASIC">APPENDIX A DIFFERENCES WITH MICROSOFT BASIC</a><br>
+<a href="#APPENDIX B RESERVED WORDS IN BASIC-EM">APPENDIX B RESERVED WORDS IN BASIC-EM</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Martin L. Kersten<br>
+Gert-Jan Akkerman<br>
+Marcel Worring<br>
+Edo Westerhuis<br>
+Frans Kunst<br>
+Ronnie Lachniet</i><br>
+Department of Mathematics and Computer Science.<br>
+Free University<br>
+Amsterdam</p>
+
+<p>This manual describes the programming language BASIC and
+its compiler included in the Amsterdam Compiler Kit.</p>
+<a name="INTRODUCTION."></a>
+<h2>INTRODUCTION.</h2>
+
+<p>The BASIC-EM compiler is an extensive implementation of
+the programming language BASIC. The language structure and
+semantics are modelled after the BASIC interpreter/compiler
+of Microsoft (tr), a short comparison is provided in
+appendix A.</p>
+
+<p>The compiler generates code for a virtual machine, the
+EM machine [[ACM, etc]]. Using EM as an intermediate machine
+results in a highly portable compiler and BASIC code.<br>
+The drawback of EM is that it does not directly reflect one
+particular hardware design, which means that many of the low
+level operations available within BASIC are ill-defined or
+even inapplicable. To mention a few, the peek and poke
+instructions are likely to be behave errorneous, while line
+printer and tapedeck primitives are unknown.</p>
+
+<p>This manual is divided into three chapters.<br>
+Chapter 1 discusses the general language syntax and
+semantics.<br>
+Chapter 2 describes the statements available in
+BASIC-EM.<br>
+Chapter 3 describes the predefined functions, ordered
+alphabetically.</p>
+
+<p>Appendix A discusses the differences with Microsoft
+BASIC.<br>
+Appendix B describes all reserved symbols.</p>
+<a name="SYNTAX NOTATION"></a>
+<h2>SYNTAX NOTATION</h2>
+
+<p>The conventions for syntax presentation are as
+follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>CAPS</p>
+</td>
+<td width="12%"></td>
+<td width="80%">
+
+<p>Items are reserved words, must be input as shown.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&lt;&gt;</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>Items in lowercase letters enclosed in angular brackets
+are to be supplied by the user.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>[]</p>
+</td>
+<td width="16%"></td>
+<td width="38%">
+
+<p>Items are optional.</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="82%">
+
+<p>Items may be repeated any number of times</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>{}</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>A choice between two or more alternatives. At least one
+of the entries must be chosen.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>|</p>
+</td>
+<td width="18%"></td>
+<td width="80%">
+
+<p>Vertical bars separate the choices within braces.</p>
+</td>
+</table>
+
+<p>All punctuation must be included where shown.</p>
+<a name="1. GENERAL INFORMATION"></a>
+<h2>1. GENERAL INFORMATION</h2>
+
+<p>The BASIC-EM compiler is designed for a UNIX based
+environment. It accepts a text file with a BASIC program
+(suffix .b) and generates an executable file, called
+a.out.</p>
+<a name="1.1. LINE FORMAT"></a>
+<h2>1.1. LINE FORMAT</h2>
+
+<p>A BASIC program consists of a series of lines, starting
+with a positive line number in the range 0 to 32767. A line
+may consists of more than one physical line on a terminal,
+but is limited to 1024 characters. Multiple BASIC statements
+may be placed on a single line, provided they are separated
+by a colon (:).</p>
+<a name="1.2. CONSTANTS"></a>
+<h2>1.2. CONSTANTS</h2>
+
+<p>The BASIC compiler character set is comprised of
+alphabetic characters, numeric characters, and special
+characters shown below.</p>
+<pre>     = + - * / ^ ( ) % # $ \ _
+     ! [ ] , . ; : &amp; &rsquo; ? &gt; &lt;  \ (blanc)
+</pre>
+
+<p>BASIC uses two different types of constants during
+processing: numeric and string constants.<br>
+A string constant is a sequence of characters taken from the
+ASCII character set enclosed by double quotation marks.<br>
+Numeric constants are positive or negative numbers, grouped
+into five different classes.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="40%">
+
+<p>a) integer constants</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>Whole numbers in the range of -32768 and 32767. Integer
+constants do not contain decimal points.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="48%">
+
+<p>b) fixed point constants</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>Positive or negative real numbers, i.e. numbers with a
+decimal point.</p>
+</td>
+</table>
+
+<p>c) floating point constants</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>Real numbers in scientific notation. A floating point
+constant consists of an optional signed integer or fixed
+point number followed by the letter E (or D) and an optional
+signed integer (the exponent). The allowable range of
+floating point constants is 10^-38 to 10^+38.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%">
+
+<p>d) Hex constants</p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>Hexadecimal numbers, denoted by the prefix &amp;H.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="36%">
+
+<p>e) Octal constants</p>
+</td>
+<td width="63%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>Octal numbers, denoted by the prefix &amp;O.</p></td>
+</table>
+<a name="1.3. VARIABLES"></a>
+<h2>1.3. VARIABLES</h2>
+
+<p>Variables are names used to represent values in a BASIC
+program. A variable is assigned a value by assigment
+specified in the program. Before a variable is assigned its
+value is assumed to be zero.<br>
+Variable names are composed of letters, digits or the
+decimal point, starting with a letter. Up to 40 characters
+are significant. A variable name can be followed by any of
+the following type declaration characters:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>%</p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p>Defines an integer variable</p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>!</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Defines a single precision variable (see below)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>#</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>Defines a double precision variable</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>$</p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p>Defines a string variable.</p>
+</td>
+<td width="37%">
+</td>
+</table>
+
+<p>Beside single valued variables, values may be grouped
+into tables or arrays. Each element in an array is
+referenced by the array name and an index, such a variable
+is called a subscripted variable. An array has as many
+subscripts as there are dimensions in the array, the maximum
+of which is 11.<br>
+If a variable starts with FN it is assumed to be a call to a
+user defined function.<br>
+A variable name may not be a reserved word nor the name of a
+predefined function. A list of all reserved identifiers is
+included as Appendix B.</p>
+
+<p>NOTES:<br>
+Two variables with the same name but different type is
+considered illegal.<br>
+The type of a variable without typedeclaration-character is
+set, at it&rsquo;s first occurence in the program, to the
+defaulttype which is (in this implementation) double
+precision.<br>
+Multi-dimensional array&rsquo;s must be declared before use
+(see DIM-statement ).<br>
+BASIC-EM differs from Microsoft BASIC in supporting floats
+in one precision only (due to EM), eg doubles and floats
+have the same precision.</p>
+<a name="1.4. EXPRESSIONS"></a>
+<h2>1.4. EXPRESSIONS</h2>
+
+<p>When necessary the compiler will convert a numeric value
+from one type to another. A value is always converted to the
+precision of the variable it is assigned to. When a floating
+point value is converted to an integer the fractional
+portion is rounded. In an expression all values are
+converted to the same degree of precision, i.e. that of the
+most precise operand.<br>
+Division by zero results in the message &quot;Division by
+zero&quot;. If overflow (or underflow) occurs, the
+&quot;Overflow (underflow)&quot; message is displayed and
+execution is terminated (contrary to Microsoft).</p>
+<a name="Arithmetic"></a>
+<h2>Arithmetic</h2>
+
+<p>The arithmetic operators in order of precedence,a
+re:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>^</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Exponentiation</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>-</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Negation</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>*,/,\\\\,MOD</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>Multiplication, Division, Remainder</p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>+,-</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Addition, Substraction</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>The operator \\ denotes integer division, its operands
+are rounded to integers before the operator is applied.
+Modulus arithmetic is denoted by the operator MOD, which
+yields the integer value that is the remainder of an integer
+division.<br>
+The order in which operators are performed can be changed
+with parentheses.</p>
+<a name="Relational"></a>
+<h2>Relational</h2>
+
+<p>The relational operators in order of precedence,
+are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>=</p>
+<td width="9%"></td>
+<td width="10%">
+
+<p>Equality<br>
+&lt;&gt;</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Inequality<br>
+&lt;</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Less than<br>
+&gt;</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Greater than<br>
+&lt;=</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Less than or equal to<br>
+&gt;=</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Greater than or equal to</p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+</table>
+
+<p>The relational operators are used to compare two values
+and returns either &quot;true&quot; (-1) or
+&quot;false&quot; (0) (See IF statement). The precedence of
+the relational operators is lower then the arithmetic
+operators.</p>
+<a name="Logical"></a>
+<h2>Logical</h2>
+
+<p>The logical operators performs tests on multiple
+relations, bit manipulations, or boolean operations. The
+logical operators returns a bitwise result (&quot;true&quot;
+or &quot;false&quot;). In an expression, logical operators
+are performed after the relational and arithmetic operators.
+The logical operators work by converting their operands to
+signed two-complement integers in the range -32768 to
+32767.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>NOT</p>
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise negation<br>
+AND</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise and<br>
+OR</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise or<br>
+XOR</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise exclusive or<br>
+EQV</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise equivalence<br>
+IMP</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>Bitwise implies</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+<a name="Functional"></a>
+<h2>Functional</h2>
+
+<p>A function is used in an expression to call a system or
+user defined function. A list of predefined functions is
+presented in chapter 3.</p>
+<a name="String operations"></a>
+<h2>String operations</h2>
+
+<p>Strings can be concatenated by using +. Strings can be
+compared with the relational operators. String comparison is
+performed in lexicographic order.</p>
+<a name="1.5. ERROR MESSAGES"></a>
+<h2>1.5. ERROR MESSAGES</h2>
+
+<p>The occurence of an error results in termination of the
+program unless an ON....ERROR statement has been
+encountered.</p>
+<a name="2. B-EM STATEMENTS"></a>
+<h2>2. B-EM STATEMENTS</h2>
+
+<p>This chapter describes the statements available within
+the BASIC-EM compiler. Each description is formatted as
+follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>Shows the correct syntax for the statement. See
+introduction of syntax notation above.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Describes the purpose and details of the
+instructions.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Describes special cases, deviation from Microsoft BASIC
+etc.</p>
+</td>
+</table>
+<a name="2.1. CALL"></a>
+<h2>2.1. CALL</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="78%">
+
+<p>CALL &lt;variable name&gt;[(&lt;argument list&gt;)]</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The CALL statement provides the means to execute
+procedures and functions written in another language
+included in the Amsterdam Compiler Kit. The argument list
+consist of (subscripted) variables. The BASIC compiler
+pushes the address of the arguments on the stack in order of
+encounter.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>Not yet available.</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<a name="2.2. CLOSE"></a>
+<h2>2.2. CLOSE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>CLOSE [[#]&lt;file number&gt;[,[#]&lt;file
+number...&gt;]]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To terminate I/O on a disk file. &lt;file number&gt; is
+the number associated with the file when it was OPENed (See
+OPEN-statement). Ommission of parameters results in closing
+all files.</p>
+</td>
+</table>
+
+<p>The END statement and STOP statement always issue a
+CLOSE of all files.</p>
+<a name="2.3. DATA"></a>
+<h2>2.3. DATA</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p>DATA &lt;list of constants&gt;</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>DATA statements are used to construct a data bank of
+values that are accessed by the program&rsquo;s READ
+statement. DATA statements are non-executable, the data
+items are assembled in a data file by the BASIC compiler.
+This file can be replaced, provided the layout remains the
+same (otherwise the RESTORE won&rsquo;t function
+properly).</p>
+</td>
+</table>
+
+<p>The list of data items consists of numeric and string
+constants as discussed in section 1. Moreover, string
+constants starting with a letter and not containing blancs,
+newlines, commas, colon need not be enclosed with the string
+quotes.</p>
+
+<p>DATA statements can be reread using the RESTORE
+statement.</p>
+<a name="2.4. DEF FN"></a>
+<h2>2.4. DEF FN</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>DEF FN&lt;name&gt;
+[(&lt;parameterlist&gt;)]=&lt;expression&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To define and name a function that is written by the
+user. &lt;name&gt; must be an identifier and should be
+preceded by FN, which is considered integral part of the
+function name. &lt;expression&gt; defines the expression to
+be evaluated upon function call.</p>
+</td>
+</table>
+
+<p>The parameter list is comprised of a comma separated
+list of variable names, used within the function definition,
+that are to replaced by values upon function call. The
+variable names defined in the parameterlist, called formal
+parameters, do not affect the definition and use of
+variables defined with the same name in the rest of the
+BASIC program.</p>
+
+<p>A type declaration character may be suffixed to the
+function name to designate the data type of the function
+result.</p>
+<a name="2.5. DEFINT/SNG/DBL/STR"></a>
+<h2>2.5. DEFINT/SNG/DBL/STR</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p>DEF&lt;type&gt; &lt;range of letters&gt;</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Any undefined variable starting with the letter included
+in the range of letters is declared of type &lt;type&gt;
+unless a type declaration character is appended. The range
+of letters is a comma separated list of characters and
+character ranges (&lt;letter&gt;-&lt;letter&gt;).</p>
+</td>
+</table>
+<a name="2.6. DIM"></a>
+<h2>2.6. DIM</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p>DIM &lt;list of subscripted variable&gt;</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The DIM statement allocates storage for subscripted
+variables. If an undefined subscripted variable is used the
+maximum value of the array subscript is assumed to be 10. A
+subscript out of range is signalled by the program (when ACK
+works) The minimum subscript value is 0, unless the OPTION
+BASE statement has been encountered.</p>
+</td>
+</table>
+
+<p>All variables in a subscripted variable are initially
+zero.</p>
+
+<p>BUGS. Multi-dimensional arrays MUST be defined.
+Subscript out of range is left unnotified.</p>
+<a name="2.7. END"></a>
+<h2>2.7. END</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="6%">
+
+<p>END</p>
+</td>
+<td width="73%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>END terminates a BASIC program and returns to the UNIX
+shell. An END statement at the end of the BASIC program is
+optional.</p>
+</td>
+</table>
+<a name="2.8. ERR and ERL"></a>
+<h2>2.8. ERR and ERL</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="44%">
+
+<p>&lt;identifier name&gt;= ERR</p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>&lt;identifier name&gt;= ERL</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Whenever an error occurs the variable ERR contains the
+error number and ERL the BASIC line where the error
+occurred. The variables are usually used in error handling
+routines provided by the user.</p>
+</td>
+</table>
+<a name="2.9. ERROR"></a>
+<h2>2.9. ERROR</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p>ERROR &lt;integer expression&gt;</p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To simulate the occurrence of a BASIC error. To define a
+private error code a value must be used that is not already
+in use by the BASIC runtime system. The list of error
+messages currently in use can be found in appendix B.</p>
+</td>
+</table>
+<a name="2.10. FIELD"></a>
+<h2>2.10. FIELD</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>To be implemented.</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<a name="2.11. FOR...NEXT"></a>
+<h2>2.11. FOR...NEXT</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>FOR &lt;variable&gt;=
+&lt;low&gt;TO&lt;high&gt;[STEP&lt;size&gt;]</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>......<br>
+NEXT [&lt;variable&gt;][,&lt;variable&gt;...]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The FOR statements allows a series of statements to be
+performed repeatedly. &lt;variable&gt; is used as a counter.
+During the first execution pass it is assigned the value
+&lt;low&gt;, an arithmetic expression. After each pass the
+counter is incremented (decremented) with the step size
+&lt;size&gt;, an expression. Ommission of the step size is
+intepreted as an increment of 1.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Execution of the program lines specified between the FOR
+and the NEXT statement is terminated as soon as &lt;low&gt;
+is greater (less) than &lt;high&gt;</p>
+<!-- INDENTATION -->
+<p>The NEXT statement is labeled with the name(s) of the
+counter to be incremented.</p>
+<!-- INDENTATION -->
+<p>The variables mentioned in the NEXT statement may be
+ommitted, in which case the variable of increment the
+counter of the most recent FOR statement. If a NEXT
+statement is encountered before its corresponding FOR
+statement, the error message &quot;NEXT without FOR&quot; is
+generated.</p></td>
+</table>
+<a name="2.12. GET"></a>
+<h2>2.12. GET</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="78%">
+
+<p>GET [#]&lt;file number&gt;[, &lt;record number&gt;]</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>To be implemented.</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<a name="2.13. GOSUB...RETURN"></a>
+<h2>2.13. GOSUB...RETURN</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="38%">
+
+<p>GOSUB &lt;line number&gt; ...</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>RETURN</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The GOSUB statement branches to the first statement of a
+subroutine. The RETURN statement cause a branch back to the
+statement following the most recent GOSUB statement. A
+subroutine may contain more than one RETURN statement.</p>
+</td>
+</table>
+
+<p>Subroutines may be called recursively. Nesting of
+subroutine calls is limited, upon exceeding the maximum
+depth the error message &quot;XXXXX&quot; is displayed.</p>
+<a name="2.14. GOTO"></a>
+<h2>2.14. GOTO</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="36%">
+
+<p>GOTO &lt;line number&gt;</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To branch unconditionally to a specified line in the
+program. If &lt;line number&gt; does not exists, the
+compilation error message &quot;Line not defined&quot; is
+displayed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Microsoft BASIC continues at the first line equal or
+greater then the line specified.</p>
+</td>
+</table>
+<a name="2.15. IF...THEN"></a>
+<h2>2.15. IF...THEN</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="87%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>IF &lt;expression&gt; THEN {&lt;statements&gt;|&lt;line
+number&gt;} [ELSE {&lt;statements&gt;|&lt;line
+number&gt;}]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>IF &lt;expression&gt; GOTO &lt;line number&gt; [ELSE
+{&lt;statements&gt;|&lt;line number&gt;}]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The IF statement is used to make a decision regarding
+the program flow based on the result of the expressions. If
+the expression is not zero, the THEN or GOTO clause is
+executed. If the result of &lt;expression&gt; is zero, the
+THEN or GOTO clause is ignored and the ELSE clause, if
+present is executed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>IF..THEN..ELSE statements may be nested. Nesting is
+limited by the length of the line. The ELSE clause matches
+with the closests unmatched THEN.</p>
+<!-- INDENTATION -->
+<p>When using IF to test equality for a value that is the
+result of a floating point expression, remember that the
+internal representation of the value may not be exact.
+Therefore, the test should be against a range to handle the
+relative error.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Microsoft BASIC allows a comma before THEN.</p>
+</td>
+</table>
+<a name="2.16. INPUT"></a>
+<h2>2.16. INPUT</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>INPUT [;][&lt;&quot;prompt string&quot;&gt;;]&lt;list of
+variables&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>An INPUT statement can be used to obtain values from the
+user at the terminal. When an INPUT statement is encountered
+a question mark is printed to indicate the program is
+awaiting data. IF &lt;&quot;prompt string&quot;&gt; is
+included, the string is printed before the the question
+mark. The question mark is suppressed when the prompt string
+is followed by a comma, rather then a semicolon.</p>
+</td>
+</table>
+
+<p>For each variable in the variable a list a value should
+be supplied. Data items presented should be separated by a
+comma.</p>
+
+<p>The type of the variable in the variable list must
+aggree with the type of the data item entered. Responding
+with too few or too many data items causes the message
+&quot;?Redo&quot;. No assignment of input values is made
+until an acceptable response is given.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The option to disgard the carriage return with the
+semicolon after the input symbol is not yet implemented.</p>
+</td>
+</table>
+<a name="2.17. INPUT [#]"></a>
+<h2>2.17. INPUT [#]</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>INPUT #&lt;file number&gt;,&lt;list of variables&gt;</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>The purpose of the INPUT# statement is to read data
+items from a sequential file and assign them to program
+variables. &lt;file number&gt; is the number used to open
+the file for input. The variables mentioned are
+(subscripted) variables. The type of the data items read
+should aggree with the type of the variables. A type
+mismatch results in the error message &quot;XXXXX&quot;.</p>
+</td>
+</table>
+
+<p>The data items on the sequential file are separated by
+commas and newlines. In scanning the file, leading spaces,
+new lines, tabs, and carriage returns are ignored. The first
+character encountered is assumed to be the state of a new
+item. String items need not be enclosed with double quotes,
+provided it does not contain spaces, tabs, newlines and
+commas,</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Microsoft BASIC won&rsquo;t assign values until the end
+of input statement. This means that the user has to supply
+all the information.</p>
+</td>
+</table>
+<a name="2.18. LET"></a>
+<h2>2.18. LET</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p>[LET]&lt;variable&gt;=&lt;expression&gt;</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To assign the value of an expression to a (subscribted)
+variable. The type convertions as dictated in chapter 1
+apply.</p>
+</td>
+</table>
+<a name="2.19. LINE INPUT"></a>
+<h2>2.19. LINE INPUT</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>LINE INPUT [;][&lt;&quot;prompt
+string&quot;&gt;;]&lt;string variable&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>An entire line of input is assigned to the string
+variable. See INPUT for the meaning of the &lt;&quot;prompt
+string&quot;&gt; option.</p>
+</td>
+</table>
+<a name="2.20. LINE INPUT [#]"></a>
+<h2>2.20. LINE INPUT [#]</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>LINE INPUT #&lt;file number&gt;,&lt;string
+variable&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Read an entire line of text from a sequential file
+&lt;file number&gt; and assign it to a string variable.</p>
+</td>
+</table>
+<a name="2.21. LSET and RSET"></a>
+<h2>2.21. LSET and RSET</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>To be implemented</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<a name="2.22. MID$"></a>
+<h2>2.22. MID$</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>MID$(&lt;string expr1&gt;,n[,m])=&lt;string
+expr2&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To replace a portion of a string with another string
+value. The characters of &lt;string expr2&gt; replaces
+characters in &lt;string expr1&gt; starting at position n.
+If m is present, at most m characters are copied, otherwise
+all characters are copied. However, the string obtained
+never exceeds the length of string expr1.</p>
+</td>
+</table>
+<a name="2.23. ON ERROR GOTO"></a>
+<h2>2.23. ON ERROR GOTO</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p>ON ERROR GOTO &lt;line number&gt;</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To enable error handling within the BASIC program. An
+error may result from arithmetic errors, disk problems,
+interrupts, or as a result of the ERROR statement. After
+printing an error message the program is continued at the
+statements associated with &lt;line number&gt;.</p>
+</td>
+</table>
+
+<p>Error handling is disabled using ON ERROR GOTO 0.
+Subsequent errors result in an error message and program
+termination.</p>
+<a name="2.24. ON...GOSUB and ON ...GOTO"></a>
+<h2>2.24. ON...GOSUB and ON ...GOTO</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>ON &lt;expression&gt; GOSUB &lt;list of line
+numbers&gt;</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>ON &lt;expression&gt; GOTO &lt;list of line
+numbers&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To branch to one of several specified line numbers or
+subroutines, based on the result of the &lt;expression&gt;.
+The list of line numbers are considered the first, second,
+etc alternative. Branching to the first occurs when the
+expression evaluates to one, to the second alternative on
+two, etc. If the value of the expression is zero or greater
+than the number of alternatives, processing continues at the
+first statement following the ON..GOTO (ON GOSUB)
+statement.</p>
+</td>
+</table>
+
+<p>When the expression results in a negative number the an
+&quot;Illegal function call&quot; error occurs.</p>
+
+<p>BUG If the value of the expression is zero or greater
+than the number of alternatives, processing does NOT
+continue at the first statement following the ON..GOTO (ON
+GOSUB) statement.</p>
+<a name="2.25. OPEN"></a>
+<h2>2.25. OPEN</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>OPEN {&quot;i&quot; | &quot;o&quot; | &quot;r&quot; } ,
+[#]&lt;file number&gt; , &lt;file-name&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To open &lt;file-name&gt; (filename should be quoted)
+for input/reading or output. If file is not opened for
+output it has to be existent, otherwise an &quot;file not
+found&quot; error will occur.</p>
+</td>
+</table>
+<a name="2.26. OPTION BASE"></a>
+<h2>2.26. OPTION BASE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="26%">
+
+<p>OPTION BASE n</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To declare the lower bound of subsequent array
+subscripts as either 0 or 1. The default lower bound is
+zero.</p>
+</td>
+</table>
+<a name="2.27. POKE"></a>
+<h2>2.27. POKE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p>POKE &lt;expr1&gt;,&lt;expr2&gt;</p>
+</td>
+<td width="39%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To poke around in memory. The use of this statement is
+not recommended, because it requires full understanding of
+both the implementation of the Amsterdam Compiler Kit and
+the hardware characteristics.</p>
+</td>
+</table>
+<a name="2.28. PRINT"></a>
+<h2>2.28. PRINT</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>PRINT &lt;list of variables and/or constants&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To print constants or the contents of variables on the
+terminal-device. If the variables or constants are seperated
+by comma&rsquo;s the values will be printed seperated by
+tabs. If the variables or constants are seperated by
+semi-colon&rsquo;s the values will be printed without spaces
+in between. The new-line generated at the end of the
+print-statement can be suppressed by a semi-colon at the end
+of list of variables or constants.</p>
+</td>
+</table>
+<a name="2.29. PRINT USING"></a>
+<h2>2.29. PRINT USING</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>To be implemented</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<a name="2.30. PUT"></a>
+<h2>2.30. PUT</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>To be implemented</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<a name="2.31. RANDOMIZE"></a>
+<h2>2.31. RANDOMIZE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p>RANDOMIZE [&lt;expression&gt;]</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To reset the random seed. When the expression is
+ommitted, the system will ask for a value between -32768 and
+32767. The random number generator returns the same sequence
+of values provided the same seed is used.</p>
+</td>
+</table>
+<a name="2.32. READ"></a>
+<h2>2.32. READ</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p>READ &lt;list of variables&gt;</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To read values from the DATA statements and assign them
+to variables. The type of the variables should match to the
+type of the items being read, otherwise a &quot;Syntax
+error&quot; occurs. If all data is read the message
+&quot;Out of data&quot; will be displayed.</p>
+</td>
+</table>
+<a name="2.33. REM"></a>
+<h2>2.33. REM</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="24%">
+
+<p>REM &lt;remark&gt;</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To include explantory information in a program. The REM
+statements are not executed. A single quote has the same
+effect as : REM, which allows for the inclusion of comment
+at the end of the line.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>remarks</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>Microsoft BASIC does not allow REM statements as part of
+DATA lines.</p>
+</td>
+</table>
+<a name="2.34. RESTORE"></a>
+<h2>2.34. RESTORE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p>RESTORE [&lt;line number&gt;]</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To allow DATA statements to be re-read from a specific
+line. After a RESTORE statement is executed, the next READ
+accesses the first item of the DATA statements. If &lt;line
+number&gt; is specified, the next READ accesses the first
+item in the specified line.</p>
+</td>
+</table>
+
+<p>Note that data statements result in a sequential
+datafile generated by the compiler, being read by the read
+statements. This data file may be replaced using the
+operating system functions with a modified version, provided
+the same layout of items (same number of lines and items per
+line) is used.</p>
+<a name="2.35. STOP"></a>
+<h2>2.35. STOP</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="8%">
+
+<p>STOP</p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To terminate the execution of a program and return to
+the operating system command interpreter. A STOP statement
+results in the message &quot;Break in line ???&quot;</p>
+</td>
+</table>
+<a name="2.36. SWAP"></a>
+<h2>2.36. SWAP</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p>SWAP &lt;variable&gt;,&lt;variable&gt;</p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To exchange the values of two variables.</p>
+</td>
+<td width="0%">
+</td>
+</table>
+
+<p>BUG. Strings cannot be swapped !</p>
+<a name="2.37. TRON/TROFF"></a>
+<h2>2.37. TRON/TROFF</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="8%">
+
+<p>TRON</p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="10%">
+
+<p>TROFF</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>As an aid in debugging the TRON statement results in a
+program listing each line being interpreted. TROFF disables
+generation of this code.</p>
+</td>
+</table>
+<a name="2.38. WHILE...WEND"></a>
+<h2>2.38. WHILE...WEND</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="36%">
+
+<p>WHILE &lt;expression&gt; ..... WEND</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To execute a series of BASIC statements as long as a
+conditional expression is true. WHILE...WEND loops may be
+nested.</p>
+</td>
+</table>
+<a name="2.39. WRITE"></a>
+<h2>2.39. WRITE</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="58%">
+
+<p>WRITE [&lt;list of expressions&gt;]</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To write data at the terminal in DATA statement layout
+conventions. The expressions should be separated by
+commas.</p>
+</td>
+</table>
+<a name="2.40. WRITE #"></a>
+<h2>2.40. WRITE #</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><b>syntax</b></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>WRITE #&lt;file number&gt; ,&lt;list of
+expressions&gt;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><b>purpose</b></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>To write a sequential data file, being opened with the
+&quot;O&quot; mode. The values are being writting using the
+DATA statements layout conventions.</p>
+</td>
+</table>
+<a name="3. FUNCTIONS"></a>
+<h2>3. FUNCTIONS</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>ABS(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the absolute value of expression X</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>ASC(X$)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the numeric value of the first character of the
+string. If X$ is not initialized an &quot;Illegal function
+call&quot; error is returned.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>ATN(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the arctangent of X in radians. Result is in the
+range of -pi/2 to pi/2.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>CDBL(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts X to a double precision number.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>CHR$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts the integer value X to its ASCII character. X
+must be in the range of 0 to 257. It is used for cursor
+addressing and generating bel signals.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>CINT(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts X to an integer by rounding the fractional
+portion. If X is not in the range -32768 to 32767 an
+&quot;Overflow&quot; error occurs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>COS(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the cosine of X in radians.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>CSNG(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts X to a single precision number.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="28%">
+
+<p>CVI(&lt;2-bytes&gt;)</p>
+</td>
+<td width="22%"></td>
+<td width="50%">
+
+<p>Convert two byte string value to integer number.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="28%">
+
+<p>CVS(&lt;4-bytes&gt;)</p>
+</td>
+<td width="22%"></td>
+<td width="50%">
+
+<p>Convert four byte string value to single precision
+number.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="28%">
+
+<p>CVD(&lt;8-bytes&gt;)</p>
+</td>
+<td width="22%"></td>
+<td width="50%">
+
+<p>Convert eight byte string value to double precision
+number.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="40%">
+
+<p>EOF[(&lt;file-number&gt;)]</p>
+</td>
+<td width="10%"></td>
+<td width="50%">
+
+<p>Returns -1 (true) if the end of a sequential file has
+been reached.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>EXP(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns e(base of natural logarithm) to the power of X.
+X should be less then 10000.0.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>FIX(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the truncated integer part of X. FIX(X) is
+equivalent to SGN(X)*INT(ABS(X)). The major difference
+between FIX and INT is that FIX does not return the next
+lower number for negative X.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>HEX$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the string which represents the hexadecimal
+value of the decimal argument. X is rounded to an integer
+using CINT before HEX$ is evaluated.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>INT(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the largest integer &lt;= X.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="28%">
+
+<p>INP$(X[,[#]Y])</p>
+</td>
+<td width="22%"></td>
+<td width="50%">
+
+<p>Returns the string of X characters read from the
+terminal or the designated file.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>LEN(X$)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the number of characters in the string X$. Non
+printable and blancs are counted too.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="36%">
+
+<p>LOC(&lt;file number&gt;)</p>
+</td>
+<td width="14%"></td>
+<td width="50%">
+
+<p>For sequential files LOC returns position of the
+read/write head, counted in number of bytes. For random
+files the function returns the record number just read or
+written from a GET or PUT statement. If nothing was read or
+written 0 is returned.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>LOG(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the natural logarithm of X. X must be greater
+than zero.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p>MID$(X,I,[J])</p>
+</td>
+<td width="24%"></td>
+<td width="50%">
+
+<p>Returns first J characters from string X starting at
+position I in X. If J is omitted all characters starting of
+from position I in X are returned.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>MKI$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts an integer expression to a two-byte string.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>MKS$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts a single precision expression to a four-byte
+string.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>MKD$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Converts a double precision expression to a eight-byte
+string.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>OCT$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the string which represents the octal value of
+the decimal argument. X is rounded to an integer using CINT
+before OCTS is evaluated.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>PEEK(I)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the byte read from the indicated memory. (Of
+limited use in the context of ACK)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>POS(I)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the current cursor position. To be
+implemented.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>RIGHT$(X$,I)</p>
+</td>
+<td width="26%"></td>
+<td width="50%">
+
+<p>Returns the right most I characters of string X$. If I=0
+then the empty string is returned.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>RND(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns a random number between 0 and 1. X is a dummy
+argument.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>SGN(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>If X&gt;0 , SGN(X) returns 1.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="49%"></td>
+<td width="50%">
+<p>if X=0, SGN(X) returns 0.<br>
+if X&lt;0, SGN(X) returns -1.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>SIN(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the sine of X in radians.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>SPACE$(X)</p>
+</td>
+<td width="32%"></td>
+<td width="50%">
+
+<p>Returns a string of spaces length X. The expression X is
+rounded to an integer using CINT.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>STR$(X)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the string representation value of X.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>STRING$(I,J)</p>
+</td>
+<td width="26%"></td>
+<td width="50%">
+
+<p>Returns thes string of length Iwhose characters all have
+ASCII code J. (or first character when J is a string)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>TAB(I)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Spaces to position I on the terminal. If the current
+print position is already beyond space I,TAB goes to that
+position on the next line. Space 1 is leftmost position, and
+the rightmost position is width minus 1. To be used within
+PRINT statements only.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>TAN(X)</p>
+</td>
+<td width="38%"></td>
+<td width="50%">
+
+<p>Returns the tangent of X in radians. If TAN overflows
+the &quot;Overflow&quot; message is displayed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>VAL(X$)</p>
+</td>
+<td width="36%"></td>
+<td width="50%">
+
+<p>Returns the numerical value of string X$. The VAL
+function strips leading blanks and tabs from the argument
+string.</p>
+</td>
+</table>
+<a name="APPENDIX A DIFFERENCES WITH MICROSOFT BASIC"></a>
+<h2>APPENDIX A DIFFERENCES WITH MICROSOFT BASIC</h2>
+
+<p>The following list of Microsoft commands and statements
+are not recognized by the compiler.</p>
+<pre>     SPC
+     USR
+     VARPTR
+     AUTO
+     CHAIN
+     CLEAR
+     CLOAD
+     COMMON
+     CONT
+     CSAVE
+     DELETE
+     EDIT
+     ERASE
+     FRE
+     KILL
+     LIST
+     LLIST
+     LOAD
+     LPRINT
+     MERGE
+     NAME
+     NEW
+     NULL
+     RENUM
+     RESUME
+     RUN
+     SAVE
+     WAIT
+     WIDTH LPRINT
+</pre>
+
+<p>Some statements are in the current implementation not
+available, but will be soon. These include:</p>
+<pre>     CALL
+     DEFUSR
+     FIELD
+     GET
+     INKEY
+     INPUT$
+     INSTR$
+     LEFT$
+     LSET
+     RSET
+     PUT
+</pre>
+<a name="APPENDIX B RESERVED WORDS IN BASIC-EM"></a>
+<h2>APPENDIX B RESERVED WORDS IN BASIC-EM</h2>
+
+<p>The following list of words/symbols/names/identifiers
+are reserved, which means that they can not be used for
+variable-names.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="11" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ABS</p>
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>AND</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ASC</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>AS<br>
+ATN</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>AUTO</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>BASE</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CALL<br>
+CDBL</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CHAIN</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CHR</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CINT<br>
+CLEAR</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CLOAD</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>CLOSE</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>COMMON<br>
+CONT</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>COS</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CSNG</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CSAVE<br>
+CVI</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CVS</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>CVD</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>DATA<br>
+DEFINT</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>DEFSNG</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>DEFDBL</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>DEFSTR<br>
+DEF</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>DELETE</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>DIM</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>EDIT<br>
+ELSE</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>END</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>EOF</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ERASE<br>
+ERROR</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ERR</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ERL</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ELSE<br>
+EQV</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>EXP</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>FIELD</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>FIX<br>
+FOR</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>FRE</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>GET</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>GOSUB<br>
+GOTO</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>HEX</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>IF</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>IMP<br>
+INKEY</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>INPUT</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>INP</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>INSTR<br>
+INT</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>KILL</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LEFT</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LEN</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LET</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LINE</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LIST</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LLIST<br>
+LOAD</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LOC</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LOG</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>LPOS<br>
+LPRINT</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>LSET</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>MERGE</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>MID<br>
+MKI</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>MKS</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>MKD</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>MOD<br>
+NAME</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>NEW</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>NEXT</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>NOT</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>NULL</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ON</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>OCT</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>OPEN<br>
+OPTION</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>OR</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>OUT</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>PEEK<br>
+POKE</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>PRINT</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>POS</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>PUT<br>
+RANDOMIZE</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>READ</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>REM</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>RENUM<br>
+REN</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>RESTORE</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>RESUME</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>RETURN<br>
+RIGHT</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>RND</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>RUN</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SAVE<br>
+STEP</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SGN</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SIN</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SPACE<br>
+SPC</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SQR</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>STOP</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>STRING<br>
+STR</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>SWAP</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>TAB</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>TAN<br>
+THEN</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>TO</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>TRON</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>TROFF<br>
+USING</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>USR</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>VAL</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>VARPTR<br>
+WAIT</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>WHILE</p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>WEND</p>
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>WIDTH<br>
+WRITE</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>XOR</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/basic.pdf b/doc/tack/basic.pdf
new file mode 100644 (file)
index 0000000..0848c96
Binary files /dev/null and b/doc/tack/basic.pdf differ
diff --git a/doc/tack/ceg.html b/doc/tack/ceg.html
new file mode 100644 (file)
index 0000000..9824842
--- /dev/null
@@ -0,0 +1,1917 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:36 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The Code Expander Generator</title>
+</head>
+<body>
+
+<h1 align=center>The Code Expander Generator</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The code expander generator">2. The code expander generator</a><br>
+<a href="#3. Description of the EM_table">3. Description of the EM_table</a><br>
+<a href="#3.1. Grammar">3.1. Grammar</a><br>
+<a href="#3.2. Semantics">3.2. Semantics</a><br>
+<a href="#3.2.1. Actions">3.2.1. Actions</a><br>
+<a href="#3.2.2. Labels">3.2.2. Labels</a><br>
+<a href="#3.2.3. Arguments of an EM instruction">3.2.3. Arguments of an EM instruction</a><br>
+<a href="#3.2.4. Conditionals">3.2.4. Conditionals</a><br>
+<a href="#3.2.5. Abbreviations">3.2.5. Abbreviations</a><br>
+<a href="#3.2.6. Implicit arguments">3.2.6. Implicit arguments</a><br>
+<a href="#3.2.7. Pseudo instructions">3.2.7. Pseudo instructions</a><br>
+<a href="#3.2.8. Storage instructions">3.2.8. Storage instructions</a><br>
+<a href="#3.3. User supplied definitions and functions">3.3. User supplied definitions and functions</a><br>
+<a href="#3.4. Generating assembly code">3.4. Generating assembly code</a><br>
+<a href="#4. Description of the as_table">4. Description of the as_table</a><br>
+<a href="#4.1. Grammar">4.1. Grammar</a><br>
+<a href="#4.2. Semantics">4.2. Semantics</a><br>
+<a href="#4.2.1. Rules">4.2.1. Rules</a><br>
+<a href="#4.2.2. Declaration of types.">4.2.2. Declaration of types.</a><br>
+<a href="#4.2.3. The function of the @-sign and the if-statement.">4.2.3. The function of the @-sign and the if-statement.</a><br>
+<a href="#4.2.4. References to operands">4.2.4. References to operands</a><br>
+<a href="#4.2.5. The functions assemble() and block_assemble()">4.2.5. The functions assemble() and block_assemble()</a><br>
+<a href="#4.3. Generating assembly code">4.3. Generating assembly code</a><br>
+<a href="#5. Building a code expander">5. Building a code expander</a><br>
+<a href="#5.1. Phase one">5.1. Phase one</a><br>
+<a href="#5.2. Phase two">5.2. Phase two</a><br>
+<a href="#6. Acknowledgements">6. Acknowledgements</a><br>
+<a href="#7. References">7. References</a><br>
+<a href="#References">References</a><br>
+<a href="#Appendix A, the back -primitives">Appendix A, the back -primitives</a><br>
+<a href="#Appendix B, description of ACK-a.out library">Appendix B, description of ACK-a.out library</a><br>
+
+<hr>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>A <b>code expander</b> (<b>ce</b> for short) is a part
+of the Amsterdam Compiler Kit
+<sup><small><small>1</small></small></sup> (<b>ACK</b>) and
+provides the user with high-speed generation of
+medium-quality code. Although conceptually equivalent to the
+more usual <b>code generator</b>, it differs in some
+aspects.</p>
+
+<p>Normally, a program to be compiled with <b>ACK</b> is
+first fed to the preprocessor. The output of the
+preprocessor goes into the appropriate front end, which
+produces EM <sup><small><small>2</small></small></sup> (a
+machine independent low level intermediate code). The
+generated EM code is fed into the peephole optimizer, which
+scans it with a window of a few instructions, replacing
+certain inefficient code sequences by better ones. After the
+peephole optimizer a back end follows, which produces
+high-quality assembly code. The assembly code goes via the
+target optimizer into the assembler and the object code then
+goes into the linker/loader, the final component in the
+pipeline.</p>
+
+<p>For various applications this scheme is too slow. When
+debugging, for example, compile time is more important than
+execution time of a program. For this purpose a new scheme
+is introduced:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>The code generator and assembler are replaced by a
+library, the <b>code expander</b>, consisting of a set of
+routines, one for every EM-instruction. Each routine expands
+its EM-instruction into relocatable object code. In
+contrast, the usual ACK code generator uses expensive
+pattern matching on sequences of EM-instructions. The
+peephole and target optimizer are not used.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>These routines replace the usual EM-generating routines
+in the front end; this eliminates the overhead of
+intermediate files.</p>
+</td>
+</table>
+
+<p>This results in a fast compiler producing object file,
+ready to be linked and loaded, at the cost of unoptimized
+object code.</p>
+
+<p>Because of the simple nature of the code expander, it is
+much easier to build, to debug, and to test. Experience has
+demonstrated that a code expander can be constructed,
+debugged, and tested in less than two weeks.</p>
+
+<p>This document describes the tools for automatically
+generating a <b>ce</b> (a library of C files) from two
+tables and a few machine-dependent functions. A thorough
+knowledge of EM is necessary to understand this
+document.</p>
+<a name="2. The code expander generator"></a>
+<h2>2. The code expander generator</h2>
+
+<p>The code expander generator (<b>ceg</b>) generates a
+code expander from two tables and a few machine-dependent
+functions. This section explains how <b>ceg</b> works. The
+first half describes the transformations that are done on
+the two tables. The second half tells how these
+transformations are done by the <b>ceg</b>.</p>
+
+<p>A code expander consists of a set of routines that
+convert EM-instructions directly to relocatable object code.
+These routines are called by a front end through the
+EM_CODE(3ACK) <sup><small><small>3</small></small></sup>
+interface. To free the table writer of the burden of
+building an object file, we supply a set of routines that
+build an object file in the ACK.OUT(5ACK)
+<sup><small><small>4</small></small></sup> format (see
+appendix B). This set of routines is called the
+<b>back</b>-primitives (see appendix A). In short, a code
+expander consists of a set of routines that map the EM_CODE
+interface on the <b>back</b>-primitives interface.</p>
+
+<p>To avoid repetition of the same sequences of
+<b>back</b>-primitives in different EM-instructions and to
+improve readability, the EM-to-object information must be
+supplied in two tables. The EM_table maps EM to an assembly
+language, and the as_table maps assembly code to
+<b>back</b>-primitives. The assembly language is chosen by
+the table writer. It can either be an actual assembly
+language or his ad-hoc designed language.</p>
+
+<p>The following picture shows the dependencies between the
+different components:</p>
+
+<p align=center><img src="grohtml-106561.png"></p>
+
+<p>The picture suggests that, during compilation, the EM
+instructions are first transformed into assembly
+instructions and then the assembly instructions are
+transformed into object-generating calls. This is not what
+happens in practice, although the user is free to think it
+does. Actually, however the EM_table and the as_table are
+combined during code expander generation time, yielding an
+imaginary compound table that results in routines from the
+EM_CODE interface that generate object code directly.</p>
+
+<p>As already indicated, the compound table does not exist
+either. Instead, each assembly instruction in the as_table
+is converted to a routine generating C
+<sup><small><small>5</small></small></sup> code to generate
+C code to call the <b>back</b>-primitives. The EM_table is
+converted into a program that for each EM instruction
+generates a routine, using the routines generated from the
+as_table. Execution of the latter program will then generate
+the code expander.</p>
+
+<p>This scheme allows great flexibility in the table
+writing, while still resulting in a very efficient code
+expander. One implication is that the as_table is
+interpreted twice and the EM_table only once. This has
+consequences for their structure.</p>
+
+<p>To illustrate what happens, we give an example. The
+example is an entry in the tables for the VAX-machine. The
+assembly language chosen is a subset of the VAX assembly
+language.</p>
+
+<p>One of the most fundamental operations in EM is
+&lsquo;&lsquo;loc c&rsquo;&rsquo;, load the value of c on
+the stack. To expand this instruction the tables contain the
+following information:</p>
+<pre>     EM_table   :
+        C_loc   ==&gt;   &quot;pushl $$$1&quot;.
+          /* $1 refers to the first argument of C_loc.
+           * $$ is a quoted $. */
+
+
+
+
+     as_table   :
+        pushl  src : CONST   ==&gt;
+                              @text1( 0xd0);
+                              @text1( 0xef);
+                              @text4( %$( src-&gt;num)).
+</pre>
+
+<p>The as_table is transformed in the following
+routine:</p>
+<pre>     pushl_instr(src)
+     t_operand *src;
+     /* &lsquo;&lsquo;t_operand&rsquo;&rsquo; is a struct defined by the
+      * table writer. */
+     {
+        printf(&quot;swtxt();&quot;);
+        printf(&quot;text1( 0xd0 );&quot;);
+        printf(&quot;text1( 0xef );&quot;);
+        printf(&quot;text4(%s);&quot;, substitute_dollar( src-&gt;num));
+     }
+</pre>
+
+<p>Using &lsquo;&lsquo;pushl_instr()&rsquo;&rsquo;, the
+following routine is generated from the EM_table:</p>
+<pre>     C_loc( c)
+     arith c;
+     /* text1() and text4() are library routines that fill the
+      * text segment. */
+     {
+         swtxt();
+         text1( 0xd0);
+         text1( 0xef);
+         text4( c);
+     }
+</pre>
+
+<p>A compiler call to &lsquo;&lsquo;C_loc()&rsquo;&rsquo;
+will cause the 1-byte numbers
+&lsquo;&lsquo;0xd0&rsquo;&rsquo; and
+&lsquo;&lsquo;0xef&rsquo;&rsquo; and the 4-byte value of the
+variable &lsquo;&lsquo;c&rsquo;&rsquo; to be stored in the
+text segment.</p>
+
+<p>The transformations on the tables are done automatically
+by the code expander generator. The code expander generator
+is made up of two tools: <b>emg</b> and <b>asg</b>.
+<b>Asg</b> transforms each assembly instruction into a C
+routine. These C routines generate calls to the
+<b>back</b>-primitives. The generated C routines are used by
+<b>emg</b> to generate the actual code expander from the
+EM_table.</p>
+
+<p>The link between <b>emg</b> and <b>asg</b> is an
+assembly language. We did not enforce a specific syntax for
+the assembly language; instead we have given the table
+writer the freedom to make an ad-hoc assembly language or to
+use an actual assembly language suitable for his purpose.
+Apart from a greater flexibility this has another advantage;
+if the table writer adopts the assembly language that runs
+on the machine at hand, he can test the EM_table
+independently from the as_table. Of course there is a price
+to pay: the table writer has to do the decoding of the
+operands himself. See section 4 for more details.</p>
+
+<p>Before we describe the structure of the tables in
+detail, we will give an overview of the four main
+phases.</p>
+
+<p>phase 1:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The as_table is transformed by <b>asg</b>. This results
+in a set of C routines. Each assembly-opcode generates one C
+routine. Note that a call to such a routine does not
+generate the corresponding object code; it generates C code,
+which, when executed, generates the desired object code.</p>
+</td>
+</table>
+
+<p>phase 2:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The C routines generated by <b>asg</b> are used by emg to
+expand the EM_table. This results in a set of C routines,
+the code expander, which conform to the procedural interface
+EM_CODE(3ACK). A call to such a routine does indeed generate
+the desired object code.</p>
+</td>
+</table>
+
+<p>phase 3:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The front end that uses the procedural interface is
+linked/loaded with the code expander generated in phase 2
+and the <b>back</b>-primitives (a supplied library). This
+results in a compiler.</p>
+</td>
+</table>
+
+<p>phase 4:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The compiler runs. The routines in the code expander are
+executed and produce object code.</p>
+</td>
+</table>
+<a name="3. Description of the EM_table"></a>
+<h2>3. Description of the EM_table</h2>
+
+<p>This section describes the EM_table. It contains four
+subsections. The first 3 sections describe the syntax of the
+EM_table, the semantics of the EM_table, and the functions
+and constants that must be present in the EM_table, in the
+file &lsquo;&lsquo;mach.c&rsquo;&rsquo; or in the file
+&lsquo;&lsquo;mach.h&rsquo;&rsquo;. The last section
+explains how a table writer can generate assembly code
+instead of object code. The section on semantics contains
+many examples.</p>
+<a name="3.1. Grammar"></a>
+<h2>3.1. Grammar</h2>
+
+<p>The following grammar describes the syntax of the
+EM_table.</p>
+
+<p align=center><img src="grohtml-106562.png"></p>
+
+<p>The &lsquo;&lsquo;(&rsquo;&rsquo;
+&lsquo;&lsquo;)&rsquo;&rsquo; brackets are used for
+grouping, &lsquo;&lsquo;[&rsquo;&rsquo; ...
+&lsquo;&lsquo;]&rsquo;&rsquo; means ... 0 or 1 time, a
+&lsquo;&lsquo;*&rsquo;&rsquo; means zero or more times, and
+a &lsquo;&lsquo;|&rsquo;&rsquo; means a choice between left
+or right. A <b>C_instr</b> is a name in the EM_CODE(3ACK)
+interface. <b>condition</b> is a C expression.
+<b>function-call</b> is a call of a C function.
+<b>label</b>, <b>mnemonic</b>, and <b>operand</b> are
+arbitrary strings. If an <b>operand</b> contains brackets,
+the brackets must match. There is an upper bound on the
+number of operands; the maximum number is defined by the
+constant MAX_OPERANDS in de file
+&lsquo;&lsquo;const.h&rsquo;&rsquo; in the directory
+assemble.c. Comments in the table should be placed between
+&lsquo;&lsquo;/*&rsquo;&rsquo; and
+&lsquo;&lsquo;*/&rsquo;&rsquo;. The table is processed by
+the C preprocessor, before being parsed by <b>emg</b>.</p>
+<a name="3.2. Semantics"></a>
+<h2>3.2. Semantics</h2>
+
+<p>The EM_table is processed by <b>emg</b>. <b>Emg</b>
+generates a C function for every instruction in the
+EM_CODE(3ACK). For every EM-instruction not mentioned in the
+EM_table, a C function that prints an error message is
+generated. It is possible to divide the
+EM_CODE(3ACK)-interface into four parts :</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>text instructions (e.g., C_loc, C_adi, ..)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>pseudo instructions (e.g., C_open, C_df_ilb, ..)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>storage instructions (e.g., C_rom_icon, ..)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>message instructions (e.g., C_mes_begin, ..)</p>
+</td>
+</table>
+
+<p>This section starts with giving the semantics of the
+grammar. The examples are text instructions. The section
+ends with remarks on the pseudo instructions and the storage
+instructions. Since message instructions are not useful for
+a code expander, they are ignored.</p>
+<a name="3.2.1. Actions"></a>
+<h2>3.2.1. Actions</h2>
+
+<p>The EM_table is made up of rules describing how to
+expand a <b>C_instr</b> defined by the
+EM_CODE(3ACK)-interface (corresponding to an EM instruction)
+into actions. There are two kinds of actions: assembly
+instructions and C function calls. An assembly instruction
+is defined as a mnemonic followed by zero or more operands
+separated by commas. The semantics of an assembly
+instruction is defined by the table writer. When the
+assembly language is not expressive enough, then, as an
+escape route, function calls can be made. However, this
+reduces the speed of the actual code expander. Finally,
+actions can be grouped into a list of actions; actions are
+separated by a semicolon and terminated by a
+&lsquo;&lsquo;.&rsquo;&rsquo;.</p>
+<pre>     C_nop   ==&gt; .
+            /* Empty action list : no operation. */
+
+
+     C_inc   ==&gt; &quot;incl (sp)&quot;.
+            /* Assembler instruction, which is evaluated
+             * during expansion of the EM_table */
+
+
+     C_slu   ==&gt; C_sli( $1).
+            /* Function call, which is evaluated during
+             *  execution of the compiler. */
+</pre>
+<a name="3.2.2. Labels"></a>
+<h2>3.2.2. Labels</h2>
+
+<p>Since an assembly language without instruction labels is
+a rather weak language, labels inside a contiguous block of
+assembly instructions are allowed. When using labels two
+rules must be observed:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>The name of a label should be unique inside an action
+list.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>The labels used in an assembler instruction should be
+defined in the same action list.</p>
+</td>
+</table>
+
+<p>The following example illustrates the usage of
+labels.</p>
+<pre>        /* Compare the two top elements on the stack. */
+     C_cmp      ==&gt;     &quot;pop bx&quot;;
+                        &quot;pop cx&quot;;
+                        &quot;xor ax, ax&quot;;
+                        &quot;cmp cx, bx&quot;;
+                     /* Forward jump to local label */
+                        &quot;je 2f&quot;;
+                        &quot;jb 1f&quot;;
+                        &quot;inc ax&quot;;
+                        &quot;jmp 2f&quot;;
+                        &quot;1: dec ax&quot;;
+                        &quot;2: push ax&quot;.
+</pre>
+
+<p>We will come back to labels in the section on the
+as_table.</p>
+<a name="3.2.3. Arguments of an EM instruction"></a>
+<h2>3.2.3. Arguments of an EM instruction</h2>
+
+<p>In most cases the translation of a <b>C_instr</b>
+depends on its arguments. The arguments of a <b>C_instr</b>
+are numbered from 1 to <i>n</i>, where <i>n</i> is the total
+number of arguments of the current <b>C_instr</b> (there are
+a few exceptions, see Implicit arguments). The table writer
+may refer to an argument as $<i>i</i>. If a plain $-sign is
+needed in an assembly instruction, it must be preceded by a
+extra $-sign.</p>
+
+<p>There are two groups of <b>C_instr</b>s whose arguments
+are handled specially:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>1: Instructions dealing with local offsets</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>The value of the $<i>i</i> argument referring to a
+parameter ($<i>i</i> &gt;= 0) is increased by
+&lsquo;&lsquo;EM_BSIZE&rsquo;&rsquo;.
+&lsquo;&lsquo;EM_BSIZE&rsquo;&rsquo; is the size of the
+return status block and must be defined in the file
+&lsquo;&lsquo;mach.h&rsquo;&rsquo; (see section 3.3). For
+example :</p>
+<!-- INDENTATION -->
+<pre>     C_lol   ==&gt;     &quot;push $1(bp)&quot;.
+            /* automatic conversion of $1 */
+</pre>
+</td>
+</table>
+<!-- INDENTATION -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>2: Instructions using global names or instruction
+labels</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>All the arguments referring to global names or
+instruction labels will be transformed into a unique
+assembly name. To prevent name clashes with library names
+the table writer has to provide the conversions in the file
+&lsquo;&lsquo;mach.h&rsquo;&rsquo;. For example :</p>
+<!-- INDENTATION -->
+<pre>     C_bra   ==&gt;     &quot;jmp $1&quot;.
+             /* automatic conversion of $1 */
+             /* type arith is converted to string */
+</pre>
+</td>
+</table>
+<a name="3.2.4. Conditionals"></a>
+<h2>3.2.4. Conditionals</h2>
+
+<p>The rules in the EM_table can be divided into two
+groups: simple rules and conditional rules. The simple rules
+are made up of a <b>C_instr</b> followed by a list of
+actions, as described above. The conditional rules
+(COND_SEQUENCE) allow the table writer to select an action
+list depending on the value of a condition.</p>
+
+<p>A CONDITIONAL is a list of a boolean expression with the
+corresponding simple rule. If the expression evaluates to
+true then the corresponding simple rule is carried out. If
+more than one condition evaluates to true, the first one is
+chosen. The last case of a COND_SEQUENCE of a <b>C_instr</b>
+must handle the default case. The boolean expressions in a
+COND_SEQUENCE must be C expressions. Besides the ordinary C
+operators and constants, $<i>i</i> references can be used in
+an expression.</p>
+<pre>         /* Load address of LB $1 levels back. */
+     C_lxl
+         $1 == 0    ==&gt;    &quot;pushl fp&quot;.
+         $1 == 1    ==&gt;    &quot;pushl 4(ap)&quot;.
+         default    ==&gt;    &quot;movl $$$1, r0&quot;;
+                           &quot;jsb .lxl&quot;;
+                           &quot;pushl r0&quot;.
+</pre>
+<a name="3.2.5. Abbreviations"></a>
+<h2>3.2.5. Abbreviations</h2>
+
+<p>EM instructions with an external as an argument come in
+three variants in the EM_CODE(3ACK) interface. In most cases
+it will be possible to take these variants together. For
+this purpose the &lsquo;&lsquo;..&rsquo;&rsquo; notation is
+introduced. For the code expander there is no difference
+between the following instructions.</p>
+<pre>     C_loe_dlb    ==&gt;    &quot;pushl $1 + $2&quot;.
+     C_loe_dnam   ==&gt;    &quot;pushl $1 + $2&quot;.
+     C_loe        ==&gt;    &quot;pushl $1 + $2&quot;.
+</pre>
+
+<p>So it can be written in the following way.</p>
+<pre>     C_loe..      ==&gt;    &quot;pushl $1 + $2&quot;.
+</pre>
+<a name="3.2.6. Implicit arguments"></a>
+<h2>3.2.6. Implicit arguments</h2>
+
+<p>In the last example &lsquo;&lsquo;C_loe&rsquo;&rsquo;
+has two arguments, but in the EM_CODE interface it has one
+argument. This argument depends on the current
+&lsquo;&lsquo;hol&rsquo;&rsquo; block; in the EM_table this
+is made explicit. Every <b>C_instr</b> whose argument
+depends on a &lsquo;&lsquo;hol&rsquo;&rsquo; block has one
+extra argument; argument 1 refers to the
+&lsquo;&lsquo;hol&rsquo;&rsquo; block.</p>
+<a name="3.2.7. Pseudo instructions"></a>
+<h2>3.2.7. Pseudo instructions</h2>
+
+<p>Most pseudo instructions are machine independent and are
+provided by <b>ceg</b>. The table writer has only to supply
+the following functions, which are used to build a
+stackframe:</p>
+<pre>     C_prolog()
+     /* Performs the prolog, for example save
+      * return address */
+
+
+     C_locals( n)
+     arith n;
+     /* Allocate n bytes for locals on the stack */
+
+
+     C_jump( label)
+     char *label;
+     /* Generates code for a jump to &lsquo;&lsquo;label&rsquo;&rsquo; */
+</pre>
+
+<p>These functions can be defined in
+&lsquo;&lsquo;mach.c&rsquo;&rsquo; or in the EM_table (see
+section 3.3).</p>
+<a name="3.2.8. Storage instructions"></a>
+<h2>3.2.8. Storage instructions</h2>
+
+<p>The storage instructions
+&lsquo;&lsquo;C_bss_<i>cstp()</i>&rsquo;&rsquo;,
+&lsquo;&lsquo;C_hol_<i>cstp()</i>&rsquo;&rsquo;, dealing
+with constants of type string (C_..._icon, C_..._ucon,
+C_..._fcon), are generated automatically. No information is
+needed in the table. To generate the C_..._icon, C_..._ucon,
+C_..._fcon instructions <b>ceg</b> only has to know how to
+convert a number of type string to bytes; this can be
+defined with the constants ONE_BYTE, TWO_BYTES, and
+FOUR_BYTES. C_rom_icon, C_con_icon, C_bss_icon, C_hol_icon
+can be abbreviated by ..icon. This also holds for ..ucon and
+..fcon. For example :</p>
+<pre>     \.\.icon
+         $2 == 1   ==&gt;  gen1( (ONE_BYTE) atoi( $1)).
+         $2 == 2   ==&gt;  gen2( (TWO_BYTES) atoi( $1)).
+         $2 == 4   ==&gt;  gen4( (FOUR_BYTES) atol( $1)).
+         default   ==&gt;   arg_error( &quot;..icon&quot;, $2).
+</pre>
+
+<p>Gen1(), gen2() and gen4() are <b>back</b>-primitives
+(see appendix A), and generate one, two, or four byte
+constants. Atoi() is a C library function that converts
+strings to integers. The constants
+&lsquo;&lsquo;ONE_BYTE&rsquo;&rsquo;,
+&lsquo;&lsquo;TWO_BYTES&rsquo;&rsquo;, and
+&lsquo;&lsquo;FOUR_BYTES&rsquo;&rsquo; must be defined in
+the file &lsquo;&lsquo;mach.h&rsquo;&rsquo;.</p>
+<a name="3.3. User supplied definitions and functions"></a>
+<h2>3.3. User supplied definitions and functions</h2>
+
+<p>If the table writer uses all the default functions he
+has only to supply the following constants and functions
+:</p>
+
+<p align=center><img src="grohtml-106563.png"></p>
+
+<p>An example of the file
+&lsquo;&lsquo;mach.h&rsquo;&rsquo; for the vax4.</p>
+
+<p align=center><img src="grohtml-106565.png"></p>
+
+<p>Notice that EM_BSIZE is zero. The vax
+&lsquo;&lsquo;call&rsquo;&rsquo; instruction takes
+automatically care of the base block.</p>
+
+<p>There are three primitives that have to be defined by
+the table writer, either as functions in the file
+&lsquo;&lsquo;mach.c&rsquo;&rsquo; or as rules in the
+EM_table. For example, for the 8086 they look like this:</p>
+<pre>     C_jump       ==&gt;       &quot;jmp $1&quot;.
+
+
+     C_prolog     ==&gt;       &quot;push bp&quot;;
+                          &quot;mov bp, sp&quot;.
+
+
+     C_locals
+       $1  == 0   ==&gt;     .
+       $1  == 2   ==&gt;     &quot;push ax&quot;.
+       $1  == 4   ==&gt;     &quot;push ax&quot;;
+                          &quot;push ax&quot;.
+       default    ==&gt;     &quot;sub sp, $1&quot;.
+</pre>
+<a name="3.4. Generating assembly code"></a>
+<h2>3.4. Generating assembly code</h2>
+
+<p>When the code expander generator is used for generating
+assembly instead of object code (see section 5), additional
+print formats have to be defined in
+&lsquo;&lsquo;mach.h&rsquo;&rsquo;. The following table
+lists these formats.</p>
+
+<p align=center><img src="grohtml-106566.png"></p>
+<a name="4. Description of the as_table"></a>
+<h2>4. Description of the as_table</h2>
+
+<p>This section describes the as_table. Like the previous
+section, it is divided into four parts: the first two parts
+describe the grammar and the semantics of the as_table; the
+third part gives an overview of the functions and the
+constants that must be present in the as_table (in the file
+&lsquo;&lsquo;as.h&rsquo;&rsquo; or in the file
+&lsquo;&lsquo;as.c&rsquo;&rsquo;); the last part describes
+the case when assembly is generated instead of object code.
+The part on semantics contains examples that appear in the
+as_table for the VAX or for the 8086.</p>
+<a name="4.1. Grammar"></a>
+<h2>4.1. Grammar</h2>
+
+<p>The form of the as_table is given by the following
+grammar :</p>
+
+<p align=center><img src="grohtml-106567.png"></p>
+
+<p><b>mnemonic</b>, <b>operand</b>, and <b>type</b> are all
+C identifiers; <b>condition</b> is a normal C expression;
+<b>function-call</b> must be a C function call. A function
+can be called with standard C arguments or with a reference
+(see section 4.2.4). Since the as_table is interpreted
+during code expander generation as well as during code
+expander execution, two levels of calls are present in it. A
+&lsquo;&lsquo;function-call&rsquo;&rsquo; is done during
+code expander generation, a
+&lsquo;&lsquo;@function-call&rsquo;&rsquo; during code
+expander execution.</p>
+<a name="4.2. Semantics"></a>
+<h2>4.2. Semantics</h2>
+
+<p>The as_table is made up of rules that map assembly
+instructions onto <b>back</b>-primitives, a set of functions
+that construct an object file. The table is processed by
+<b>asg</b>, which generates a C functions for each assembler
+mnemonic. The names of these functions are the assembler
+mnemonics postfixed with &lsquo;&lsquo;_instr&rsquo;&rsquo;
+(e.g., &lsquo;&lsquo;add&rsquo;&rsquo; becomes
+&lsquo;&lsquo;add_instr()&rsquo;&rsquo;). These functions
+will be used by the function assemble() during the expansion
+of the EM_table. After explaining the semantics of the
+as_table the function assemble() will be described.</p>
+<a name="4.2.1. Rules"></a>
+<h2>4.2.1. Rules</h2>
+
+<p>A rule in the as_table is made up of a left and a right
+hand side; the left hand side describes an assembler
+instruction (mnemonic and operands); the right hand side
+gives the corresponding actions as <b>back</b>-primitives or
+as functions defined by the table writer, which call
+<b>back-primitives</b>. Two simple examples from the VAX
+as_table and the 8086 as_table, resp.:</p>
+<pre>     movl src, dst  ==&gt; @text1( 0xd0);
+                        gen_operand( src);
+                        gen_operand( dst).
+         /* &lsquo;&lsquo;gen_operand&rsquo;&rsquo; is a function that encodes
+          * operands by calling back-primitives. */
+
+
+     rep ens:MOVS   ==&gt;  @text1( 0xf3);
+                         @text1( 0xa5).
+
+
+</pre>
+<a name="4.2.2. Declaration of types."></a>
+<h2>4.2.2. Declaration of types.</h2>
+
+<p>In general, a machine instruction is encoded as an
+opcode followed by zero or more the operands. There are two
+methods for mapping assembler mnemonics onto opcodes: the
+mnemonic determines the opcode, or mnemonic and operands
+together determine the opcode. Both cases can be easily
+expressed in the as_table. The first case is obvious. The
+second case is handled by introducing type fields for the
+operands.</p>
+
+<p>When mnemonic and operands together determine the
+opcode, the table writer has to give several rules for each
+combination of mnemonic and operands. The rules differ in
+the type fields of the operands. The table writer has to
+supply functions that check the type of the operand. The
+name of such a function is the name of the type; it has one
+argument: a pointer to a struct of type <i>t_operand</i>; it
+returns non-zero when the operand is of this type, otherwise
+it returns 0.</p>
+
+<p>This will usually lead to a list of rules per mnemonic.
+To reduce the amount of work an abbreviation is supplied.
+Once the mnemonic is specified it can be referred to in the
+following rules by &lsquo;&lsquo;...&rsquo;&rsquo;. One has
+to make sure that each mnemonic is mentioned only once in
+the as_table, otherwise <b>asg</b> will generate more than
+one function with the same name.</p>
+
+<p>The following example shows the usage of type
+fields.</p>
+<pre>      mov dst:REG, src:EADDR  ==&gt;
+               @text1( 0x8b);                /* opcode */
+               mod_RM( %d(dst-&gt;reg), src). /* operands */
+
+
+      ... dst:EADDR, src:REG  ==&gt;
+               @text1( 0x89);                /* opcode */
+               mod_RM( %d(src-&gt;reg), dst). /* operands */
+</pre>
+
+<p>The table-writer must supply the restriction functions,
+<tt>REG</tt> and <tt>EADDR</tt> in the previous example, in
+&lsquo;&lsquo;as.c&rsquo;&rsquo; or
+&rsquo;&rsquo;as.h&rsquo;&rsquo;.</p>
+<a name="4.2.3. The function of the @-sign and the if-statement."></a>
+<h2>4.2.3. The function of the @-sign and the if-statement.</h2>
+
+<p>The right hand side of a rule is made up of function
+calls. Since the as_table is interpreted on two levels,
+during code expander generation and during code expander
+execution, two levels of calls are present in it. A
+function-call without an &lsquo;&lsquo;@&rsquo;&rsquo;-sign
+is called during code expander generation (e.g., the
+<tt>gen_operand()</tt> in the first example). A function
+call with an &lsquo;&lsquo;@&rsquo;&rsquo;-sign is called
+during code expander execution (e.g., the
+<b>back</b>-primitives). So the last group will be part of
+the compiler.</p>
+
+<p>The need for the &lsquo;&lsquo;@&rsquo;&rsquo;-sign
+construction arises, for example, when implementing push/pop
+optimization (e.g., &lsquo;&lsquo;push x&rsquo;&rsquo;
+followed by &lsquo;&lsquo;pop y&rsquo;&rsquo; can be
+replaced by &lsquo;&lsquo;move x, y&rsquo;&rsquo;). In this
+case flags need to be set, unset, and tested during the
+execution of the compiler:</p>
+<pre>PUSH src  ==&gt;   /* save in ax */
+                mov_instr( AX_oper, src);
+                /* set flag */
+                @assign( push_waiting, TRUE).
+</pre>
+<pre>     POP dst   ==&gt;   @if ( push_waiting)
+                            /* &lsquo;&lsquo;mov_instr&rsquo;&rsquo; is asg-generated */
+                            mov_instr( dst, AX_oper);
+                            @assign( push_waiting, FALSE).
+                     @else
+                            /* &lsquo;&lsquo;pop_instr&rsquo;&rsquo; is asg-generated */
+                            pop_instr( dst).
+                     @fi.
+</pre>
+
+<p>Although the @-sign is followed syntactically by a
+function name, this function can very well be the name of a
+macro defined in C. This is in fact the case with
+&lsquo;&lsquo;@assign()&rsquo;&rsquo; in the above
+example.</p>
+
+<p>The case may arise when information is needed that is
+not known until execution of the compiler. For example one
+needs to know if a &lsquo;&lsquo;$<i>i</i>&rsquo;&rsquo;
+argument fits in one byte. In this case one can use a
+special if-statement provided by <b>asg</b>: @if, @elsif,
+@else, @fi. This means that the conditions will be evaluated
+at run time of the <b>ce</b>. In such a condition one may of
+course refer to the &rsquo;&rsquo;$<i>i</i>&rsquo;&rsquo;
+arguments. For example, constants can be packed into one or
+two byte arguments as follows:</p>
+<pre>     mov dst:ACCU, src:DATA ==&gt;
+                            @if ( fits_byte( %$(dst-&gt;expr)))
+                                 @text1( 0xc0);
+                                 @text1( %$(dst-&gt;expr)).
+                            @else
+                                 @text1( 0xc8);
+                                 @text2( %$(dst-&gt;expr)).
+                            @fi.
+</pre>
+<a name="4.2.4. References to operands"></a>
+<h2>4.2.4. References to operands</h2>
+
+<p>As noted before, the operands of an assembler
+instruction may be used as pointers to the struct
+<i>t_operand</i> in the right hand side of the table.
+Because of the free format assembler, the types of the
+fields in the struct <i>t_operand</i> are unknown to
+<b>asg</b>. As these fields can appear in calls to
+functions, <b>asg</b> must know these types. This section
+explains how these types must be specified.</p>
+
+<p>References to operands come in three forms: ordinary
+operands, operands that contain
+&lsquo;&lsquo;$<i>i</i>&rsquo;&rsquo; references, and
+operands that refer to names of local labels. The
+&lsquo;&lsquo;$<i>i</i>&rsquo;&rsquo; in operands represent
+names or numbers of a <b>C_instr</b> and must be given as
+arguments to the <b>back</b>-primitives. Labels in operands
+must be converted to a number that tells the distance, the
+number of bytes, between the label and the current position
+in the text-segment.</p>
+
+<p>All these three cases are treated in an uniform way.
+When the table writer makes a reference to an operand of an
+assembly instruction, he must describe the type of the
+operand in the following way.</p>
+
+<p align=center><img src="grohtml-106568.png"></p>
+
+<p>The three cases differ only in the conversion field. The
+printformat conversion applies to ordinary operands. The
+&lsquo;&lsquo;%$&rsquo;&rsquo; applies to operands that
+contain a &lsquo;&lsquo;$<i>i</i>&rsquo;&rsquo;. The
+expression between parentheses must result in a pointer to a
+char. The result of &lsquo;&lsquo;%$&rsquo;&rsquo; is of the
+type of &lsquo;&lsquo;$<i>i</i>&rsquo;&rsquo;. The
+&lsquo;&lsquo;%dist&rsquo;&rsquo; applies to operands that
+refer to a local label. The expression between the brackets
+must result in a pointer to a char. The result of
+&lsquo;&lsquo;%dist&rsquo;&rsquo; is of type arith.</p>
+
+<p>The following example illustrates the usage of
+&lsquo;&lsquo;%$&rsquo;&rsquo;. (For an example that
+illustrates the usage of ordinary fields see the section on
+&lsquo;&lsquo;User supplied definitions and
+functions&rsquo;&rsquo;).</p>
+<pre>     jmp dst ==&gt;
+         @text1( 0xe9);
+         @reloc2( %$(dst-&gt;lab), %$(dst-&gt;off), PC_REL).
+</pre>
+
+<p>A useful function concerning $<i>i</i>s is arg_type(),
+which takes as input a string starting with $<i>i</i> and
+returns the type of the <i>i</i>&rsquo;&rsquo;th argument of
+the current EM-instruction, which can be STRING, ARITH or
+INT. One may need this function while decoding operands if
+the context of the $<i>i</i> does not give enough
+information. If the function arg_type() is used, the file
+arg_type.h must contain the definition of STRING, ARITH and
+INT.</p>
+
+<p>%dist is only guaranteed to work when called as a
+parameter of text1(), text2() or text4(). The goal of the
+%dist conversion is to reduce the number of reloc1(),
+reloc2() and reloc4() calls, saving space and time (no
+relocation at compiler run time). The following example
+illustrates the usage of
+&lsquo;&lsquo;%dist&rsquo;&rsquo;.</p>
+<pre>      jmp dst:ILB    ==&gt; /* label in an instruction list */
+          @text1( 0xeb);
+          @text1( %dist( dst-&gt;lab)).
+
+
+      ... dst:LABEL  ==&gt; /* global label */
+          @text1( 0xe9);
+          @reloc2( %$(dst-&gt;lab), %$(dst-&gt;off), PC_REL).
+</pre>
+
+<a name="4.2.5. The functions assemble() and block_assemble()"></a>
+
+<h2>4.2.5. The functions assemble() and block_assemble()</h2>
+
+<p>The functions assemble() and block_assemble() are
+provided by <b>ceg</b>. If, however, the table writer is not
+satisfied with the way they work he can supply his own
+assemble() or block_assemble(). The default function
+assemble() splits an assembly string into a label, mnemonic,
+and operands and performs the following actions on them:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>It processes the local label; it records the name and
+current position. Thereafter it calls the function
+process_label() with one argument of type string, the label.
+The table writer has to define this function.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>Thereafter it calls the function process_mnemonic() with
+one argument of type string, the mnemonic. The table writer
+has to define this function.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>It calls process_operand() for each operand.
+Process_operand() must be written by the table-writer since
+no fixed representation for operands is enforced. It has two
+arguments: a string (the operand to decode) and a pointer to
+the struct <i>t_operand</i>. The declaration of the struct
+<i>t_operand</i> must be given in the file
+&lsquo;&lsquo;as.h&rsquo;&rsquo;, and the table-writer can
+put all the information needed for encoding the operand in
+machine format in it.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>It examines the mnemonic and calls the associated
+function, generated by <b>asg</b>, with pointers to the
+decoded operands as arguments. This makes it possible to use
+the decoded operands in the right hand side of a rule (see
+below).</p>
+</td>
+</table>
+
+<p>If the default assemble() does not work the way the
+table writer wants, he can supply his own version of it.
+Assemble() has the following arguments:</p>
+<pre>     assemble( instruction )
+         char *instruction;
+</pre>
+
+<p><i>instruction</i> points to a null-terminated
+string.</p>
+
+<p>The default function block_assemble() is called with a
+sequence of assembly instructions that belong to one action
+list. It calls assemble() for every assembly instruction in
+this block. But if a special action is required on a block
+of assembly instructions, the table writer only has to
+rewrite this function to get a new <b>ceg</b> that obliges
+to his wishes. The function block_assemble has the following
+arguments:</p>
+<pre>     block_assemble( instructions, nr, first, last)
+           char   **instruction;
+           int      nr, first, last;
+</pre>
+
+<p><i>Instruction</i> point to an array of pointers to
+strings representing assembly instructions. <i>Nr</i> is the
+number of instructions that must be assembled. <i>First</i>
+and <i>last</i> have no function in the default
+block_assemble(), but are useful when optimizations are done
+in block_assemble().</p>
+
+<p>Four things have to be specified in
+&lsquo;&lsquo;as.h&rsquo;&rsquo; and
+&lsquo;&lsquo;as.c&rsquo;&rsquo;. First the user must give
+the declaration of struct <i>t_operand</i> in
+&lsquo;&lsquo;as.h&rsquo;&rsquo;, and the functions
+process_operand(), process_mnemonic(), and process_label()
+must be given in &lsquo;&lsquo;as.c&rsquo;&rsquo;. If the
+right hand side of the as_table contains function calls
+other than the <b>back</b>-primitives, these functions must
+also be present in &lsquo;&lsquo;as.c&rsquo;&rsquo;. Note
+that both the &lsquo;&lsquo;@&rsquo;&rsquo;-sign (see 4.2.3)
+and &lsquo;&lsquo;references&rsquo;&rsquo; (see 4.2.4) also
+work in the functions defined in
+&lsquo;&lsquo;as.c&rsquo;&rsquo;.</p>
+
+<p>The following example shows the representative and
+essential parts of the 8086 &lsquo;&lsquo;as.h&rsquo;&rsquo;
+and &lsquo;&lsquo;as.c&rsquo;&rsquo; files.</p>
+<pre><small>/* Constants and type definitions in as.h */
+
+
+#define        UNKNOWN                0
+#define        IS_REG                 0x1
+#define        IS_ACCU                0x2
+#define        IS_DATA                0x4
+#define        IS_LABEL               0x8
+#define        IS_MEM                 0x10
+#define        IS_ADDR                0x20
+#define        IS_ILB                 0x40
+
+
+#define AX                0
+#define BX                3
+#define CL                1
+#define SP                4
+#define BP                5
+#define SI                6
+#define DI                7
+
+
+#define REG( op)         ( op-&gt;type &amp; IS_REG)
+#define ACCU( op)        ( op-&gt;type &amp; IS_REG  &amp;&amp;  op-&gt;reg == AX)
+#define REG_CL( op)      ( op-&gt;type &amp; IS_REG  &amp;&amp;  op-&gt;reg == CL)
+#define DATA( op)        ( op-&gt;type &amp; IS_DATA)
+#define LABEL( op)       ( op-&gt;type &amp; IS_LABEL)
+#define ILB( op)         ( op-&gt;type &amp; IS_ILB)
+#define MEM( op)         ( op-&gt;type &amp; IS_MEM)
+#define ADDR( op)        ( op-&gt;type &amp; IS_ADDR)
+#define EADDR( op)       ( op-&gt;type &amp; ( IS_ADDR | IS_MEM | IS_REG))
+#define CONST1( op)      ( op-&gt;type &amp; IS_DATA  &amp;&amp; strcmp( &quot;1&quot;, op-&gt;expr) == 0)
+#define MOVS( op)        ( op-&gt;type &amp; IS_LABEL&amp;&amp;strcmp(&quot;
+#define IMMEDIATE( op)   ( op-&gt;type &amp; ( IS_DATA | IS_LABEL))
+
+
+struct t_operand {
+        unsigned type;
+        int reg;
+        char *expr, *lab, *off;
+       };
+
+
+extern struct t_operand saved_op, *AX_oper;
+</small></pre>
+<pre><small>/* Some functions in as.c. */
+
+
+#include &quot;arg_type.h&quot;
+#include &quot;as.h&quot;
+
+
+#define last( s)     ( s + strlen( s) - 1)
+#define LEFT         &rsquo;(&rsquo;
+#define RIGHT        &rsquo;)&rsquo;
+#define DOLLAR       &rsquo;$&rsquo;
+
+
+process_operand( str, op)
+char *str;
+struct t_operand *op;
+
+
+/*        expr            -&gt;        IS_DATA en IS_LABEL
+ *        reg             -&gt;        IS_REG en IS_ACCU
+ *        (expr)          -&gt;        IS_ADDR
+ *        expr(reg)       -&gt;        IS_MEM
+ */
+{
+        char *ptr, *index();
+
+
+        op-&gt;type = UNKNOWN;
+        if ( *last( str) == RIGHT) {
+                ptr = index( str, LEFT);
+                *last( str) = &rsquo; &rsquo;;
+                *ptr = &rsquo; &rsquo;;
+                if ( is_reg( ptr+1, op)) {
+                        op-&gt;type = IS_MEM;
+                        op-&gt;expr = ( *str == &rsquo; &rsquo; ? &quot;0&quot; : str);
+                }
+                else {
+                        set_label( ptr+1, op);
+                        op-&gt;type = IS_ADDR;
+                }
+        }
+        else
+                if ( is_reg( str, op))
+                        op-&gt;type = IS_REG;
+                else {
+                        if ( contains_label( str))
+                                set_label( str, op);
+                        else {
+                                op-&gt;type = IS_DATA;
+                                op-&gt;expr = str;
+                        }
+                }
+}
+
+
+/*********************************************************************/
+
+
+mod_RM( reg, op)
+int reg;
+struct t_operand *op;
+
+
+/* This function helps to decode operands in machine format.
+ * Note the $-operators
+ */
+{
+      if ( REG( op))
+              R233( 0x3, reg, op-&gt;reg);
+      else if ( ADDR( op)) {
+              R233( 0x0, reg, 0x6);
+              @reloc2( %$(op-&gt;lab), %$(op-&gt;off), ABSOLUTE);
+      }
+      else if ( strcmp( op-&gt;expr, &quot;0&quot;) == 0)
+              switch( op-&gt;reg) {
+                case SI : R233( 0x0, reg, 0x4);
+                          break;
+
+
+                case DI : R233( 0x0, reg, 0x5);
+                          break;
+
+
+                case BP : R233( 0x1, reg, 0x6);        /* exception! */
+                          @text1( 0);
+                          break;
+
+
+                case BX : R233( 0x0, reg, 0x7);
+                          break;
+
+
+                default : fprint( STDERR, &quot;Wrong index register %d\n&quot;,
+                                  op-&gt;reg);
+              }
+      else {
+              @if ( fit_byte( %$(op-&gt;expr)))
+                      switch( op-&gt;reg) {
+                          case SI : R233( 0x1, reg, 0x4);
+                                  break;
+
+
+                        case DI : R233( 0x1, reg, 0x5);
+                                  break;
+
+
+                        case BP : R233( 0x1, reg, 0x6);
+                                  break;
+
+
+                        case BX : R233( 0x1, reg, 0x7);
+                                  break;
+
+
+                        default : fprint( STDERR, &quot;Wrong index register %d\n&quot;,
+                                          op-&gt;reg);
+                      }
+                      @text1( %$(op-&gt;expr));
+              @else
+                      switch( op-&gt;reg) {
+                        case SI : R233( 0x2, reg, 0x4);
+                                  break;
+
+
+                        case DI : R233( 0x2, reg, 0x5);
+                                  break;
+
+
+                        case BP : R233( 0x2, reg, 0x6);
+                                  break;
+
+
+                        case BX : R233( 0x2, reg, 0x7);
+                                  break;
+
+
+                        default : fprint( STDERR, &quot;Wrong index register %d\n&quot;,
+                                          op-&gt;reg);
+                      }
+                      @text2( %$(op-&gt;expr));
+              @fi
+      }
+}
+</small></pre>
+<a name="4.3. Generating assembly code"></a>
+<h2>4.3. Generating assembly code</h2>
+
+<p>It is possible to generate assembly instead of object
+files (see section 5), in which case there is no need to
+supply &lsquo;&lsquo;as_table&rsquo;&rsquo;,
+&lsquo;&lsquo;as.h&rsquo;&rsquo;, and
+&lsquo;&lsquo;as.c&rsquo;&rsquo;. This option is useful for
+debugging the EM_table.</p>
+<a name="5. Building a code expander"></a>
+<h2>5. Building a code expander</h2>
+
+<p>This section describes how to generate a code expander
+in two phases. In phase one, the EM_table is written and
+assembly code is generated. If the assembly code is an
+actual language, the EM_table can be tested by assembling
+and running the generated code. If an ad-hoc assembly
+language is used by the table writer, it is not possible to
+test the EM_table, but the code generated is at least in
+readable form. In the second phase, the as_table is written
+and object code is generated. After the generated object
+code is fed into the loader, it can be tested.</p>
+<a name="5.1. Phase one"></a>
+<h2>5.1. Phase one</h2>
+
+<p>The following is a list of instructions to make a code
+expander that generates assembly instructions.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="2%"></td>
+<td width="54%">
+
+<p>Create a new directory.</p>
+</td>
+<td width="34%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>Create the &lsquo;&lsquo;EM_table&rsquo;&rsquo;,
+&lsquo;&lsquo;mach.h&rsquo;&rsquo;, and
+&lsquo;&lsquo;mach.c&rsquo;&rsquo; files; there is no need
+for &lsquo;&lsquo;as_table&rsquo;&rsquo;,
+&lsquo;&lsquo;as.h&rsquo;&rsquo;, and
+&lsquo;&lsquo;as.c&rsquo;&rsquo; at this moment.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="2%"></td>
+<td width="9%">
+
+<p>type</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><tt>install_ceg -as</tt><br>
+install_ceg will create a Makefile and three directories :
+ceg, ce, and back. Ceg will contain the program ceg; this
+program will be used to turn
+&lsquo;&lsquo;EM_table&rsquo;&rsquo; into a set of C source
+files (in the ce directory), one for each EM-instruction.
+All these files will be compiled and put in a library called
+<b>ce.a</b>.<br>
+The option <tt>-as</tt> means that a <b>back</b>-library
+will be generated (in the directory
+&lsquo;&lsquo;back&rsquo;&rsquo;) that supports the
+generation of assembly language. The library is named
+&lsquo;&lsquo;back.a&rsquo;&rsquo;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>Link a front end, &lsquo;&lsquo;ce.a&rsquo;&rsquo;, and
+&lsquo;&lsquo;back.a&rsquo;&rsquo; together resulting in a
+compiler that generates assembly code.</p>
+</td>
+</table>
+
+<p>If the table writer has chosen an actual assembly
+language, the EM_table can be tested (e.g., by running the
+compiler on the EM test set). If an error occurs, change the
+EM_table and type</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><tt>update_ceg</tt> <b>C_instr</b></p>
+</td>
+</table>
+
+<p>where <b>C_instr</b> stands for the name of the
+erroneous EM-instruction. If the table writer has chosen an
+ad-hoc assembly language, he can at least read the generated
+code and look for possible errors. If an error is found, the
+same procedure as described above can be followed.</p>
+<a name="5.2. Phase two"></a>
+<h2>5.2. Phase two</h2>
+
+<p>The next phase is to generate a <b>ce</b> that produces
+relocatable object code.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>Remove the &lsquo;&lsquo;ce&rsquo;&rsquo;,
+&lsquo;&lsquo;ceg&rsquo;&rsquo;, and
+&lsquo;&lsquo;back&rsquo;&rsquo; directories.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="2%"></td>
+<td width="89%">
+
+<p>Write the &lsquo;&lsquo;as_table&rsquo;&rsquo;,
+&lsquo;&lsquo;as.h&rsquo;&rsquo;, and
+&lsquo;&lsquo;as.c&rsquo;&rsquo; files.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="2%"></td>
+<td width="9%">
+
+<p>type</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><tt>install_ceg -obj</tt></p>
+
+<p>The option <tt>-obj</tt> means that
+&lsquo;&lsquo;back.a&rsquo;&rsquo; will contain a library
+for generating ACK.OUT(5ACK) object files, see appendix B.
+If the writer does not want to use the default
+&lsquo;&lsquo;back.a&rsquo;&rsquo;, the <tt>-obj</tt> flag
+must omitted and a &lsquo;&lsquo;back.a&rsquo;&rsquo; should
+be supplied that generates the generates object code in the
+desired format.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>Link a front end, &lsquo;&lsquo;ce.a&rsquo;&rsquo;, and
+&lsquo;&lsquo;back.a&rsquo;&rsquo; together resulting in a
+compiler that generates object code.</p>
+</td>
+</table>
+
+<p>The as_table is ready to be tested. If an error occurs,
+adapt the table. Then there are two ways to proceed:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p>recompile the whole EM_table,</p>
+</td>
+<td width="20%">
+</td>
+</table>
+
+<p><tt>update_ceg ALL</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="1%"></td>
+<td width="90%">
+
+<p>recompile just the few EM-instructions that contained
+the error,</p>
+</td>
+</table>
+
+<p><tt>update_ceg</tt> <b>C_instr</b></p>
+
+<p>where <b>C_instr</b> is an erroneous EM-instruction.
+This has to be done for every EM-instruction that contained
+the erroneous assembly instruction.</p>
+<a name="6. Acknowledgements"></a>
+<h2>6. Acknowledgements</h2>
+
+<p>We want to thank Henri Bal, Dick Grune, and Ceriel
+Jacobs for their valuable suggestions and the critical
+reading of this paper.</p>
+<a name="7. References"></a>
+<h2>7. References</h2>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>A.S. Tanenbaum, H. v. Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;APractical Toolkit For Making
+Compilers,&rdquo; <i>Communications of the ACM,</i> 26, 9
+(September 1983).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>A.S. Tanenbuum, H. v. Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;Description of a Machine Architecture for
+Use with Block Structured Languages,&rdquo; IR-81, Dept.
+Mathematics and Computer Science, Vrije Universiteit,
+Amsterdam (August 1983).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>ACK Documentation, <i>EM_CODE(3ACK),</i> Dept.
+Mathematics and Computer Science, Vrije Universiteit,
+Amsterdam.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>ACK Documentation, <i>ACK.OUT(5ACK),</i> Dept.
+Mathematics and Computer Science, Vrije Universiteit,
+Amsterdam.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>B.W. Kernighan and D.M. Ritchie, <i>The C Programming
+Language,</i> Prentice-Hall Inc., Englewood Cliffs, New
+Jersey (1978).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="5%"></td>
+<td width="90%">
+
+<p>ACK Documentation, <i>PRINT(3ACK),</i> Dept. Mathematics
+and Computer Science, Vrije Universiteit, Amsterdam.</p>
+</td>
+</table>
+<a name="Appendix A, the back -primitives"></a>
+<h2>Appendix A, the back -primitives</h2>
+
+<p>This appendix describes the routines available to
+generate relocatable object code. If the default back.a is
+used, the object code is in ACK.OUT(5ACK) format. In de
+default back.a, the names defined here are remapped to more
+hidden names, to avoid name conflicts with for instance
+names used in the front-end. This remapping is done in an
+include-file, &quot;back.h&quot;. A user-implemented back.a
+should do the same thing.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A1.</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Text and data generation; with ONE_BYTE b;
+TWO_BYTES w; FOUR_BYTES l; arith n;</small></p>
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-106569.png"></small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A2.</small></p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p><small>Relocation; with char *s; arith o; int
+r;</small></p>
+</td>
+<td width="7%">
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-1065610.png"></small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A3.</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Symbol table interaction; with int seg; char
+*s;</small></p>
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-1065611.png"></small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A4.</small></p>
+</td>
+<td width="4%"></td>
+<td width="64%">
+
+<p><small>Start/end actions; with char *f;</small></p>
+</td>
+<td width="25%">
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-1065612.png"></small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A5.</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Label generation routines; with int n; arith g;
+char *l; These routines all return a &quot;char *&quot; to a
+static area, which is overwritten at each call.</small></p>
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-1065613.png"></small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>A6.</small></p>
+</td>
+<td width="4%"></td>
+<td width="84%">
+
+<p><small>Some miscellaneous routines, with char
+*l;</small></p>
+</td>
+<td width="5%">
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-1065614.png"></small></p>
+<a name="Appendix B, description of ACK-a.out library"></a>
+<h2>Appendix B, description of ACK-a.out library</h2>
+
+<p>The object file produced by <b>ce</b> is by default in
+ACK.OUT(5ACK) format. The object file is made up of one
+header, followed by four segment headers, followed by text,
+data, relocation information, symbol table, and the string
+area. The object file is tuned for the ACK-LED, so there are
+some special things done just before the object file is
+dumped. First, four relocation records are added which
+contain the names of the four segments. Second, all the
+local relocation is resolved. This is done by the function
+do_relo(). If there is a record belonging to a local name
+this address is relocated in the segment to which the record
+belongs. Besides doing the local relocation, do_relo()
+changes the &lsquo;&lsquo;nami&rsquo;&rsquo;-field of the
+local relocation records. This field receives the index of
+one of the four relocation records belonging to a segment.
+After the local relocation has been resolved the routine
+output_back() dumps the ACK object file.</p>
+
+<p>If a different a.out format is wanted, one can choose
+between three strategies:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="3%"></td>
+<td width="90%">
+
+<p>The most simple one is to use a conversion program,
+which converts the ACK a.out format to the wanted a.out
+format. This program exists for all most all machines on
+which ACK runs. However, not all conversion programs can
+generate relocation information. The disadvantage is that
+the compiler will become slower.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="3%"></td>
+<td width="90%">
+
+<p>A better solution is to change the functions
+output_back(), do_relo(), open_back(), and close_back() in
+such a way that they produce the wanted a.out format. This
+strategy saves a lot of I/O.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="3%"></td>
+<td width="90%">
+
+<p>If this still is not satisfactory, the
+<b>back</b>-primitives can be adapted to produce the wanted
+a.out format.</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/ceg.pdf b/doc/tack/ceg.pdf
new file mode 100644 (file)
index 0000000..2f4b0f7
Binary files /dev/null and b/doc/tack/ceg.pdf differ
diff --git a/doc/tack/cg.html b/doc/tack/cg.html
new file mode 100644 (file)
index 0000000..b8dbcbe
--- /dev/null
@@ -0,0 +1,4597 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:07 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The table driven code generator from</title>
+</head>
+<body>
+
+<h1 align=center>The table driven code generator from</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Global overview of the workings of the code generator.">2. Global overview of the workings of the code generator.</a><br>
+<a href="#3. Description of the machine table">3. Description of the machine table</a><br>
+<a href="#3.1. Some constants">3.1. Some constants</a><br>
+<a href="#3.2. Register definition">3.2. Register definition</a><br>
+<a href="#3.3. Stack token definition">3.3. Stack token definition</a><br>
+<a href="#3.4. Token expressions">3.4. Token expressions</a><br>
+<a href="#3.5. Expressions">3.5. Expressions</a><br>
+<a href="#3.6. Code rules">3.6. Code rules</a><br>
+<a href="#3.6.1. The EM pattern">3.6.1. The EM pattern</a><br>
+<a href="#3.6.2. The stack pattern">3.6.2. The stack pattern</a><br>
+<a href="#3.6.3. The code part">3.6.3. The code part</a><br>
+<a href="#3.6.3.1. Stack cleanup">3.6.3.1. Stack cleanup</a><br>
+<a href="#3.6.3.2. Register allocation">3.6.3.2. Register allocation</a><br>
+<a href="#3.6.3.3. Code">3.6.3.3. Code</a><br>
+<a href="#3.6.4. Stack replacement">3.6.4. Stack replacement</a><br>
+<a href="#3.6.5. EM replacement">3.6.5. EM replacement</a><br>
+<a href="#3.6.6. Cost">3.6.6. Cost</a><br>
+<a href="#3.6.7. Examples">3.6.7. Examples</a><br>
+<a href="#3.7. Move code rules">3.7. Move code rules</a><br>
+<a href="#3.8. Test code rules">3.8. Test code rules</a><br>
+<a href="#3.9. Stacking code rules.">3.9. Stacking code rules.</a><br>
+<a href="#4. The files mach.h and mach.c">4. The files mach.h and mach.c</a><br>
+<a href="#4.1. Types in the code generator">4.1. Types in the code generator</a><br>
+<a href="#4.2. Global variables to work with">4.2. Global variables to work with</a><br>
+<a href="#4.3. Macros in mach.h">4.3. Macros in mach.h</a><br>
+<a href="#4.3.1. Example mach.h for the PDP-11">4.3.1. Example mach.h for the PDP-11</a><br>
+<a href="#4.4. Functions in mach.c">4.4. Functions in mach.c</a><br>
+<a href="#4.4.1. Example mach.c for the PDP-11">4.4.1. Example mach.c for the PDP-11</a><br>
+<a href="#5. Coercions">5. Coercions</a><br>
+<a href="#6. Internal workings of the code generator.">6. Internal workings of the code generator.</a><br>
+<a href="#6.1. Description of tables.c and tables.h contents">6.1. Description of tables.c and tables.h contents</a><br>
+<a href="#6.1.1. Tables.c">6.1.1. Tables.c</a><br>
+<a href="#6.1.2. tables.h">6.1.2. tables.h</a><br>
+<a href="#6.2. Other important data structures">6.2. Other important data structures</a><br>
+<a href="#6.3. A tour through the sources">6.3. A tour through the sources</a><br>
+<a href="#6.3.1. codegen.c">6.3.1. codegen.c</a><br>
+<a href="#6.3.1.1. DO_NEXTEM">6.3.1.1. DO_NEXTEM</a><br>
+<a href="#6.3.1.2. DO_COERC">6.3.1.2. DO_COERC</a><br>
+<a href="#6.3.1.3. DO_XMATCH">6.3.1.3. DO_XMATCH</a><br>
+<a href="#6.3.1.4. DO_MATCH">6.3.1.4. DO_MATCH</a><br>
+<a href="#6.3.1.5. DO_REMOVE">6.3.1.5. DO_REMOVE</a><br>
+<a href="#6.3.1.6. DO_DEALLOCATE">6.3.1.6. DO_DEALLOCATE</a><br>
+<a href="#6.3.1.7. DO_REALLOCATE">6.3.1.7. DO_REALLOCATE</a><br>
+<a href="#6.3.1.8. DO_ALLOCATE">6.3.1.8. DO_ALLOCATE</a><br>
+<a href="#6.3.1.9. DO_LOUTPUT">6.3.1.9. DO_LOUTPUT</a><br>
+<a href="#6.3.1.10. DO_ROUTPUT">6.3.1.10. DO_ROUTPUT</a><br>
+<a href="#6.3.1.11. DO_MOVE">6.3.1.11. DO_MOVE</a><br>
+<a href="#6.3.1.12. DO_ERASE">6.3.1.12. DO_ERASE</a><br>
+<a href="#6.3.1.13. DO_TOKREPLACE">6.3.1.13. DO_TOKREPLACE</a><br>
+<a href="#6.3.1.14. DO_EMREPLACE">6.3.1.14. DO_EMREPLACE</a><br>
+<a href="#6.3.1.15. DO_COST">6.3.1.15. DO_COST</a><br>
+<a href="#6.3.1.16. DO_RETURN">6.3.1.16. DO_RETURN</a><br>
+<a href="#6.3.2. compute.c">6.3.2. compute.c</a><br>
+<a href="#6.3.3. equiv.c">6.3.3. equiv.c</a><br>
+<a href="#6.3.4. fillem.c">6.3.4. fillem.c</a><br>
+<a href="#6.3.5. gencode.c">6.3.5. gencode.c</a><br>
+<a href="#6.3.6. glosym.c">6.3.6. glosym.c</a><br>
+<a href="#6.3.7. main.c">6.3.7. main.c</a><br>
+<a href="#6.3.8. move.c">6.3.8. move.c</a><br>
+<a href="#6.3.9. nextem.c">6.3.9. nextem.c</a><br>
+<a href="#6.3.10. reg.c">6.3.10. reg.c</a><br>
+<a href="#6.3.11. salloc.c">6.3.11. salloc.c</a><br>
+<a href="#6.3.12. state.c">6.3.12. state.c</a><br>
+<a href="#6.3.13. subr.c">6.3.13. subr.c</a><br>
+<a href="#6.3.13.1. match">6.3.13.1. match</a><br>
+<a href="#6.3.13.2. instance,cinstance">6.3.13.2. instance,cinstance</a><br>
+<a href="#6.3.13.3. eqtoken">6.3.13.3. eqtoken</a><br>
+<a href="#6.3.13.4. distance">6.3.13.4. distance</a><br>
+<a href="#6.3.13.5. split">6.3.13.5. split</a><br>
+<a href="#6.3.13.6. docoerc">6.3.13.6. docoerc</a><br>
+<a href="#6.3.13.7. stackupto">6.3.13.7. stackupto</a><br>
+<a href="#6.3.13.8. findcoerc">6.3.13.8. findcoerc</a><br>
+<a href="#6.3.14. var.c">6.3.14. var.c</a><br>
+
+<hr>
+
+<p><b>the Amsterdam Compiler Kit</b></p>
+
+<p align=center><i><small>ABSTRACT</small></i></p>
+
+<p align=center><i><small>Hans van
+Staveren</small></i><small><br>
+Dept. of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</small></p>
+
+<p><small>It is possible to automate the process of
+compiler building to a great extent using collections of
+tools. The Amsterdam Compiler Kit is such a collection of
+tools. This document provides a description of the internal
+workings of the table driven code generator in the Amsterdam
+Compiler Kit, and a description of syntax and semantics of
+the driving table.</small></p>
+
+<p><small>&gt;&gt;&gt; NOTE &lt;&lt;&lt;<br>
+This document pertains to the <b>old</b> code generator.
+Refer to the &quot;Second Revised Edition&quot; for the new
+code generator.</small></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><small>Part of the Amsterdam Compiler Kit is a code
+generator system consisting of a code generator generator
+(<i>cgg</i> for short) and some machine independent C code.
+<i>Cgg</i> reads a machine description table and creates two
+files, tables.h and tables.c. These are then used together
+with other C code to produce a code generator for the
+machine at hand.</small></p>
+
+<p><small>This in turn reads compact EM code and produces
+assembly code. The remainder of this document will first
+broadly describe the working of the code generator, then a
+description of the machine table follows after which the
+internal workings of the code generator will be
+explained.</small></p>
+
+<p><small>The reader is assumed to have at least a vague
+notion about the semantics of the intermediary EM code.
+Someone wishing to write a table for a new machine should be
+thoroughly acquainted with EM code and the assembly code of
+the machine at hand.</small></p>
+<a name="2. Global overview of the workings of the code generator."></a>
+<h2>2. Global overview of the workings of the code generator.</h2>
+
+<p><small>The code generator or <i>cg</i> tries to generate
+good code by simulating the runtime stack of the program
+compiled and delaying emission of code as long as possible.
+It also keeps track of register contents, which enables it
+to eliminate redundant moves, and tries to eliminate
+redundant tests by keeping information about condition code
+status, if applicable for the machine.</small></p>
+
+<p><small><i>Cg</i> maintains a &lsquo;fakestack&rsquo;
+containing &lsquo;tokens&rsquo; that are built by executing
+the pseudo code contained in the code rules given by the
+table writer. One can think of the fakestack as a logical
+extension of the real stack the program compiled will have
+when run. During code generation tokens will be kept on the
+fakestack as long as possible but when they are moved to the
+real stack, by generating code for the push, all tokens
+above*</small></p>
+
+
+<p align=center><small><img src="grohtml-99261.png"></small></p>
+
+<p><small>the tokens pushed will be pushed also, so that
+the fakestack will not contain holes.</small></p>
+
+<p><small>The main loop of <i>cg</i> is this:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>find a pattern of EM instructions starting at the
+current one to generate code for. This pattern will usually
+be of length one but longer patterns can be
+used.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Select one of the possibly many stack patterns
+that go with this EM pattern on the basis of heuristics
+and/or lookahead.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Force the current fakestack contents to match the
+pattern. This may involve copying tokens to registers,
+making dummy transformations, e.g. to transform a
+&quot;local&quot; into an &quot;register offsetted&quot; or
+might even cause to have the complete fakestack contents put
+to the real stack and then back into registers if no
+suitable transformations were provided by the table
+writer.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Execute the pseudocode associated with the code
+rule just selected, this may cause registers to be
+allocated, code to be emitted etc..</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Put tokens onto the fakestack to reflect the
+result of the operation.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Insert some EM instructions into the stream, this
+is possible but not common.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Account for the cost. The cost is kept in a
+(space, time) vector and lookahead decisions are based on a
+linear combination of these.</small></p>
+</td>
+</table>
+
+<p><small>The table that drives <i>cg</i> is not read in
+every time, but instead is used at compiletime of <i>cg</i>
+to set parameters and to load pseudocode tables. A program
+called <i>cgg</i> reads the table and produces large lists
+of numbers that are compiled together with machine
+independent code to produce a code generator for the machine
+at hand.</small></p>
+<a name="3. Description of the machine table"></a>
+<h2>3. Description of the machine table</h2>
+
+<p><small>The machine description table consists of the
+following sections:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Constant definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Register definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p><small>Token definitions</small></p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="56%">
+
+<p><small>Token expression definitions</small></p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p><small>Code rules</small></p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="32%">
+
+<p><small>Move definitions</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7)</small></p>
+</td>
+<td width="6%"></td>
+<td width="32%">
+
+<p><small>Test definitions</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>8)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Stacking definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+
+<p><small>Input is in free format, white space and newlines
+may be used at will to improve legibility. Identifiers used
+in the table have the same syntax as C identifiers, upper
+and lower case considered different, all characters
+significant. There is however one exception: identifiers
+must be more than one character long for parsing reasons. C
+style comments are accepted</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>/* this is a comment */</small></p>
+</table>
+
+<p><small>and #define macros may be used if the need
+arises.</small></p>
+<a name="3.1. Some constants"></a>
+<h2>3.1. Some constants</h2>
+
+<p><small>Before anything else three constants must be
+defined, all with the syntax NAME=value, value being an
+integer. These constants are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_WSIZE</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>Number of bytes in a machine word. This is the
+number of bytes a simple <b>loc</b> instruction will put on
+the stack.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_PSIZE</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>Number of bytes in a pointer. This is the number
+of bytes a <b>lal</b> instruction will put on the
+stack.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_BSIZE</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>Number of bytes in the hole between AB and LB. If
+the calling sequence just saves PC and LB this size will be
+twice the pointersize.</small></p>
+</td>
+</table>
+
+<p><small>EM_WSIZE and EM_PSIZE are checked when a program
+is compiled with the resulting code generator. EM_BSIZE is
+used by <i>cg</i> to add to the offset of instructions
+dealing with locals having positive offsets, i.e.
+parameters.</small></p>
+
+<p><small>Optionally one can give here the factors with
+which the size and time parts of the cost function have to
+be multiplied to ensure they have the same order of
+magnitude. This can be done as</small></p>
+<pre><small>     TIMEFACTOR = C1/C2
+     SIZEFACTOR = C3/C4
+</small></pre>
+
+<p><small>Above numbers must be read as rational numbers.
+Defaults are 1/1 for both of them. These constants set the
+default size/time tradeoff in the code generator, so if
+TIMEFACTOR and SIZEFACTOR are both 1 the code generator will
+choose at random between two codesequences where one has
+cost (10,4) and the other has cost (8,6). See also the
+description of the cost field below.</small></p>
+
+<p><small>Also optional is the definition of a printformat
+for integers in the codefile. This is given as</small></p>
+<pre><small>     FORMAT = string
+</small></pre>
+
+<p><small>The default for string is &quot;%ld&quot;. For
+example on the PDP 11 one can use</small></p>
+<pre><small>     FORMAT= &quot;0%lo&quot;
+</small></pre>
+
+<p><small>to satisfy the old UNIX assembler that reads
+octal unless followed by a period, and the ACK assembler
+that follows C conventions.</small></p>
+<a name="3.2. Register definition"></a>
+<h2>3.2. Register definition</h2>
+
+<p><small>The next part of the tables describes the various
+registers of the machine and defines identifiers to be used
+in later parts of the tables. Example for the
+PDP-11:</small></p>
+<pre><small>REGISTERS:
+R0 = ( &quot;r0&quot;,2), REG.
+R1 = ( &quot;r1&quot;,2), REG, ODDREG.
+R2 = ( &quot;r2&quot;,2), REG.
+R3 = ( &quot;r3&quot;,2), REG, ODDREG.
+R4 = ( &quot;r4&quot;,2), REG.
+LB = ( &quot;r5&quot;,2), LOCALBASE.
+R01= ( &quot;r0&quot;,4,R0,R1), REGPAIR.
+R23= ( &quot;r2&quot;,4,R2,R3), REGPAIR.
+FR0= ( &quot;r0&quot;,4), FREG.
+FR1= ( &quot;r1&quot;,4), FREG.
+FR2= ( &quot;r2&quot;,4), FREG.
+FR3= ( &quot;r3&quot;,4), FREG.
+DR0= ( &quot;r0&quot;,8,FR0), DREG.
+DR1= ( &quot;r1&quot;,8,FR1), DREG.
+DR2= ( &quot;r2&quot;,8,FR2), DREG.
+DR3= ( &quot;r3&quot;,8,FR3), DREG.
+</small></pre>
+
+<p><small>The identifier before the &rsquo;=&rsquo; sign is
+the name of the register as used further on in the table.
+The string is the name of the register as far as the
+assembler is concerned. The number is the size of the
+register in bytes. Identifiers following the number but
+within the parentheses are previously defined registernames
+that are contained in the register being defined. The
+identifiers following the closing parenthesis are properties
+of the register. So for example R23 is a register with
+assembler name r2, 4 bytes long, contains the registers R2
+and R3 and has the property REGPAIR.</small></p>
+
+<p><small>It might seem wise to list each and every
+property of a register, so one might give R0 the extra
+property MFPTREG named after the not too well known MFPT
+instruction on newer PDP-11 types, but this is not a good
+idea. Every extra property means the registerset is more
+unorthogonal and <i>cg</i> execution time is influenced by
+that, because it has to take into account a larger set of
+registers that are not equivalent.</small></p>
+
+<p><small>There is a predefined property SCRATCH that is
+dynamic, i.e. a register can have the property SCRATCH one
+time, and loose it the next. A register has the property
+SCRATCH when it has a reference count of one. One needs to
+be able to discriminate between SCRATCH registers and
+others, because it is only allowed to do arithmetic on
+SCRATCH registers.</small></p>
+<a name="3.3. Stack token definition"></a>
+<h2>3.3. Stack token definition</h2>
+
+<p><small>The next part describes all possible tokens that
+can reside on the fakestack during code generation.
+Attributes of a token are described in the form of a C
+struct declaration, this is followed by the size in bytes of
+the token, optionally followed by the cost of the token when
+used as an addressing mode and the format to be used on
+output.</small></p>
+
+<p><small>Tokens should usually be declared for every
+addressing mode of the machine at hand and for every size
+directly usable in a machine instruction. Example for the
+PDP-11 (incomplete):</small></p>
+<pre><small>TOKENS:
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>IREG2 =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>{ REGISTER reg; } 2 &quot;*%[reg]&quot; /*
+indirect register */</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>REGCONST =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ REGISTER reg; STRING off; } 2 /* not really
+addressable */</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>REGOFF2 =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ REGISTER reg; STRING off; } 2
+&quot;%[off](%[reg])&quot;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>IREGOFF2 =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ REGISTER reg; STRING off; } 2
+&quot;*%[off](%[reg])&quot;</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>CONST =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>{ INT off; } 2 cost=(2,850)
+&quot;$%[off].&quot;</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>EXTERN2 =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ STRING off; } 2 &quot;%[off]&quot;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>IEXTERN2 =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ STRING off; } 2 &quot;*%[off]&quot;</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>PAIRSIGNED =</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>{ REGISTER regeven,regodd; } 2
+&quot;%[regeven]&quot;</small></p>
+</td>
+<td width="59%">
+</td>
+</table>
+
+<p><small>Types allowed in the struct are REGISTER, INT and
+STRING. Tokens without a printformat should never be
+output.</small></p>
+
+<p><small>Notice that tokens need not correspond to
+addressing modes, the REGCONST token listed above, meaning
+the sum of the contents of the register and the constant,
+has no corresponding addressing mode on the PDP-11, but is
+included so that a sequence of add constant, load indirect,
+can be handled efficiently. This REGCONST token is needed as
+part of the path</small></p>
+<pre><small>     REGISTER -&gt; REGCONST -&gt; REGOFF
+</small></pre>
+
+<p><small>of which the first and the last &quot;exist&quot;
+and the middle is needed only as an intermediate
+step.</small></p>
+<a name="3.4. Token expressions"></a>
+<h2>3.4. Token expressions</h2>
+
+<p><small>Usually machines have certain collections of
+addressing modes that can be used with certain instructions.
+The stack patterns in the table are lists of these
+collections and since it is cumbersome to write out these
+long lists every time, there is a section here to give names
+to these collections. Please note that it is not forbidden
+to write out a token expression in the remainder of the
+table, but for clarity it is usually better not to. Example
+for the PDP-11 (incomplete):</small></p>
+<pre><small>TOKENEXPRESSIONS:
+SOURCE2 = REG + IREG2 + REGOFF2 + IREGOFF2 + CONST + EXTERN2 +
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>IEXTERN2</small></p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><small>SREG = REG * SCRATCH</small></p>
+
+<p><small>Permissible in the expressions are all PASCAL set
+operators, i.e.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>+</small></p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p><small>set union</small></p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="28%">
+
+<p><small>set difference</small></p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>*</small></p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p><small>set intersection</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+
+<p><small>Every tokenidentifier is also a token expression
+identifier denoting the singleton collection of tokens
+containing just itself. Every register property as defined
+above is also a token expression matching all registers with
+that property when on the fakestack. The standard token
+expression identifier ALL denotes the collection of all
+tokens.</small></p>
+<a name="3.5. Expressions"></a>
+<h2>3.5. Expressions</h2>
+
+<p><small>Throughout the rest of the table expressions can
+be used in some places. This section will give the syntax
+and semantics of expressions. There are four types of
+expressions: integer, string, register and undefined. Type
+checking is performed by <i>cgg</i>. An operator with at
+least one undefined operand returns undefined except for the
+defined() function mentioned below. An undefined expression
+is interpreted as FALSE when it is needed as a truth value.
+Basic terms in an expression are</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>number</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>A number is a constant of type
+integer.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>string</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>A string within double quotes is a constant of
+type string. All the normal C style escapes may be used
+within the string.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>REGIDENT</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>The name of a register is a constant of type
+register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>$<i>i</i></small></p>
+</td>
+<td width="28%"></td>
+<td width="68%">
+
+<p><small>A dollarsign followed by a number is the
+representation of the argument of EM instruction . The type
+of the operand is dependent on the instruction, sometimes it
+is integer, sometimes it is string. It is undefined when the
+instruction has no operand.</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="31%"></td>
+<td width="68%">
+<p><small>Although an exhaustive list could be given
+describing all the types the following rule of thumb will
+suffice. If it is unimaginable for the operand of the
+instruction ever to be something different from a plain
+integer, the type is integer, otherwise it is string.<i><br>
+Cg</i> makes all necessary conversions, like adding EM_BSIZE
+to positive arguments of instructions dealing with locals,
+prepending underlines to global names, converting codelabels
+into a unique representation etc. Details about this can be
+found in the section about machine dependent C
+code.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>%[1]</small></p>
+</td>
+<td width="24%"></td>
+<td width="68%">
+
+<p><small>This in general means the token mentioned first
+in the stack pattern. When used inside an expression the
+token must be a simple register. Type of this is
+register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>%[1.off]</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>This means field &quot;off&quot; of the first
+stack pattern token. Type is the same as that of field
+&quot;off&quot;. To use this expression implies a check that
+all tokens in the token expression used have the same
+attributes.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>%[1.1]</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>This is the first subregister of the first token.
+Previous comments apply.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>%[b]</small></p>
+</td>
+<td width="24%"></td>
+<td width="60%">
+
+<p><small>The second allocated register.</small></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>%[a.2]</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>The second subregister of the first allocated
+register.</small></p>
+</td>
+</table>
+
+<p><small>All normal C operators apply to integers, the +
+operator serves for string concatenation and register
+expressions can only be compared to each other. Furthermore
+there are some special &quot;functions&quot;:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>tostring(e)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Converts an integer expression e to a
+string.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>defined(e)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if expression e is defined, 0
+otherwise.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><small>samesign(e1,e2)</small></p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if integer expression e1 and e2 have
+the same sign.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>sfit(e1,e2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if integer expression e1 fits as a
+signed integer into a field of e2 bits, 0
+otherwise.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>ufit(e1,e2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Same as above but now for unsigned
+e1.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>rom(a,n)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Integer expression giving the n&rsquo;th argument
+from the <b>rom</b> descriptor pointed at by the a&rsquo;th
+EM instruction. Undefined if that descriptor does not
+exist.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>loww(a)</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Returns the lower half of the argument of the
+a&rsquo;th EM instruction. This is used to split the
+arguments of a <b>ldc</b> instruction.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>highw(a)</small></p>
+</td>
+<td width="16%"></td>
+<td width="40%">
+
+<p><small>Same for upper half.</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<a name="3.6. Code rules"></a>
+<h2>3.6. Code rules</h2>
+
+<p><small>The largest section of the tables consists of the
+code generation rules. They specify EM patterns, stack
+patterns, code to be generated etc. Syntax is</small></p>
+<pre><small>code rule : EM pattern &rsquo;|&rsquo; stack pattern &rsquo;|&rsquo; code &rsquo;|&rsquo;
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>stack replacement &rsquo;|&rsquo; EM replacement
+&rsquo;|&rsquo; cost ;</small></p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><small>All parts are optional, however there must be at
+least one pattern present. If the empattern is missing the
+rule becomes a rewriting rule or <i>coercion</i> to be used
+when code generation cannot continue because of an invalid
+stack pattern. The code rules are preceded by the
+word</small></p>
+<pre><small>     CODE:
+</small></pre>
+
+<p><small>The next paragraphs describe the various parts in
+detail.</small></p>
+<a name="3.6.1. The EM pattern"></a>
+<h2>3.6.1. The EM pattern</h2>
+
+<p><small>The EM pattern consists of a list of EM mnemonics
+followed by a boolean expression. Examples:</small></p>
+<pre><small><b>     loe
+</b></small></pre>
+
+<p><small>will match a single <b>loe</b>
+instruction,</small></p>
+<pre><small><b>     loc loc cif</b> $1==2 &amp;&amp; $2==8
+</small></pre>
+
+<p><small>is a pattern that will match</small></p>
+<pre><small><b>     loc</b> 2
+<b>     loc</b> 8
+<b>     cif
+</b></small></pre>
+
+<p><small>and</small></p>
+<pre><small><b>     lol inc stl</b> $1==$3
+</small></pre>
+
+<p><small>will match for example</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small><b>lol</b> 6</small></p>
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>lol</b> -2</small></p>
+</td>
+<td width="20%">
+</td>
+<td width="20%">
+
+<p><small><b>lol</b> 4<b><br>
+inc</b></small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>inc</b></small></p>
+</td>
+<td width="20%">
+
+<p><small>but <i>not</i></small></p>
+</td>
+<td width="20%">
+
+<p><small><b>inc<br>
+stl</b> 6</small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>stl</b> -2</small></p>
+</td>
+<td width="20%">
+</td>
+<td width="20%">
+
+<p><small><b>stl</b> -4</small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+</table>
+
+<p><small>A missing boolean expression evaluates to
+TRUE.</small></p>
+
+<p><small>When the EM pattern is the same as in the
+previous code rule the pattern should be given as
+&lsquo;...&rsquo;. The code generator will match the longest
+EM pattern on every occasion, if two patterns of the same
+length match the first in the table will be chosen, while
+all patterns of length greater than or equal to three are
+considered to be of the same length.</small></p>
+<a name="3.6.2. The stack pattern"></a>
+<h2>3.6.2. The stack pattern</h2>
+
+<p><small>The stack pattern is a list of token expressions,
+usually token expression identifiers for clarity. No boolean
+expression is allowed here. The first expression is the one
+that matches the top of the stack.</small></p>
+
+<p><small>The pattern can be followed by the word STACK in
+which case the pattern only matches if there is nothing else
+on the fakestack. The code generator will stack everything
+not matched at the start of the rule.</small></p>
+
+<p><small>The pattern can be preceded with the
+word</small></p>
+<pre><small>     nocoercions:
+</small></pre>
+
+<p><small>which tells the code generator not to try to
+coerce to the pattern but only to use it when it is already
+there. There are two reasons for this construction,
+correctness and speed. It is needed for correctness when the
+pattern contains a register that is not transparent when
+data is moved through it.</small></p>
+
+<p><small>Example: on the PDP-11 the shortest code
+for</small></p>
+<pre><small><b>     lae</b> a
+<b>     loi</b> 8
+<b>     lae</b> b
+<b>     sti</b> 8
+</small></pre>
+
+<p><small>is</small></p>
+<pre><small>     movf _a,fr0
+     movf fr0,_b
+</small></pre>
+
+<p><small>assuming that the floating point processor is in
+double precision mode and fr0 is free. Unfortunately this is
+not correct since a trap can occur on certain kinds of data.
+This could happen if there was a pattern for <b>sti</b> 8
+that allowed one to move a floating point register not
+preceded by nocoercions: . The code generator would then
+find that moving the 8-byte global _a to a floating point
+register and then storing it to _b was the cheapest,
+assuming that the space/time knob was turned far enough to
+space. It is unfortunate that the type information is no
+longer present, since if _a really is a floating point
+number the move could be made without error.</small></p>
+
+<p><small>The second reason for the nocoercions: construct
+is speed. When the code generator has a long list of
+possible stack patterns for one EM pattern it can waste a
+lot of time trying to find coercions to all of them, while
+the mere presence of such a long list indicates that the
+table writer has given a lot of special cases. In this case
+prepending all the special cases by nocoercions: will stop
+the code generator from trying to find things there
+aren&rsquo;t.</small></p>
+<a name="3.6.3. The code part"></a>
+<h2>3.6.3. The code part</h2>
+
+<p><small>The code part consists of three parts, stack
+cleanup, register allocation and code to generate. All of
+these may be omitted.</small></p>
+<a name="3.6.3.1. Stack cleanup"></a>
+<h2>3.6.3.1. Stack cleanup</h2>
+
+<p><small>The stack cleanup part describes certain
+stacktokens that should neither remain on the fakestack, nor
+remembered as contents of registers. This is usually only
+required with store operations. The entire fakestack, except
+for the part matched in the stack pattern, is searched for
+tokens matching the expression and they are copied to the
+real stack. Every register that contains the stacktoken is
+marked as empty.</small></p>
+
+<p><small>Syntax is</small></p>
+<pre><small>     remove(token expression) <i>or
+</i>     remove(token expression, boolean expression)
+</small></pre>
+
+<p><small>Example:</small></p>
+<pre><small>     remove(REGOFF2,%[reg] != LB || %[off] == $1)
+</small></pre>
+
+<p><small>is part of a remove() call for use in the
+<b>stl</b> code rule. It removes all register offsetted
+tokens where the register is not the localbase plus the
+local wherein the store is done. The necessity for this can
+be seen from the following example:</small></p>
+<pre><small><b>     lol</b> 4
+<b>     inl</b> 4
+<b>     stl</b> 6
+</small></pre>
+
+<p><small>Without a proper remove() call in the rule for
+<b>inl</b> code would be generated as here</small></p>
+<pre><small>     inc 4(r5)
+     mov 4(r5),6(r5)
+</small></pre>
+
+<p><small>so local 6 would be given the new value of local
+4 instead of the old as the EM code prescribed.</small></p>
+
+<p><small>When generating something like a branch
+instruction it might be needed to empty the fakestack
+completely. This can of course be done with</small></p>
+<pre><small>     remove(ALL)
+</small></pre>
+<a name="3.6.3.2. Register allocation"></a>
+<h2>3.6.3.2. Register allocation</h2>
+
+<p><small>The register allocation part describes the kind
+of registers needed. Syntax for allocate() is</small></p>
+<pre><small>     allocate(itemlist)
+</small></pre>
+
+<p><small>where itemlist is a list of three kinds of
+things:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="74%">
+
+<p><small>a tokendescription, for example %[1].</small></p>
+</td>
+<td width="15%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will instruct the code generator to
+temporarily decrement the reference count of all registers
+contained in the token, so that they are available for
+allocation in this allocate() call if they were only used in
+that token. See example below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>a register property.</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will allocate a register with that property.
+The register will be marked as empty at this point.
+Lookahead will be performed if necessary.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>a register property with
+initialization.</small></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will allocate the register as in 2) but will
+also initialize it. This eases the task of the code
+generator because it can find a register already filled with
+the right value if it exists.</small></p>
+</td>
+</table>
+
+<p><small>Examples:</small></p>
+<pre><small>     allocate(OREG)
+</small></pre>
+
+<p><small>will allocate an odd register, while</small></p>
+<pre><small>     allocate(REG={REGOFF2,LB,$1})
+</small></pre>
+
+<p><small>will allocate a register while simultaneously
+filling it with the asked value.<br>
+Inside the coercion from SOURCE2 to REGISTER in the PDP-11
+table the following allocate() can be found.</small></p>
+<pre><small>     allocate(%[1],REG=%[1])
+</small></pre>
+
+<p><small>This tells the code generator that registers
+contained in %[1] can be used again and asks to fill the
+register allocated with %[1]. So if
+%[1]={REGOFF2,R3,&quot;4&quot;} and R3 has a reference count
+of 1 the following code might be generated.</small></p>
+<pre><small>     mov 4(r3),r3
+</small></pre>
+
+<p><small>In the rest of the line the registers allocated
+can be named by %[a] and %[b.1],%[b.2], i.e. with lower case
+letters in order of allocation.</small></p>
+
+<p><small>Warning:</small></p>
+<pre><small>     allocate(R3)
+</small></pre>
+
+<p><small>is not the way to allocate R3. R3 is not a
+register property, so it will be seen as a token description
+and the effect is that R3 will have its reference count
+decremented.</small></p>
+<a name="3.6.3.3. Code"></a>
+<h2>3.6.3.3. Code</h2>
+
+<p><small>Code to be generated is specified as a list of
+items of the following kind:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a string in double quotes (&quot;This is a
+string&quot;).</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This is copied to the codefile and a newline ( \n
+) is appended. Inside the string all normal C string
+conventions are allowed, and substitutions can be made of
+the following sorts.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p><small>a)</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>$1, $2 etc. These are the operands of the
+corresponding EM instructions and are printed according to
+their type. To put a real &rsquo;$&rsquo; inside the string
+it must be doubled (&rsquo;$$&rsquo;).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p><small>b)</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>%[1], %[2.reg], %[b.1] etc. These have their
+obvious meaning. If they describe a complete token ( %[1] )
+the printformat for the token is used. If they stand for a
+basic term in an expression they will be printed according
+to their type. To put a real &rsquo;%&rsquo; inside the
+string it must be doubled (&rsquo;%%&rsquo;).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p><small>c)</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>%( arbitrary expression %). This allows inclusion
+of arbitrary expressions inside strings. Usually not needed
+very often, so that the awkward notation is not too bad.
+Note that %(%[1]%) is equivalent to %[1].</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a move() call. This has the following
+syntax:</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><small>     move(token description, token description)
+</small></pre>
+<!-- INDENTATION -->
+<p><small>Moves are handled specially since that enables the
+code generator to keep track of register contents.
+Example:</small></p>
+<!-- INDENTATION -->
+<pre><small>     move(R3,{REGOFF2,LB,$1})
+</small></pre>
+<!-- INDENTATION -->
+<p><small>will generate code to move R3 to $1(r5) except
+when R3 already was a copy of $1(r5). Then the code will be
+omitted. The rules describing how to move things to each
+other can be found in the MOVES section described
+below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>an erase() call. This has the following
+syntax:</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><small>     erase(register expression)
+</small></pre>
+<!-- INDENTATION -->
+<p><small>This tells the code generator that the register
+mentioned no longer has any useful value. This is
+<i>necessary</i> after code in the table has changed the
+contents of registers. For example, after an add to a
+register the register must be erased, because the contents
+do no longer match any token.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>For machines that have condition codes, alas most
+of them do, there are provisions to remember condition code
+setting and prevent needless testing. To set the condition
+code to a token put in the code the following
+call:</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><small>     test(token)
+</small></pre>
+<!-- INDENTATION -->
+<p><small>where token can be all of the standard forms that
+can also be used in move(). This will generate a test if the
+condition codes were not already set to that token. It is
+also possible to tell <i>cg</i> that a certain operation,
+like a preceding add has set the condition codes to some
+token with the call</small></p>
+<!-- INDENTATION -->
+<pre><small>     setcc(token)
+</small></pre>
+<!-- INDENTATION -->
+<p><small>So a sequence of a setcc and a test on the same
+token will generate no code. Another allowed call within the
+code is</small></p>
+<!-- INDENTATION -->
+<pre><small>     samecc
+</small></pre>
+<!-- INDENTATION -->
+<p><small>which tells the code generator that condition
+codes were unaffected in this rule. If no setcc or samecc
+has been given the default is</small></p>
+<!-- INDENTATION -->
+<pre><small>     nocc
+</small></pre>
+<!-- INDENTATION -->
+<p><small>when a piece of code contained strings, which
+tells the code generator that the condition codes have no
+useful value any more.</small></p></td>
+</table>
+<a name="3.6.4. Stack replacement"></a>
+<h2>3.6.4. Stack replacement</h2>
+
+<p><small>The stack replacement is a possibly empty list of
+items to be pushed onto the fakestack. Three kinds of items
+are possible:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>An item of the form %[1]. This will push the
+stacktoken mentioned back onto the stack
+unchanged.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>A register expression. This will push the
+register mentioned onto the fakestack.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>An item of the form { REGOFF2,%[1.reg],$1 }. This
+generates a token with tokenidentifier REGOFF2 and
+attributes in order of declaration.</small></p>
+</td>
+</table>
+
+<p><small>All tokens matched by the stack pattern at the
+beginning of the code rule are first removed and their
+registers deallocated. Items are pushed in the order of
+appearance. This means that the last item will be on the top
+of the stack after the push. So if the stack pattern
+contained two token expressions and they must be pushed back
+unchanged, they have to be specified as stack
+replacement</small></p>
+<pre><small>     %[2] %[1]
+</small></pre>
+
+<p><small>and not the other way around.</small></p>
+<a name="3.6.5. EM replacement"></a>
+<h2>3.6.5. EM replacement</h2>
+
+<p><small>In exceptional cases it might be useful to leave
+part of an empattern undone. For example, a <b>sdl</b>
+instruction might be split into two <b>stl</b> instructions
+when there is no 4-byte quantity on the stack. The
+emreplacement part allows one to express this.
+Example:</small></p>
+<pre><small><b>     stl</b> $1 <b>stl</b> $1+2
+</small></pre>
+
+<p><small>The instructions are inserted in the stream so
+that they can match the first part of a pattern in the next
+step. Note that since the code generator traverses the EM
+instructions in a strict linear fashion, it is impossible to
+let the EM replacement match later parts of a pattern. So if
+there is a pattern</small></p>
+<pre><small><b>     loc stl</b> $1==0
+</small></pre>
+
+<p><small>and the input is</small></p>
+<pre><small><b>     loc</b> 0 <b>sdl</b> 4
+</small></pre>
+
+<p><small>the <b>loc</b> 0 will be processed first, then
+the <b>sdl</b> might be split into two <b>stl</b>&rsquo;s
+but the pattern cannot match now.</small></p>
+<a name="3.6.6. Cost"></a>
+<h2>3.6.6. Cost</h2>
+
+<p><small>The cost field can be specified when there is
+more than one code rule with the same empattern. If the code
+generator has a choice between two possibilities to generate
+code it will choose the cheapest according to the cost
+field. The cost for a code generation is the sum of the
+costs of all the coercions needed, plus the cost for freeing
+registers plus the cost of the code rule itself.</small></p>
+
+<p><small>The format of the costfield is</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>( nbytes, time )</small></p>
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="30%"></td>
+<td width="10%">
+
+<p><small>or</small></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p><small>( nbytes, time ) + %[<i>i</i>]</small></p>
+
+<p><small>with time in the metric desired, like nanoseconds
+or states. See constants section above. The %[<i>i</i>] in
+the second example is used for adding the cost of a certain
+address mode used in the code generated. This can of course
+be repeated if desired. The cost of the address mode must
+then be specified in the token definition
+section.</small></p>
+<a name="3.6.7. Examples"></a>
+<h2>3.6.7. Examples</h2>
+
+<p><small>A list of examples for the PDP-11 is given here.
+Far from being complete it gives examples of most kinds of
+instructions.</small></p>
+<pre><small><b>adi</b> $1==2 | SREG,SOURCE2 |
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>&quot;add %[2],%[1]&quot; erase(%[1])
+setcc(%[1])</small></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>| %[1] | | (2,450) + %[2]</small></p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><small>... | SOURCE2,SREG |</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;add %[1],%[2]&quot; erase(%[2])
+setcc(%[2])</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>| %[2] | | (2,450) + %[1]</small></p>
+</td>
+</table>
+
+<p><small>is an example of the use of the &lsquo;...&rsquo;
+construct and shows how to place erase() and setcc()
+calls.</small></p>
+<pre><small><b>dvi</b> $1==2 | SOURCE2,SPAIRSIGNED |
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>&quot;div %[1],%[2]&quot; erase(%[2])</small></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>| %[2.regeven] | |</small></p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><small><b>cmi tgt</b> $1==2 | SOURCE2,SOURCE2 |
+allocate(REG={CONST,0})</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;cmp %[2],%[1];ble 1f;inc %[a];1:&quot;
+erase(%[a])</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>| %[a] | |</small></p>
+</td>
+</table>
+
+<p><small><b>cal</b> | STACK |</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;jsr pc,$1&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>| | |</small></p>
+</td>
+</table>
+
+<p><small><b>lol</b> | | | { REGOFF2, LB, $1 } |
+|</small></p>
+
+<p><small><b>stl</b> | SOURCE2 |</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>remove(REGOFF2,%[off]==$1)</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>move(%[1],{REGOFF2,LB,$1})</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>| | |</small></p>
+</td>
+</table>
+
+<p><small>| SOURCE2 |</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>allocate(%[1],REGPAIR)</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>move(%[1],%[a.2])</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>test(%[a.2])</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;sxt %[a.even]&quot; | { PAIRSIGNED, %[a.1],
+%[a.2] }| |</small></p>
+</td>
+</table>
+
+<p><small>This coercion shows how to use the move and test
+calls. At first one might think that the testcall is
+unnecessary, since the move will have set the condition
+codes, but the move may never have been executed if the
+register already contained the value, in which case it is
+necessary to do the test. If the move was executed the test
+will be omitted.</small></p>
+<pre><small>| SOURCE2 | allocate(%[1],REG=%[1]) | %[a] | |
+
+
+<b>sdl</b> | SOURCE2 | | %[1] | <b>stl</b> $1 <b>stl</b> $1+2 |
+
+
+<b>exg</b> $1==2 | SOURCE2 SOURCE2 | | %[1] %[2] | |
+</small></pre>
+
+<p><small>This last example again shows the difference in
+the order of the stack pattern and the stack
+replacement.</small></p>
+<a name="3.7. Move code rules"></a>
+<h2>3.7. Move code rules</h2>
+
+<p><small>When issuing a move() call as described above or
+a register allocation with initialization, the code
+generator has to know which instruction to use for the move.
+The code will of course only be generated if it cannot be
+omitted. This is listed in the move section of the tables by
+giving a list of tuples:</small></p>
+<pre><small>     ( source, destination, codepart [ , costfield ] )
+</small></pre>
+
+<p><small>where the square brackets mean the costfield is
+optional. Example for the PDP-11</small></p>
+<pre><small>     MOVES:
+     ( CONST %[off]==0 , SOURCE2, &quot;clr %[2]&quot; )
+     ( SOURCE2, SOURCE2, &quot;mov %[1],%[2]&quot; )
+</small></pre>
+
+<p><small>The moves are scanned from top to bottom, so the
+first one that matches will be chosen.</small></p>
+<a name="3.8. Test code rules"></a>
+<h2>3.8. Test code rules</h2>
+
+<p><small>When issuing a test() call as described above,
+the code generator has to know which instruction to use for
+the test. The code will only be generated if the condition
+codes were not already set to the token. This is listed in
+the test section of the tables by giving a list of
+tuples:</small></p>
+<pre><small>     ( source, codepart [ , costfield ] )
+</small></pre>
+
+<p><small>Example for the PDP-11</small></p>
+<pre><small>     TESTS:
+     ( SOURCE2, &quot;tst %[1]&quot;)
+     ( DREG, &quot;tstf %[1]\ncfcc&quot;)
+</small></pre>
+
+<p><small>The tests are scanned from top to bottom, so the
+first one that matches will be chosen.</small></p>
+<a name="3.9. Stacking code rules."></a>
+<h2>3.9. Stacking code rules.</h2>
+
+<p><small>When the code generator has to stack a token it
+must know which code to use. Since it must at all times be
+possible to empty the fakestack even when no registers are
+free, it is mandatory that all tokens used must have a rule
+attached for stacking them without using a scratch register.
+Since however this might be clumsy and a register might in
+practice be available it is also possible to give rules
+which use a register. On the Intel 8086 for example, there
+is no instruction to push a constant without using a
+register, and the code needed to do it without, must use
+global data and as such is very complicated and wasteful of
+memory and time. It can therefore be left to be used in
+extreme cases, while in general the constant is pushed
+through a register. The stacking rules are listed in the
+stack section of the table as a list of tuples:</small></p>
+<pre><small>     (source, [ register property ] , codepart [ , costfield ] )
+</small></pre>
+
+<p><small>Example for the Intel 8086:</small></p>
+<pre><small>     STACKS:
+     (CONST, REG, move(%[1],%[a]) &quot;push %[a]&quot;)
+     (REG ,, &quot;push %[1]&quot;)
+</small></pre>
+<a name="4. The files mach.h and mach.c"></a>
+<h2>4. The files mach.h and mach.c</h2>
+
+<p><small>The table writer must also supply two files
+containing machine dependent declarations and C code. These
+files are mach.h and mach.c.</small></p>
+<a name="4.1. Types in the code generator"></a>
+<h2>4.1. Types in the code generator</h2>
+
+<p><small>Three different types of integer coexist in the
+code generator and their range depends on the machine at
+hand. The type &rsquo;int&rsquo; is used for things like
+labelcounters that won&rsquo;t require more than 16 bits
+precision. The type &rsquo;word&rsquo; is used among others
+to assemble datawords and is of type &rsquo;long&rsquo;. The
+type &rsquo;full&rsquo; is used for addresses and is of type
+&rsquo;long&rsquo; if EM_WSIZE&gt;2 or
+EM_PSIZE&gt;2.</small></p>
+
+<p><small>In macro and function definitions in later
+paragraphs implicit typing will be used for parameters, that
+is parameters starting with an &rsquo;s&rsquo; will be of
+type string, and the letters
+&rsquo;i&rsquo;,&rsquo;w&rsquo;,&rsquo;f&rsquo; will stand
+for int, word and full respectively.</small></p>
+<a name="4.2. Global variables to work with"></a>
+<h2>4.2. Global variables to work with</h2>
+
+<p><small>Some global variables are present in the code
+generator that can be manipulated by the routines in mach.h
+and mach.c.</small></p>
+
+<p><small>The declarations are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>FILE *codefile;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* code is emitted on this stream */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>word part_word;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* words to be output are put together here
+*/</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>int part_size;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* number of bytes already put in part_word
+*/</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>char str[];</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* Last string read in */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>long argval;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* Last int read and kept */</small></p>
+</td>
+</table>
+<a name="4.3. Macros in mach.h"></a>
+<h2>4.3. Macros in mach.h</h2>
+
+<p><small>In the file mach.h a collection of macros is
+defined that have to do with formatting of assembly code for
+the machine at hand. Some of these macros can of course be
+left undefined in which case the macro calls are left in the
+source and will be treated as function calls. These
+functions can then be defined in <i>mach.c</i>.</small></p>
+
+<p><small>The macros to be defined are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>ex_ap(s)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must print the magic incantations that will mark
+the symbol to be exported to other modules. This is the
+translation of the EM <b>exa</b> and <b>exp</b>
+instructions.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>in_ap(s)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Same to import the symbol. Translation of
+<b>ina</b> and <b>inp</b>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newplb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of procedure label
+<i>s</i>. If left undefined the newilb() macro is used
+instead.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newilb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of instruction label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newdlb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of data label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p><small>dlbdlb(s1,s2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><small>Must define data label <i>s1</i> to be equal to
+<i>s2</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p><small>newlbss(s,f)</small></p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p><small>Must declare a piece of memory initialized to
+BSS_INIT(see below) of length <i>f</i> and with label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>cst_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used when converting constant
+arguments of EM instructions to string. Argument to be
+formatted will be &rsquo;full&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>off_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for integer part of
+label+constant, argument will be
+&rsquo;full&rsquo;.</small></p>
+</td>
+</table>
+
+<p><small>fmt_ilb(ip,il,s)</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="31%"></td>
+<td width="68%">
+<p><small>Must use the numbers <i>ip</i> and <i>il</i> which
+are a procedure number and a label number respectively and
+copy a string to <i>s</i> that must be unique for that
+combination. This procedure is optional, if it is not given
+ilb_fmt must be defined as below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>ilb_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for creation of unique
+instruction labels. Arguments will be a unique procedure
+number (int) and the label number (int).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>dlb_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for printing numeric data
+labels. Argument will be &rsquo;int&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>hol_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for generation of labels for
+space generated by a <b>hol</b> pseudo. Argument will be
+&rsquo;int&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>hol_off</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for printing of the address of
+an element in <b>hol</b> space. Arguments will be the offset
+in the <b>hol</b> block (word) and the number of the
+<b>hol</b> (int).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_cst(w)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will assemble into one
+machineword.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_ilb(s)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will put the address of
+the instruction label into the datastream.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_dlb(s)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will put the address of
+the data label into the datastream.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p><small>fmt_id(sf,st)</small></p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><small>Must take the string in <i>sf</i> which is a
+nonnumeric global label, and transform it into a copy made
+to <i>st</i> which will not collide with reserved assembler
+words and system labels. This procedure is optional, if it
+is not given the id_first macro is used as defined
+below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>id_first</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must be a character. This is prepended to all
+nonnumeric global labels if their length is shorter than the
+maximum allowed(currently 8) or if they already start with
+that character. This is to avoid conflicts of user labels
+with system labels.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>BSS_INIT</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must be a constant. This is the value filled in
+all the words not initialized explicitly. This is loader and
+system dependent. If omitted no initialization is
+assumed.</small></p>
+</td>
+</table>
+<a name="4.3.1. Example mach.h for the PDP-11"></a>
+<h2>4.3.1. Example mach.h for the PDP-11</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define ex_ap(y)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;\t.globl
+%s\n&quot;,y)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define in_ap(y)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>/* nothing */</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define newplb(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%s:\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define newilb(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%s:\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define newdlb(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%s:\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define</small></p>
+</td>
+<td width="16%">
+
+<p><small>dlbdlb(x,y)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%s=%s\n&quot;,x,y)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define newlbss(l,x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%s:.=.+%d.\n&quot;,l,x);</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define cst_fmt</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;$%d.&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define off_fmt</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;%d.&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define ilb_fmt</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;I%x_%x&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define dlb_fmt</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;_%d&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define</small></p>
+</td>
+<td width="16%">
+
+<p><small>hol_fmt</small></p>
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;hol%d&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define hol_off</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>&quot;%ld.+hol%d&quot;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define con_cst(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;%ld.\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define con_ilb(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;%s\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define con_dlb(x)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;%s\n&quot;,x)</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define id_first</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>&rsquo;_&rsquo;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>#define BSS_INIT</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%">
+
+<p><small>0</small></p>
+</td>
+<td width="35%">
+</td>
+</table>
+<a name="4.4. Functions in mach.c"></a>
+<h2>4.4. Functions in mach.c</h2>
+
+<p><small>In mach.c some functions must be supplied, mostly
+manipulating data resulting from pseudoinstructions. The
+specifications are given here, implicit typing of parameters
+as above.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="36%">
+
+<p><small>con_part(isz,word)</small></p>
+</td>
+<td width="4%"></td>
+<td width="60%">
+
+<p><small>This function must manipulate the globals
+part_word and part_size to append the isz bytes contained in
+word to the output stream. If part_word is full, i.e.
+part_size==EM_WSIZE the function part_flush() may be called
+to empty the buffer. This is the function that must go
+through the trouble of doing byte order in words
+correct.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>con_mult(w_size)</small></p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><small>This function must take the string str[] and
+create an integer from the string of size w_size and
+generate code to assemble global data for that integer. Only
+the sizes for which arithmetic is implemented need be
+handled, so if 200-byte integer division is not implemented,
+200-byte integer global data do not have to be implemented.
+Here one must take care of word order in long
+integers.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>con_float()</small></p>
+</td>
+<td width="18%"></td>
+<td width="60%">
+
+<p><small>This function must generate code to assemble a
+floating point number of which the size is contained in
+argval and the ASCII representation in str[].</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="34%">
+
+<p><small>prolog(f_nlocals)</small></p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><small>This function is called at the start of every
+procedure. Function prolog code must be generated, and room
+made for local variables for a total of f_nlocals
+bytes.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p><small>mes(w_mesno)</small></p>
+</td>
+<td width="16%"></td>
+<td width="60%">
+
+<p><small>This function is called when a <b>mes</b> pseudo
+is seen that is not handled by the machine independent part.
+The example below probably shows all the table writer ever
+has to know about that.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>segname[]</small></p>
+</td>
+<td width="22%"></td>
+<td width="60%">
+
+<p><small>This is not a function, but an array of four
+strings. These strings are put out whenever the code
+generator switches segments. Segments are SEGTXT, SEGCON,
+SEGROM and SEGBSS in that order.</small></p>
+</td>
+</table>
+<a name="4.4.1. Example mach.c for the PDP-11"></a>
+<h2>4.4.1. Example mach.c for the PDP-11</h2>
+
+<p><small>As an example of the sort of code expected, the
+mach.c for the PDP-11 is presented here.</small></p>
+<pre><small>/*
+ * machine dependent back end routines for the PDP-11
+ */
+
+
+con_part(sz,w) register sz; word w; {
+
+
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>while (part_size % sz)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>part_size++;</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>if (part_size == EM_WSIZE)</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>part_flush();</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>if (sz == 1) {</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>w &amp;= 0xFF;</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>if (part_size)</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>w &lt;&lt;= 8;</small></p>
+</td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>part_word |= w;</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>} else {</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>assert(sz == 2);</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>part_word = w;</small></p>
+</td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>}</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="16%">
+
+<p><small>part_size += sz;</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="35%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>con_mult(sz) word sz; {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>long l;</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>if (sz != 4)</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>fatal(&quot;bad icon/ucon
+size&quot;);</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>l = atol(str);</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o\n&quot;,(int)(l&gt;&gt;16),(int)l);</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>con_float() {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>double f;</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>register short *p,i;</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>/*</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>* This code is correct only when the code
+generator is</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>* run on a PDP-11 or VAX-11 since it assumes
+native</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>* floating point format is PDP-11
+format.</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>*/</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>if (argval != 4 &amp;&amp; argval !=
+8)</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>fatal(&quot;bad fcon size&quot;);</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>f = atof(str);</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>p = (short *) &amp;f;</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>i = *p++;</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>if (argval == 8) {</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o;&quot;,i,*p++);</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>i = *p++;</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>}</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o\n&quot;,i,*p++);</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>prolog(nlocals) full nlocals; {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;mov r5,-(sp)\nmov
+sp,r5\n&quot;);</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>if (nlocals == 0)</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>return;</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>if (nlocals == 2)</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;tst
+-(sp)\n&quot;);</small></p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>else</small></p>
+</td>
+<td width="16%"></td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;sub
+$%d.,sp\n&quot;,nlocals);</small></p>
+</td>
+<td width="51%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>mes(type) word type; {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>int argt ;</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>switch ( (int)type ) {</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>case ms_ext :</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>for (;;) {</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>switch ( argt=getarg(</small></p>
+</td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) )
+{</small></p>
+</td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>case sp_cend :</small></p>
+</td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>return ;</small></p>
+</td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>default:</small></p>
+</td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>strarg(argt) ;</small></p>
+</td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>fprintf(codefile,&quot;.globl %s\n&quot;,argstr)
+;</small></p>
+</td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>break ;</small></p>
+</td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>}</small></p>
+</td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>}</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>default :</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>while ( getarg(any_ptyp) != sp_cend )
+;</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+</td>
+<td width="16%">
+
+<p><small>break ;</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="0%"></td>
+<td width="16%">
+
+<p><small>}</small></p>
+</td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="16%"></td>
+<td width="19%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>char *segname[] = {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+
+<p><small>&quot;.text&quot;, /* SEGTXT */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+
+<p><small>&quot;.data&quot;, /* SEGCON */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+
+<p><small>&quot;.data&quot;, /* SEGROM */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+
+<p><small>&quot;.bss&quot; /* SEGBSS */</small></p>
+</td>
+</table>
+
+<p><small>};</small></p>
+<a name="5. Coercions"></a>
+<h2>5. Coercions</h2>
+
+<p><small>A central part in code generation is taken by the
+<i>coercions</i>. It is the responsibility of the table
+writer to provide all necessary coercions so that code
+generation can continue. The very minimal set of coercions
+are the coercions to unstack every token expression, in
+combination with the rules to stack every token.</small></p>
+
+<p><small>If these are present the code generator can
+always make the necessary transformations by stacking and
+unstacking. Of course for codequality it is usually best to
+provide extra coercions to prevent this stacking to take
+place. <i>Cg</i> discriminates three types of
+coercions:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Unstacking coercions. This category can use the
+allocate() call in its code.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Splitting coercions, these are the coercions that
+split larger tokens into smaller ones.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Transforming coercions, these are the coercions
+that transform a token into another one of the same size.
+This category can use the allocate() call in its
+code.</small></p>
+</td>
+</table>
+
+<p><small>When a stack configuration does not match the
+stack pattern <i>coercions</i> are searched for in the
+following order:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>First tokens are split if necessary to get their
+sizes right.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Then transforming coercions are found that will
+make the pattern match.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Finally if the stack pattern is longer than the
+fakestack contents unstacking coercions will be used to fill
+up the pattern.</small></p>
+</td>
+</table>
+
+<p><small>At any point, when coercions are missing so code
+generation could not continue, the offending tokens are
+stacked.</small></p>
+<a name="6. Internal workings of the code generator."></a>
+<h2>6. Internal workings of the code generator.</h2>
+<a name="6.1. Description of tables.c and tables.h contents"></a>
+<h2>6.1. Description of tables.c and tables.h contents</h2>
+
+<p><small>In this section the intermediate files will be
+described that are produced by <i>cgg</i> and compiled with
+machine independent code to produce a code
+generator.</small></p>
+<a name="6.1.1. Tables.c"></a>
+<h2>6.1.1. Tables.c</h2>
+
+<p><small>Tables.c contains a large number of initialized
+array&rsquo;s of all sorts. Description of each
+follows:</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>byte code rules[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Pseudo code interpreted by the code generator.
+Always starts with some opcode followed by operands
+depending on the opcode. Integers in this table are between
+0 and 32767 and have a one byte encoding if between 0 and
+127.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>char stregclass[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Number of computed static register class per
+register. Two registers are in the same class if they have
+the same properties and don&rsquo;t share a common
+subregister.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>struct reginfo machregs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Info per register. Initialized with representation
+string, size, members of the register and set of registers
+affected when this one is changed. Also contains room for
+runtime information, like contents and reference
+count.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>tkdef_t tokens[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Information per tokentype. Initialized with size,
+cost, type of operands and formatstring.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>node_t enodes[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of triples representing expressions for the
+code generator.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>string code strings[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of strings. All strings are put in a list and
+checked for duplication, so only one copy per string will
+reside here.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>set_t machsets[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of token expression sets. Bit 0 of the set is
+used for the SCRATCH property of registers, bit 1 upto NREG
+are for the corresponding registers and bit NREG+1 upto the
+end are for corresponding tokens.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>inst_t tokeninstances[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of descriptions for building tokens. Contains
+type of rule for building one, plus operands depending on
+the type.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>move_t moves[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of move rules. Contains token expressions for
+source and destination plus cost and index for code
+rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>byte pattern[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>EM patterns. This is structured internally as
+chains of patterns, each chain pointed at by pathash[].
+After each pattern the list of possible code rules is
+given.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>int pathash[256]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Indices into pattern[] for all patterns with a
+certain low order byte of the hashing
+function.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c1_t c1coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of rules to stack tokens. Contains token
+expressions, register needed, cost and code
+rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c2_t c2coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of splitting coercions. Token expressions,
+split factor, replacements and code rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c3_t c3coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of one to one coercions. Token expressions,
+register needed, replacement and code rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>struct reginfo **reglist[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of lists of pointers to register information.
+For every property the list is here to find the registers
+corresponding to it.</small></p></td>
+</table>
+<a name="6.1.2. tables.h"></a>
+<h2>6.1.2. tables.h</h2>
+
+<p><small>In tables.h various derived constants for the
+tables are given. They are then used to determine array
+sizes in the actual code generator, plus loop termination in
+some cases.</small></p>
+<a name="6.2. Other important data structures"></a>
+<h2>6.2. Other important data structures</h2>
+
+<p><small>During code generation some other data structures
+are used and here is a short description of some of the
+important ones.</small></p>
+
+<p><small>Tokens are kept in the code generator as a struct
+consisting of one integer <i>t_token</i> which is -1 if the
+token is a register, and the number of the token otherwise,
+plus an array of <i>TOKENSIZE</i> unions <i>t_att</i> of
+which the first is the register number in case of a
+register.</small></p>
+
+<p><small>The fakestack is an array of these tokens, there
+is a global variable <i>stackheight</i>.</small></p>
+
+<p><small>The results of expressions are kept in a struct
+<i>result</i> with elements <i>e_typ</i>, giving the type of
+the expression: <i>EV_INT</i>, <i>EV_REG</i> or
+<i>EV_STR</i>, and a union <i>e_v</i> which contains the
+real result.</small></p>
+<a name="6.3. A tour through the sources"></a>
+<h2>6.3. A tour through the sources</h2>
+<a name="6.3.1. codegen.c"></a>
+<h2>6.3.1. codegen.c</h2>
+
+<p><small>The file codegen.c contains one large function
+consisting of one giant switch statement. It is the
+interpreter for the code generator pseudo code as contained
+in code rules[]. This function can call itself recursively
+when doing lookahead. Arguments are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>codep</small></p>
+</td>
+<td width="10%"></td>
+<td width="80%">
+
+<p><small>Pointer into code rules, pseudo program
+counter.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>ply</small></p>
+</td>
+<td width="14%"></td>
+<td width="78%">
+
+<p><small>Number of EM pattern lookahead
+allowed.</small></p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>toplevel</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>Boolean telling whether this is the toplevel
+codegen() or a deeper incarnation.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>costlimit</small></p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p><small>A cutoff value to limit searches. If the cost
+crosses costlimit the incarnation can terminate.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>forced</small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>A register number if nonzero. This is used inside
+coercions to force the allocate() call to allocate a
+register determined by earlier lookahead.</small></p>
+</td>
+</table>
+
+<p><small>The instructions inplemented in the
+switch:</small></p>
+<a name="6.3.1.1. DO_NEXTEM"></a>
+<h2>6.3.1.1. DO_NEXTEM</h2>
+
+<p><small>Matches the next EM pattern and does lookahead if
+necessary to find the best code rule associated with this
+pattern. Heuristics are used to determine best code rule
+when possible. This is done by calling the distance()
+function.</small></p>
+<a name="6.3.1.2. DO_COERC"></a>
+<h2>6.3.1.2. DO_COERC</h2>
+
+<p><small>This sets the code generator in the state to do a
+from stack coercion.</small></p>
+<a name="6.3.1.3. DO_XMATCH"></a>
+<h2>6.3.1.3. DO_XMATCH</h2>
+
+<p><small>This is done when a match no longer has to be
+checked. Used when the nocoercions: trick is used in the
+table.</small></p>
+<a name="6.3.1.4. DO_MATCH"></a>
+<h2>6.3.1.4. DO_MATCH</h2>
+
+<p><small>This is the big one inside this function. It has
+the task to transform the contents of the current fakestack
+to match the pattern given after it.</small></p>
+
+<p><small>Since the code generator does not know combining
+coercions, i.e. there is no way to make a big token out of
+two smaller ones, the first thing done is to stack every
+token that is too small. After that all tokens too big are
+split if possible to the right size.</small></p>
+
+<p><small>Next the coercions are sought that would
+transform tokens in place to the right one, plus the
+coercions that would pop tokens of the stack. Each of those
+might need a register, so a list of registers is generated
+and at the end of looking for coercions the function
+<i>tuples()</i> is called to generate the list of all
+possible <i>n</i>-tuples, where <i>n</i> equals the number
+of registers needed.</small></p>
+
+<p><small>Lookahead is now performed if the number of
+tuples is greater than one. If no possibility is found
+within the costlimit, the fakestack is made smaller by
+pushing the bottom token, and this process is repeated until
+either a way is found or the fakestack is completely empty
+and there is still no way to make the match.</small></p>
+
+<p><small>If there is a way the corresponding coercions are
+executed and the code is finished.</small></p>
+<a name="6.3.1.5. DO_REMOVE"></a>
+<h2>6.3.1.5. DO_REMOVE</h2>
+
+<p><small>Here the remove() call is executed, all tokens
+matched by the token expression plus boolean expression are
+pushed. In the current implementation there is no attempt to
+move those tokens to registers, but that is a possible
+future extension.</small></p>
+<a name="6.3.1.6. DO_DEALLOCATE"></a>
+<h2>6.3.1.6. DO_DEALLOCATE</h2>
+
+<p><small>This one temporarily decrements by one the
+reference count of all registers contained in the token
+given as argument.</small></p>
+<a name="6.3.1.7. DO_REALLOCATE"></a>
+<h2>6.3.1.7. DO_REALLOCATE</h2>
+
+<p><small>Here all temporary deallocates are made
+undone.</small></p>
+<a name="6.3.1.8. DO_ALLOCATE"></a>
+<h2>6.3.1.8. DO_ALLOCATE</h2>
+
+<p><small>This is the part that allocates a register and
+decides which one to use. If the <i>forced</i> argument was
+given its task is simple, otherwise some work must be done.
+First the list of possible registers is scanned, all free
+registers noted and it is noted whether any of those
+registers is already containing the initialization. If no
+registers are available some fakestack token is stacked and
+the process is repeated.</small></p>
+
+<p><small>After that if an exact match was found, the list
+of registers is reduced to one register matching exactly out
+of every register class. Now lookahead is performed if
+necessary and the register chosen. If an initialization was
+given the corresponding move is performed, otherwise the
+register is marked empty.</small></p>
+<a name="6.3.1.9. DO_LOUTPUT"></a>
+<h2>6.3.1.9. DO_LOUTPUT</h2>
+
+<p><small>This prints a string and an expression. Only done
+on toplevel.</small></p>
+<a name="6.3.1.10. DO_ROUTPUT"></a>
+<h2>6.3.1.10. DO_ROUTPUT</h2>
+
+<p><small>Prints a string and a new line. Only on
+toplevel.</small></p>
+<a name="6.3.1.11. DO_MOVE"></a>
+<h2>6.3.1.11. DO_MOVE</h2>
+
+<p><small>Calls the move() function in the code generator
+to implement the move() function in the table.</small></p>
+<a name="6.3.1.12. DO_ERASE"></a>
+<h2>6.3.1.12. DO_ERASE</h2>
+
+<p><small>Marks the register that is its argument as
+empty.</small></p>
+<a name="6.3.1.13. DO_TOKREPLACE"></a>
+<h2>6.3.1.13. DO_TOKREPLACE</h2>
+
+<p><small>This is the token replacement part. It is also
+called if there is no token replacement because it has some
+other functions as well.</small></p>
+
+<p><small>First the tokens that will be pushed on the
+fakestack are computed and stored in a temporary array. Then
+the tokens that were matched in this rule are popped and
+their embedded registers have their reference count
+decremented. After that the replacement tokens are
+pushed.</small></p>
+
+<p><small>Finally all registers allocated in this rule have
+their reference count decremented. If they were not pushed
+on the fakestack they will be available again in the next
+code rule.</small></p>
+<a name="6.3.1.14. DO_EMREPLACE"></a>
+<h2>6.3.1.14. DO_EMREPLACE</h2>
+
+<p><small>Places replacement EM instructions back into the
+instruction stream.</small></p>
+<a name="6.3.1.15. DO_COST"></a>
+<h2>6.3.1.15. DO_COST</h2>
+
+<p><small>Accounts for cost as given in the code
+rule.</small></p>
+<a name="6.3.1.16. DO_RETURN"></a>
+<h2>6.3.1.16. DO_RETURN</h2>
+
+<p><small>Returns from this level of codegen(). Is used at
+the end of coercions, move rules etc..</small></p>
+<a name="6.3.2. compute.c"></a>
+<h2>6.3.2. compute.c</h2>
+
+<p><small>This module computes the various expressions as
+given in the enodes[] array. Nothing very special happens
+here, it is just a recursive function computing leaves of
+expressions and applying the operator.</small></p>
+<a name="6.3.3. equiv.c"></a>
+<h2>6.3.3. equiv.c</h2>
+
+<p><small>In this module the tuples() function is
+implemented. It is given the number of registers needed and
+a list of register lists and it constructs a list of tuples
+where the <i>n</i>&rsquo;th register comes from the
+<i>n</i>&rsquo;th list. Before the list is constructed
+however the dynamic register classes are computed. Two
+registers are in the same dynamic class if they are in the
+same static class and their contents is the
+same.</small></p>
+
+<p><small>After that the permute() recursive function is
+called to generate the list of tuples. After construction a
+generated tuple is added to the list if it is not already
+pairwise in the same class or if the register relations are
+not the same, i.e. if the first and second register share a
+common subregister in one tuple and not in the other they
+are considered different.</small></p>
+<a name="6.3.4. fillem.c"></a>
+<h2>6.3.4. fillem.c</h2>
+
+<p><small>This is the routine that does the reading of EM
+instructions and the handling of pseudos. The mach.c module
+provided by the table writer is included at the end of this
+module. The routine fillemlines() is called by nextem() at
+toplevel to make sure there are enough instruction to match.
+It fills the EM instruction buffer up to 5 places from the
+end to keep room for EM replacement instructions, or up to a
+pseudo.</small></p>
+
+<p><small>The dopseudo() function performs the function of
+the pseudo last encountered. If the pseudo is a <b>rom</b>
+the corresponding label is saved with the contents of the
+<b>rom</b> to be available to the code generator later. The
+rest of the routines are small service routines for either
+input or data output.</small></p>
+<a name="6.3.5. gencode.c"></a>
+<h2>6.3.5. gencode.c</h2>
+
+<p><small>This module contains routines called by codegen()
+to generate the real code to the codefile. The function
+gencode() gets a string as argument and copies it to
+codefile while processing certain embedded control
+characters implementing the $2 and [1.reg] escapes. The
+function genexpr() prints the expression given as argument.
+It is used to implement the %( expr %) escape. The prtoken()
+function interprets the tokenformat as given in the tokens[]
+array.</small></p>
+<a name="6.3.6. glosym.c"></a>
+<h2>6.3.6. glosym.c</h2>
+
+<p><small>This module maintains a list of global symbols
+that have a <b>rom</b> pseudo associated. There are
+functions to enter a symbol and to find a
+symbol.</small></p>
+<a name="6.3.7. main.c"></a>
+<h2>6.3.7. main.c</h2>
+
+<p><small>Main routine of the code generator. Processes
+arguments and flags. Flags available are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>-d</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Sets debug mode if the code generator was not
+compiled with the NDEBUG macro defined. Debug mode gives
+very long output on stderr indicating all steps of the code
+generation process including nesting of the codegen()
+function.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>-p<i>n</i></small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Sets the lookahead depth to <i>n</i>, the
+<i>p</i> stands for ply, a well known word in chess playing
+programs.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>-w<i>n</i></small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Sets the weight percentage for size in the cost
+function to <i>n</i> percent. Uses Euclides algorithm to
+simplify rationals.</small></p>
+</td>
+</table>
+<a name="6.3.8. move.c"></a>
+<h2>6.3.8. move.c</h2>
+
+<p><small>Function to implement the move() pseudo function
+in the tables, register initialization and the setcc and
+test pseudo functions. First tests are made to try to
+prevent the move from really happening. The condition code
+register is treated special here. After that, if there is an
+after that, the move rule is found and the code
+executed.</small></p>
+<a name="6.3.9. nextem.c"></a>
+<h2>6.3.9. nextem.c</h2>
+
+<p><small>The entry point of this module is nextem(). It
+hashes the next three EM instructions, and uses the low
+order byte of the hash as an index into the array pathash[],
+to find a chain of patterns in the array pattern[], that are
+all tried for a match.</small></p>
+
+<p><small>The function trypat() does most of the work
+checking patterns. When a pattern is found to match all
+instructions the operands of the instruction are placed into
+the dollar[] array. Then the boolean expression is tried. If
+it matches the function can return, leaving the operands
+still in the dollar[] array, so later in the code rule they
+can still be used.</small></p>
+<a name="6.3.10. reg.c"></a>
+<h2>6.3.10. reg.c</h2>
+
+<p><small>Collection of routines to handle registers.
+Reference count routines are here, chrefcount() and
+getrefcount(), plus routines to erase a single register or
+all of them, erasereg() and cleanregs().</small></p>
+
+<p><small>If NDEBUG hasn&rsquo;t been defined, here is also
+the routine that checks if the reference count kept with the
+register information is in agreement with the number of
+times it occurs on the fakestack.</small></p>
+<a name="6.3.11. salloc.c"></a>
+<h2>6.3.11. salloc.c</h2>
+
+<p><small>Module for string allocation and garbage
+collection. Contains entry points myalloc(), a routine
+calling malloc() and checking whether room is left,
+myfree(), just free(), popstr() a function called from
+state.c to free all strings made since the last saved
+status. Furthermore there is salloc() which has the size of
+the string as parameter and returns a pointer to the
+allocated space, while keeping a copy of the pointer for
+garbage allocation purposes.</small></p>
+
+<p><small>The function garbage_collect is called from
+codegen() at toplevel every now and then, and checks all
+places where strings may reside to mark strings as being in
+use. Strings not in use are returned to the pool of free
+space.</small></p>
+<a name="6.3.12. state.c"></a>
+<h2>6.3.12. state.c</h2>
+
+<p><small>Set of routines called to save current status,
+restore a previous saved state and to free the room occupied
+by a saved state. A list of structs is kept here to save the
+state. If this is not done, small allocates will take space
+from the holes big enough for state saves, and as a result
+every new state save will need a new struct. The code
+generator runs out of room very rapidly under these
+conditions.</small></p>
+<a name="6.3.13. subr.c"></a>
+<h2>6.3.13. subr.c</h2>
+
+<p><small>Random set of leftover routines.</small></p>
+<a name="6.3.13.1. match"></a>
+<h2>6.3.13.1. match</h2>
+
+<p><small>Computes whether a certain token matches a
+certain token expression. Just computes a bitnumber
+according to the algorithm explained with machsets[], and
+tests the bit and the boolean expression if it is
+there.</small></p>
+<a name="6.3.13.2. instance,cinstance"></a>
+<h2>6.3.13.2. instance,cinstance</h2>
+
+<p><small>These two functions compute a token from a
+description. They differ very slight, cinstance() is used to
+compute the result of a coercion in a certain context and
+therefore has more arguments, which it uses instead of the
+global information instance() works on.</small></p>
+<a name="6.3.13.3. eqtoken"></a>
+<h2>6.3.13.3. eqtoken</h2>
+
+<p><small>eqtoken computes whether two tokens can be
+considered identical. Used to check register contents during
+moves mainly.</small></p>
+<a name="6.3.13.4. distance"></a>
+<h2>6.3.13.4. distance</h2>
+
+<p><small>This is the heuristic function that computes a
+distance from the current fakestack contents to the token
+pattern in the table. It likes exact matches most, then
+matches where at least the sizes are correct and if the
+sizes are not correct it likes too large sizes more than too
+small, since splitting a token is easier than combining
+one.</small></p>
+<a name="6.3.13.5. split"></a>
+<h2>6.3.13.5. split</h2>
+
+<p><small>This function tries to find a splitting coercion
+and executes it immediately when found. The fakestack is
+shuffled thoroughly when this happens, so pieces below the
+token that must be split are saved first.</small></p>
+<a name="6.3.13.6. docoerc"></a>
+<h2>6.3.13.6. docoerc</h2>
+
+<p><small>This function executes a coercion that was found.
+The same shuffling is done, so the top of the stack is again
+saved.</small></p>
+<a name="6.3.13.7. stackupto"></a>
+<h2>6.3.13.7. stackupto</h2>
+
+<p><small>This function gets a pointer into the fakestack
+and must stack every token including the one pointed at up
+to the bottom of the fakestack. The first stacking rule
+possible is used, so rules using registers must come
+first.</small></p>
+<a name="6.3.13.8. findcoerc"></a>
+<h2>6.3.13.8. findcoerc</h2>
+
+<p><small>Looks for a one to one coercion, if found it
+returns a pointer to it and leaves a list of possible
+registers to use in the global variable curreglist. This is
+used by codegen().</small></p>
+<a name="6.3.14. var.c"></a>
+<h2>6.3.14. var.c</h2>
+
+<p><small>Global variables used by more than one module.
+External definitions are in extern.h.</small></p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/cg.pdf b/doc/tack/cg.pdf
new file mode 100644 (file)
index 0000000..88610a1
Binary files /dev/null and b/doc/tack/cg.pdf differ
diff --git a/doc/tack/crefman.html b/doc/tack/crefman.html
new file mode 100644 (file)
index 0000000..b7996e9
--- /dev/null
@@ -0,0 +1,1410 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:12 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>ACK/CEM Compiler</title>
+</head>
+<body>
+
+<h1 align=center>ACK/CEM Compiler</h1>
+<a href="#1. C Language">1. C Language</a><br>
+<a href="#2.2 Identifiers">2.2 Identifiers</a><br>
+<a href="#2.3 Keywords">2.3 Keywords</a><br>
+<a href="#asm">asm</a><br>
+<a href="#enum">enum</a><br>
+<a href="#entry , fortran">entry , fortran</a><br>
+<a href="#2.4.1 Integer Constants">2.4.1 Integer Constants</a><br>
+<a href="#2.4.3 Character Constants">2.4.3 Character Constants</a><br>
+<a href="#2.4.4 Floating Constants">2.4.4 Floating Constants</a><br>
+<a href="#2.6 Hardware characteristics">2.6 Hardware characteristics</a><br>
+<a href="#4 What&rsquo;s in a name?">4 What&rsquo;s in a name?</a><br>
+<a href="#char">char</a><br>
+<a href="#unsigned">unsigned</a><br>
+<a href="#enum">enum</a><br>
+<a href="#void">void</a><br>
+<a href="#Fundamental types">Fundamental types</a><br>
+<a href="#7 Expressions">7 Expressions</a><br>
+<a href="#7.2 Unary operators">7.2 Unary operators</a><br>
+<a href="#7.13 Conditional operator">7.13 Conditional operator</a><br>
+<a href="#7.14 Assignment operators">7.14 Assignment operators</a><br>
+<a href="#8.2 Type specifiers">8.2 Type specifiers</a><br>
+<a href="#8.5 Structure and union declarations">8.5 Structure and union declarations</a><br>
+<a href="#9.7 Switch statement">9.7 Switch statement</a><br>
+<a href="#10 External definitions">10 External definitions</a><br>
+<a href="#10.1 External function definitions">10.1 External function definitions</a><br>
+<a href="#11.1 Lexical scope">11.1 Lexical scope</a><br>
+<a href="#12 Compiler control lines">12 Compiler control lines</a><br>
+<a href="#12.1 Token replacement">12.1 Token replacement</a><br>
+<a href="#12.2 File inclusion">12.2 File inclusion</a><br>
+<a href="#12.3 Conditional compilation">12.3 Conditional compilation</a><br>
+<a href="#12.4 Line control">12.4 Line control</a><br>
+<a href="#14.2 Functions">14.2 Functions</a><br>
+<a href="#15 Constant expressions">15 Constant expressions</a><br>
+<a href="#2. Compiler flags">2. Compiler flags</a><br>
+<a href="#References">References</a><br>
+<a href="#Appendix A - Enumeration Type">Appendix A - Enumeration Type</a><br>
+<a href="#Appendix B: C grammar in LL(1) form">Appendix B: C grammar in LL(1) form</a><br>
+
+<hr>
+
+<p><b>Reference Manual</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p align=center><i><small>Erik H.
+Baalbergen</small></i><small><br>
+Department of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam<br>
+The Netherlands</small></p>
+</td>
+</table>
+<a name="1. C Language"></a>
+<h2>1. C Language</h2>
+
+<p><small>This section discusses the extensions to and
+deviations from the C language, as described in [1]. The
+issues are numbered according to the reference
+manual.</small></p>
+<a name="2.2 Identifiers"></a>
+<h2>2.2 Identifiers</h2>
+
+<p><small>Upper and lower case letters are different. The
+number of significant letters is 32 by default, but may be
+set to another value using the <b>&minus;M</b> option. The
+identifier length should be set according to the rest of the
+compilation programs.</small></p>
+<a name="2.3 Keywords"></a>
+<h2>2.3 Keywords</h2>
+<a name="asm"></a>
+<h2>asm</h2>
+
+<p><small>The keyword <tt>asm</tt> is recognized. However,
+the statement</small></p>
+<pre><small>     asm(string);
+</small></pre>
+
+<p><small>is skipped, while a warning is given.</small></p>
+<a name="enum"></a>
+<h2>enum</h2>
+
+<p><small>The <tt>enum</tt> keyword is recognized and
+interpreted.</small></p>
+<a name="entry , fortran"></a>
+<h2>entry , fortran</h2>
+
+<p><small>The words <tt>entry</tt> and <tt>fortran</tt> are
+reserved under the restricted option. The words are not
+interpreted by the compiler.</small></p>
+<a name="2.4.1 Integer Constants"></a>
+<h2>2.4.1 Integer Constants</h2>
+
+<p><small>The type of an integer constant is the first of
+the corresponding list in which its value can be
+represented. Decimal: <tt>int, long, unsigned long</tt>;
+octal or hexadecimal: <tt>int, unsigned, long, unsigned
+long</tt>; suffixed by the letter L or l: <tt>long, unsigned
+long</tt>.</small></p>
+<a name="2.4.3 Character Constants"></a>
+<h2>2.4.3 Character Constants</h2>
+
+<p><small>A character constant is a sequence of 1 up to
+<tt>sizeof(int)</tt> characters enclosed in single quotes.
+The value of a character constant &rsquo;<i>c</i>
+<small><small>1</small></small> <i>c</i>
+<small><small>2</small></small> ...<i>c
+<small><small>n</small></small></i> &rsquo; is <i>d
+<small><small>n</small></small></i> +<i>M</i>&times;<i>d
+<small><small>n</small></small></i><small><small>&minus;1</small></small>
++...+<i>M
+<small><small>n</small></small></i><small><small>&minus;1</small></small>
+&times;<i>d</i> <small><small>2</small></small> +<i>M
+<small><small>n</small></small></i> &times;<i>d</i>
+<small><small>1</small></small> , where M is 1 + maximum
+unsigned number representable in an <tt>unsigned char</tt>,
+and <i>d <small><small>i</small></small></i> is the signed
+value (ASCII) of character <i>c
+<small><small>i</small></small></i> .</small></p>
+<a name="2.4.4 Floating Constants"></a>
+<h2>2.4.4 Floating Constants</h2>
+
+<p><small>The compiler does not support compile-time
+floating point arithmetic.</small></p>
+<a name="2.6 Hardware characteristics"></a>
+<h2>2.6 Hardware characteristics</h2>
+
+<p><small>The compiler is capable of producing EM code for
+machines with the following properties</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p><small>a <tt>char</tt> is 8 bits</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p><small>the size of <tt>int</tt> is equal to the word
+size</small></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>the size of <tt>short</tt> may not exceed the
+size of <tt>int</tt></small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>the size of <tt>int</tt> may not exceed the size
+of <tt>long</tt></small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>the size of pointers is equal to the size of
+either <tt>short</tt>, <tt>int</tt> or
+<tt>long</tt></small></p>
+</td>
+</table>
+<a name="4 What&rsquo;s in a name?"></a>
+<h2>4 What&rsquo;s in a name?</h2>
+<a name="char"></a>
+<h2>char</h2>
+
+<p><small>Objects of type <tt>char</tt> are taken to be
+signed. The combination <tt>unsigned char</tt> is
+legal.</small></p>
+<a name="unsigned"></a>
+<h2>unsigned</h2>
+
+<p><small>The type combinations <tt>unsigned char</tt>,
+<tt>unsigned short</tt> and <tt>unsigned long</tt> are
+supported.</small></p>
+<a name="enum"></a>
+<h2>enum</h2>
+
+<p><small>The data type <tt>enum</tt> is implemented as
+described in <i>Recent Changes to C</i> (see appendix A).
+<i>Cem</i> treats enumeration variables as if they were
+<tt>int</tt>.</small></p>
+<a name="void"></a>
+<h2>void</h2>
+
+<p><small>Type <tt>void</tt> is implemented. The type
+specifies an empty set of values, which takes no storage
+space.</small></p>
+<a name="Fundamental types"></a>
+<h2>Fundamental types</h2>
+
+<p><small>The names of the fundamental types can be
+redefined by the user, using <tt>typedef</tt>.</small></p>
+<a name="7 Expressions"></a>
+<h2>7 Expressions</h2>
+
+<p><small>The order of evaluation of expressions depends on
+the complexity of the subexpressions. In case of commutative
+operations, the most complex subexpression is evaluated
+first. Parameter lists are evaluated from right to
+left.</small></p>
+<a name="7.2 Unary operators"></a>
+<h2>7.2 Unary operators</h2>
+
+<p><small>The type of a <tt>sizeof</tt> expression is
+<tt>unsigned int</tt>.</small></p>
+<a name="7.13 Conditional operator"></a>
+<h2>7.13 Conditional operator</h2>
+
+<p><small>Both the second and the third expression in a
+conditional expression may include assignment operators.
+They may be structs or unions.</small></p>
+<a name="7.14 Assignment operators"></a>
+<h2>7.14 Assignment operators</h2>
+
+<p><small>Structures may be assigned, passed as arguments
+to functions, and returned by functions. The types of
+operands taking part must be the same.</small></p>
+<a name="8.2 Type specifiers"></a>
+<h2>8.2 Type specifiers</h2>
+
+<p><small>The combinations <tt>unsigned char</tt>,
+<tt>unsigned short</tt> and <tt>unsigned long</tt> are
+implemented.</small></p>
+<a name="8.5 Structure and union declarations"></a>
+<h2>8.5 Structure and union declarations</h2>
+
+<p><small>Fields of any integral type, either signed or
+unsigned, are supported, as long as the type fits in a word
+on the target machine.</small></p>
+
+<p><small>Fields are left adjusted by default; the first
+field is put into the left part of a word, the next one on
+the right side of the first one, etc. The <tt>-Vr</tt>
+option in the call of the compiler causes fields to be right
+adjusted within a machine word.</small></p>
+
+<p><small>The tags of structs and unions occupy a different
+name space from that of variables and that of member
+names.</small></p>
+<a name="9.7 Switch statement"></a>
+<h2>9.7 Switch statement</h2>
+
+<p><small>The type of <i>expression</i> in</small></p>
+<pre><small>     switch (<i>expression</i>) <i>statement
+</i></small></pre>
+
+<p><small>must be integral. A warning is given under the
+restricted option if the type is <tt>long</tt>.</small></p>
+<a name="10 External definitions"></a>
+<h2>10 External definitions</h2>
+
+<p><small>See [4] for a discussion on this complicated
+issue.</small></p>
+<a name="10.1 External function definitions"></a>
+<h2>10.1 External function definitions</h2>
+
+<p><small>Structures may be passed as arguments to
+functions, and returned by functions.</small></p>
+<a name="11.1 Lexical scope"></a>
+<h2>11.1 Lexical scope</h2>
+
+<p><small>Typedef names may be redeclared like any other
+variable name; the ice mentioned in &sect;11.1 is walked
+correctly.</small></p>
+<a name="12 Compiler control lines"></a>
+<h2>12 Compiler control lines</h2>
+
+<p><small>Lines which do not occur within comment, and with
+<tt>#</tt> as first character, are interpreted as compiler
+control line. There may be an arbitrary number of spaces,
+tabs and comments (collectively referred as <i>white
+space</i>) following the <tt>#</tt>. Comments may contain
+newline characters. Control lines with only white space
+between the <tt>#</tt> and the line separator are
+skipped.</small></p>
+
+<p><small>The #<tt>include</tt>, #<tt>ifdef</tt>,
+#<tt>ifndef</tt>, #<tt>undef</tt>, #<tt>else</tt> and
+#<tt>endif</tt> control lines and line directives consist of
+a fixed number of arguments. The list of arguments may be
+followed an arbitrary sequence of characters, in which
+comment is interpreted as such. (I.e., the text between
+<tt>/*</tt> and <tt>*/</tt> is skipped, regardless of
+newlines; note that commented-out lines beginning with
+<tt>#</tt> are not considered to be control
+lines.)</small></p>
+<a name="12.1 Token replacement"></a>
+<h2>12.1 Token replacement</h2>
+
+<p><small>The replacement text of macros is taken to be a
+string of characters, in which an identifier may stand for a
+formal parameter, and in which comment is interpreted as
+such. Comments and newline characters, preceeded by a
+backslash, in the replacement text are replaced by a space
+character.</small></p>
+
+<p><small>The actual parameters of a macro are considered
+tokens and are balanced with regard to <tt>()</tt>,
+<tt>{}</tt> and <tt>[]</tt>. This prevents the use of macros
+like</small></p>
+<pre><small>     CTL([)
+</small></pre>
+
+<p><small>Formal parameters of a macro must have unique
+names within the formal-parameter list of that
+macro.</small></p>
+
+<p><small>A message is given at the definition of a macro
+if the macro has already been #<tt>defined</tt>, while the
+number of formal parameters differ or the replacement texts
+are not equal (apart from leading and trailing white
+space).</small></p>
+
+<p><small>Recursive use of macros is detected by the
+compiler.</small></p>
+
+<p><small>Standard #<tt>defined</tt> macros are</small></p>
+<pre><small>     __FILE__  name of current input file as string constant
+     __DATE__  curent date as string constant; e.g. &quot;Tue Wed  2 14:45:23 1986&quot;
+     __LINE__  current line number as an integer
+</small></pre>
+
+<p><small>No message is given if <i>identifier</i> is not
+known in</small></p>
+<pre><small>     #undef <i>identifier
+</i></small></pre>
+<a name="12.2 File inclusion"></a>
+<h2>12.2 File inclusion</h2>
+
+<p><small>A newline character is appended to each file
+which is included.</small></p>
+<a name="12.3 Conditional compilation"></a>
+<h2>12.3 Conditional compilation</h2>
+
+<p><small>The #<tt>if</tt>, #<tt>ifdef</tt> and
+#<tt>ifndef</tt> control lines may be followed by an
+arbitrary number of</small></p>
+<pre><small>     #elif <i>constant-expression
+</i></small></pre>
+
+<p><small>control lines, before the corresponding
+#<tt>else</tt> or #<tt>endif</tt> is encountered. The
+construct</small></p>
+<pre><small>     #elif <i>constant-expression
+</i>     some text
+     #endif /* corresponding to #elif */
+</small></pre>
+
+<p><small>is equivalent to</small></p>
+<pre><small>     #else
+     #if <i>constant-expression
+</i>     some text
+     #endif /* corresponding to #if */
+     #endif /* corresponding to #else */
+</small></pre>
+
+<p><small>The <i>constant-expression</i> in #<tt>if</tt>
+and #<tt>elif</tt> control lines may contain the
+construction</small></p>
+<pre><small>     defined(<i>identifier</i>)
+</small></pre>
+
+<p><small>which is replaced by <tt>1</tt>, if
+<i>identifier</i> has been #<tt>defined</tt>, and by
+<tt>0</tt>, if not.</small></p>
+
+<p><small>Comments in skipped lines are interpreted as
+such.</small></p>
+<a name="12.4 Line control"></a>
+<h2>12.4 Line control</h2>
+
+<p><small>Line directives may occur in the following
+forms:</small></p>
+<pre><small>     #line <i>constant
+</i>     #line <i>constant</i> &quot;<i>filename</i>&quot;
+     #<i>constant
+</i>     #<i>constant</i> &quot;<i>filename</i>&quot;
+</small></pre>
+
+<p><small>Note that <i>filename</i> is enclosed in double
+quotes.</small></p>
+<a name="14.2 Functions"></a>
+<h2>14.2 Functions</h2>
+
+<p><small>If a pointer to a function is called, the
+function the pointer points to is called
+instead.</small></p>
+<a name="15 Constant expressions"></a>
+<h2>15 Constant expressions</h2>
+
+<p><small>The compiler distinguishes the following types of
+integral constant expressions</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="42%">
+
+<p><small>field-width specifier</small></p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p><small>case-entry specifier</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p><small>array-size specifier</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p><small>global variable initialization value</small></p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p><small>enum-value specifier</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>&bull;</small></p>
+</td>
+<td width="8%"></td>
+<td width="62%">
+
+<p><small>truth value in <tt>#if</tt> control
+line</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+
+<p><small>Constant integral expressions are compile-time
+evaluated while an effort is made to report overflow.
+Constant floating expressions are not compile-time
+evaluated.</small></p>
+<a name="2. Compiler flags"></a>
+<h2>2. Compiler flags</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;C</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Run the preprocessor stand-alone while
+maintaining the comments. Line directives are produced
+whenever needed.</small></p>
+</td>
+</table>
+
+
+<p><small><b>&minus;D</b><i>name</i>=<i>string-of-characters</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Define <i>name</i> as macro with
+<i>string-of-characters</i> as replacement text.</small></p>
+</td>
+</table>
+
+<p><small><b>&minus;D</b><i>name</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Equal to
+<b>&minus;D</b><i>name</i><b>=1</b>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;E</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Run the preprocessor stand alone, i.e., list the
+sequence of input tokens and delete any comments. Line
+directives are produced whenever needed.</small></p>
+</td>
+</table>
+
+<p><small><b>&minus;I</b><i>path</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Prepend <i>path</i> to the list of include
+directories. To put the directories &quot;include&quot;,
+&quot;sys/h&quot; and &quot;util/h&quot; into the include
+directory list in that order, the user has to
+specify</small></p>
+<!-- INDENTATION -->
+<pre><small>     -Iinclude -Isys/h -Iutil/h
+</small></pre>
+<!-- INDENTATION -->
+<p><small>An empty <i>path</i> causes the standard include
+directory (usually <tt>/usr/include</tt>) to be
+forgotten.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small><b>&minus;M</b><i>n</i></small></p>
+</td>
+<td width="93%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Set maximum significant identifier length to
+<i>n</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;n</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Suppress EM register messages. The user-declared
+variables are not stored into registers on the target
+machine.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;p</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Generate the EM <b>fil</b> and <b>lin</b>
+instructions in order to enable an interpreter to keep track
+of the current location in the source code.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;P</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Equivalent with <b>&minus;E</b>, but without line
+directives.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;R</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Interpret the input as restricted C (according to
+the language as described in [1]).</small></p>
+</td>
+</table>
+
+<p><small><b>&minus;T</b><i>path</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Create temporary files, if necessary, in directory
+<i>path</i>.</small></p>
+</td>
+</table>
+
+<p><small><b>&minus;U</b><i>name</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Get rid of the compiler-predefined macro
+<i>name</i>, i.e., consider</small></p>
+<!-- INDENTATION -->
+<pre><small>     #undef <i>name
+</i></small></pre>
+<!-- INDENTATION -->
+<p><small>to appear in the beginning of the
+file.</small></p>
+</td>
+</table>
+
+<p><small><b>&minus;V</b><i>cm</i>.<i>n</i>,
+<b>&minus;V</b><i>cm</i>.<i>ncm</i>.<i>n</i> ...</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Set the size and alignment requirements. The
+letter <i>c</i> indicates the simple type, which is one of
+<b>s</b>(short), <b>i</b>(int), <b>l</b>(long),
+<b>f</b>(float), <b>d</b>(double) or <b>p</b>(pointer). If
+<i>c</i> is <b>S</b> or <b>U</b>, then <i>n</i> is taken to
+be the initial alignment of structs or unions, respectively.
+The effective alignment of a struct or union is the least
+common multiple of the initial struct/union alignment and
+the alignments of its members. The <i>m</i> parameter can be
+used to specify the length of the type (in bytes) and the
+<i>n</i> parameter for the alignment of that type. Absence
+of <i>m</i> or <i>n</i> causes the default value to be
+retained. To specify that the bitfields should be right
+adjusted instead of the default left adjustment, specify
+<b>r</b> as <i>c</i> parameter.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small><b>&minus;w</b></small></p>
+</td>
+<td width="6%"></td>
+<td width="50%">
+
+<p><small>Suppress warning messages</small></p>
+</td>
+<td width="39%">
+</td>
+</table>
+
+
+<p><small><b>&minus;&minus;</b><i>character</i></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Set debug-flag <i>character</i>. This enables some
+special features offered by a debug and develop version of
+the compiler. Some particular flags may be recognized,
+others may have surprising effects.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>d</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>Generate a dependency graph, reflecting the
+calling structure of functions. Lines of the
+form</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<pre><small>     DFA: <i>calling-function</i>: <i>called-function
+</i></small></pre>
+<!-- INDENTATION -->
+<p><small>are generated whenever a function call is
+encountered.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>f</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>Dump whole identifier table, including macros and
+reserved words.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>h</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="58%">
+
+<p><small>Supply hash-table statistics.</small></p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>i</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><small>Print names of included files.</small></p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>m</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>Supply statistics concerning the memory
+allocation.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>t</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p><small>Dump table of identifiers.</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>u</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>Generate extra statistics concerning the
+predefined types and identifiers. Works in combination with
+<b>f</b> or <b>t</b>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p><small><b>x</b></small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>Print expression trees in human-readable
+format.</small></p>
+</td>
+</table>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[1]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Brian W. Kernighan, Dennis M. Ritchie, <i>The C
+Programming Language</i></small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[2]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>L. Rosler, <i>Draft Proposed Standard -
+Programming Language C,</i> ANSI X3J11 Language
+Subcommittee</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[3]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Erik H. Baalbergen, Dick Grune, Maarten Waage,
+<i>The CEM Compiler,</i> Informatica Manual IM-4, Dept. of
+Mathematics and Computer Science, Vrije Universiteit,
+Amsterdam, The Netherlands</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[4]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Erik H. Baalbergen, <i>Modeling global
+declarations in C,</i> internal paper</small></p>
+</td>
+</table>
+<a name="Appendix A - Enumeration Type"></a>
+<h2>Appendix A - Enumeration Type</h2>
+
+<p>The syntax is</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><i>enum-specifier</i>:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><tt>enum</tt> { <i>enum-list</i> }<tt><br>
+enum</tt> <i>identifier</i> { <i>enum-list</i> }<tt><br>
+enum</tt> <i>identifier</i></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><i>enum-list</i> :</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><i>enumerator<br>
+enum-list</i> , <i>enumerator</i></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><i>enumerator</i> :</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><i>identifier<br>
+identifier</i> = <i>constant-expression</i></p>
+</td>
+</table>
+
+<p>The identifier has the same role as the structure tag in
+a struct specification. It names a particular enumeration
+type.</p>
+
+<p>The identifiers in the enum-list are declared as
+constants, and may appear whenever constants are required.
+If no enumerators with <b>=</b> appear, then the values of
+the constants begin at 0 and increase by 1 as the
+declaration is read from left to right. An enumerator with
+<b>=</b> gives the associated identifier the value
+indicated; subsequent identifiers continue the progression
+from the assigned value.</p>
+
+<p>Enumeration tags and constants must all be distinct,
+and, unlike structure tags and members, are drawn from the
+same set as ordinary identifiers.</p>
+
+<p>Objects of a given enumeration type are regarded as
+having a type distinct from objects of all other types.</p>
+<a name="Appendix B: C grammar in LL(1) form"></a>
+<h2>Appendix B: C grammar in LL(1) form</h2>
+
+<p>The <b>bold-faced</b> and <i>italicized</i> tokens
+represent terminal symbols.</p>
+<pre><b>external definitions
+</b>program:  external-definition*
+external-definition:  ext-decl-specifiers [declarator [function  |  non-function]  |  &rsquo;<b>;</b>&rsquo;]  |  asm-statement
+ext-decl-specifiers:  decl-specifiers?
+non-function:  initializer? [&rsquo;<b>,</b>&rsquo; init-declarator]* &rsquo;<b>;</b>&rsquo;
+function:  declaration* compound-statement
+
+<b>declarations
+</b>declaration:  decl-specifiers init-declarator-list? &rsquo;<b>;</b>&rsquo;
+decl-specifiers:  other-specifier+ [single-type-specifier other-specifier*]?  |  single-type-specifier other-specifier*
+other-specifier: <b> auto</b>  | <b> static</b>  | <b> extern</b>  | <b> typedef</b>  | <b> register</b>  | <b> short</b>  | <b> long</b>  | <b> unsigned
+</b>type-specifier:  decl-specifiers
+single-type-specifier: <i> type-identifier</i>  |  struct-or-union-specifier  |  enum-specifier
+init-declarator-list:  init-declarator [&rsquo;<b>,</b>&rsquo; init-declarator]*
+init-declarator:  declarator initializer?
+declarator:  primary-declarator [&rsquo;<b>(</b>&rsquo; formal-list ? &rsquo;<b>)</b>&rsquo;  |  arrayer]*  |  &rsquo;<b>*</b>&rsquo; declarator
+primary-declarator:  identifier  |  &rsquo;<b>(</b>&rsquo; declarator &rsquo;<b>)</b>&rsquo;
+arrayer:  &rsquo;<b>[</b>&rsquo; constant-expression? &rsquo;<b>]</b>&rsquo;
+formal-list:  formal [&rsquo;<b>,</b>&rsquo; formal]*
+formal:  identifier
+enum-specifier: <b> enum</b> [enumerator-pack  |  identifier enumerator-pack?]
+enumerator-pack:  &rsquo;<b>{</b>&rsquo; enumerator [&rsquo;<b>,</b>&rsquo; enumerator]* &rsquo;<b>,</b>&rsquo;? &rsquo;<b>}</b>&rsquo;
+enumerator:  identifier [&rsquo;<b>=</b>&rsquo; constant-expression]?
+struct-or-union-specifier:  [ <b>struct</b>  | <b> union</b>] [ struct-declaration-pack  |  identifier struct-declaration-pack?]
+struct-declaration-pack:  &rsquo;<b>{</b>&rsquo; struct-declaration+ &rsquo;<b>}</b>&rsquo;
+struct-declaration:  type-specifier struct-declarator-list &rsquo;<b>;</b>&rsquo;?
+struct-declarator-list:  struct-declarator [&rsquo;<b>,</b>&rsquo; struct-declarator]*
+struct-declarator:  declarator bit-expression?  |  bit-expression
+bit-expression:  &rsquo;<b>:</b>&rsquo; constant-expression
+initializer:  &rsquo;<b>=</b>&rsquo;? initial-value
+cast:  &rsquo;<b>(</b>&rsquo; type-specifier abstract-declarator &rsquo;<b>)</b>&rsquo;
+abstract-declarator:  primary-abstract-declarator [&rsquo;<b>(</b>&rsquo; &rsquo;<b>)</b>&rsquo;  |  arrayer]*  |  &rsquo;<b>*</b>&rsquo; abstract-declarator
+primary-abstract-declarator:  [&rsquo;<b>(</b>&rsquo; abstract-declarator &rsquo;<b>)</b>&rsquo;]?
+
+<b>statements
+</b>statement:
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>expression-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| label &rsquo;<b>:</b>&rsquo; statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| compound-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| if-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| while-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| do-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| for-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| switch-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| case-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| default-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| break-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| continue-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| return-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| jump</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| &rsquo;<b>;</b>&rsquo;</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>| asm-statement</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>;</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>expression-statement: expression
+&rsquo;<b>;</b>&rsquo;<br>
+label: identifier<br>
+if-statement: <b>if</b> &rsquo;<b>(</b>&rsquo; expression
+&rsquo;<b>)</b>&rsquo; statement [<b>else</b>
+statement]?<br>
+while-statement: <b>while</b> &rsquo;<b>(</b>&rsquo;
+expression &rsquo;<b>)</b>&rsquo; statement<br>
+do-statement: <b>do</b> statement <b>while</b>
+&rsquo;<b>(</b>&rsquo; expression &rsquo;<b>)</b>&rsquo;
+&rsquo;<b>;</b>&rsquo;<br>
+for-statement: <b>for</b> &rsquo;<b>(</b>&rsquo; expression?
+&rsquo;<b>;</b>&rsquo; expression? &rsquo;<b>;</b>&rsquo;
+expression? &rsquo;<b>)</b>&rsquo; statement<br>
+switch-statement: <b>switch</b> &rsquo;<b>(</b>&rsquo;
+expression &rsquo;<b>)</b>&rsquo; statement<br>
+case-statement: <b>case</b> constant-expression
+&rsquo;<b>:</b>&rsquo; statement<br>
+default-statement: <b>default</b> &rsquo;<b>:</b>&rsquo;
+statement<br>
+break-statement: <b>break</b> &rsquo;<b>;</b>&rsquo;<br>
+continue-statement: <b>continue</b>
+&rsquo;<b>;</b>&rsquo;<br>
+return-statement: <b>return</b> expression?
+&rsquo;<b>;</b>&rsquo;<br>
+jump: <b>goto</b> identifier &rsquo;<b>;</b>&rsquo;<br>
+compound-statement: &rsquo;<b>{</b>&rsquo; declaration*
+statement* &rsquo;<b>}</b>&rsquo;<br>
+asm-statement: <b>asm</b> &rsquo;<b>(</b>&rsquo;
+<i>string</i> &rsquo;<b>)</b>&rsquo;
+&rsquo;<b>;</b>&rsquo;</p>
+
+<p><b>expressions</b><br>
+initial-value: assignment-expression |
+initial-value-pack<br>
+initial-value-pack: &rsquo;<b>{</b>&rsquo;
+initial-value-list &rsquo;<b>}</b>&rsquo;<br>
+initial-value-list: initial-value [&rsquo;<b>,</b>&rsquo;
+initial-value]* &rsquo;<b>,</b>&rsquo;?<br>
+primary: <i>identifier</i> | constant | <i>string</i> |
+&rsquo;<b>(</b>&rsquo; expression &rsquo;<b>)</b>&rsquo;<br>
+secundary: primary [index-pack | parameter-pack |
+selection]*<br>
+index-pack: &rsquo;<b>[</b>&rsquo; expression
+&rsquo;<b>]</b>&rsquo;<br>
+parameter-pack: &rsquo;<b>(</b>&rsquo; parameter-list?
+&rsquo;<b>)</b>&rsquo;<br>
+selection: [&rsquo;<b>.</b>&rsquo; |
+&rsquo;<b>&minus;&gt;</b>&rsquo;] identifier<br>
+parameter-list: assignment-expression
+[&rsquo;<b>,</b>&rsquo; assignment-expression]*<br>
+postfixed: secundary postop?<br>
+unary: cast unary | postfixed | unop unary | size-of<br>
+size-of: <b>sizeof</b> [cast | unary]<br>
+binary-expression: unary [binop binary-expression]*<br>
+conditional-expression: binary-expression
+[&rsquo;<b>?</b>&rsquo; expression &rsquo;<b>:</b>&rsquo;
+assignment-expression]?<br>
+assignment-expression: conditional-expression [asgnop
+assignment-expression]?<br>
+expression: assignment-expression [&rsquo;<b>,</b>&rsquo;
+assignment-expression]*<br>
+unop: &rsquo;<b>*</b>&rsquo; | &rsquo;<b>&amp;</b>&rsquo; |
+&rsquo;<b>&minus;</b>&rsquo; | &rsquo;<b>!</b>&rsquo; |
+&rsquo;<b>~</b> &rsquo; | &rsquo;<b>++</b>&rsquo; |
+&rsquo;<b>&minus;&minus;</b>&rsquo;<br>
+postop: &rsquo;<b>++</b>&rsquo; |
+&rsquo;<b>&minus;&minus;</b>&rsquo;<br>
+multop: &rsquo;<b>*</b>&rsquo; | &rsquo;<b>/</b>&rsquo; |
+&rsquo;<b>%</b>&rsquo;<br>
+addop: &rsquo;<b>+</b>&rsquo; |
+&rsquo;<b>&minus;</b>&rsquo;<br>
+shiftop: &rsquo;<b>&lt;&lt;</b>&rsquo; |
+&rsquo;<b>&gt;&gt;</b>&rsquo;<br>
+relop: &rsquo;<b>&lt;</b>&rsquo; | &rsquo;<b>&gt;</b>&rsquo;
+| &rsquo;<b>&lt;=</b>&rsquo; |
+&rsquo;<b>&gt;=</b>&rsquo;<br>
+eqop: &rsquo;<b>==</b>&rsquo; | &rsquo;<b>!=</b>&rsquo;<br>
+arithop: multop | addop | shiftop |
+&rsquo;<b>&amp;</b>&rsquo; | &rsquo;<b>^</b> &rsquo; |
+&rsquo;<b>|</b>&rsquo;<br>
+binop: arithop | relop | eqop |
+&rsquo;<b>&amp;&amp;</b>&rsquo; |
+&rsquo;<b>||</b>&rsquo;<br>
+asgnop: &rsquo;<b>=</b>&rsquo; | &rsquo;<b>+</b>&rsquo;
+&rsquo;<b>=</b>&rsquo; | &rsquo;<b>&minus;</b>&rsquo;
+&rsquo;<b>=</b>&rsquo; | &rsquo;<b>*</b>&rsquo;
+&rsquo;<b>=</b>&rsquo; | &rsquo;<b>/</b>&rsquo;
+&rsquo;<b>=</b>&rsquo; | &rsquo;<b>%</b>&rsquo;
+&rsquo;<b>=</b>&rsquo;</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p>| &rsquo;<b>&lt;&lt;</b>&rsquo; &rsquo;<b>=</b>&rsquo; |
+&rsquo;<b>&gt;&gt;</b>&rsquo; &rsquo;<b>=</b>&rsquo; |
+&rsquo;<b>&amp;</b>&rsquo; &rsquo;<b>=</b>&rsquo; |
+&rsquo;<b>^</b> &rsquo; &rsquo;<b>=</b>&rsquo; |
+&rsquo;<b>|</b>&rsquo; &rsquo;<b>=</b>&rsquo;</p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p>| &rsquo;<b>+=</b>&rsquo; |
+&rsquo;<b>&minus;=</b>&rsquo; | &rsquo;<b>*=</b>&rsquo; |
+&rsquo;<b>/=</b>&rsquo; | &rsquo;<b>%=</b>&rsquo;</p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p>| &rsquo;<b>&lt;&lt;=</b>&rsquo; |
+&rsquo;<b>&gt;&gt;=</b>&rsquo; | &rsquo;<b>&amp;=</b>&rsquo;
+| &rsquo;<b>^=</b>&rsquo; | &rsquo;<b>|=</b>&rsquo;</p>
+</td>
+</table>
+
+<p>constant: <i>integer</i> | <i>floating</i><br>
+constant-expression: assignment-expression<br>
+identifier: <i>identifier</i> | <i>type-identifier</i></p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/crefman.pdf b/doc/tack/crefman.pdf
new file mode 100644 (file)
index 0000000..87407d4
Binary files /dev/null and b/doc/tack/crefman.pdf differ
diff --git a/doc/tack/ego.html b/doc/tack/ego.html
new file mode 100644 (file)
index 0000000..4d6353a
--- /dev/null
@@ -0,0 +1,9470 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:28 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The design and implementation of the EM Global Optimizer</title>
+</head>
+<body>
+
+<h1 align=center>The design and implementation of the EM Global Optimizer</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Overview of the global optimizer">2. Overview of the global optimizer</a><br>
+<a href="#2.1. The ACK compilation process">2.1. The ACK compilation process</a><br>
+<a href="#2.2. The EM code">2.2. The EM code</a><br>
+<a href="#2.3. Requirements on the EM input">2.3. Requirements on the EM input</a><br>
+<a href="#2.4. Structure of the optimizer">2.4. Structure of the optimizer</a><br>
+<a href="#2.5. Structure of this document">2.5. Structure of this document</a><br>
+<a href="#2.6. References">2.6. References</a><br>
+<a href="#3. The Intermediate Code and the IC phase">3. The Intermediate Code and the IC phase</a><br>
+<a href="#3.1. Introduction">3.1. Introduction</a><br>
+<a href="#3.2. Representation of complex data structures in a sequential file">3.2. Representation of complex data structures in a sequential file</a><br>
+<a href="#3.3. Definition of the intermediate code">3.3. Definition of the intermediate code</a><br>
+<a href="#3.3.1. The object table">3.3.1. The object table</a><br>
+<a href="#3.3.2. The procedure table">3.3.2. The procedure table</a><br>
+<a href="#3.3.3. The EM text">3.3.3. The EM text</a><br>
+<a href="#3.3.4. The control flow graphs">3.3.4. The control flow graphs</a><br>
+<a href="#3.3.5. The loop tables">3.3.5. The loop tables</a><br>
+<a href="#3.4. External representation of the intermediate code">3.4. External representation of the intermediate code</a><br>
+<a href="#3.5. The Intermediate Code construction phase">3.5. The Intermediate Code construction phase</a><br>
+<a href="#3.5.1. Implementation">3.5.1. Implementation</a><br>
+<a href="#3.5.2. Source files of IC">3.5.2. Source files of IC</a><br>
+<a href="#4. The Control Flow Phase">4. The Control Flow Phase</a><br>
+<a href="#4.1. Partitioning into basic blocks">4.1. Partitioning into basic blocks</a><br>
+<a href="#4.2. Control Flow">4.2. Control Flow</a><br>
+<a href="#4.3. Immediate dominators">4.3. Immediate dominators</a><br>
+<a href="#4.4. Loop detection">4.4. Loop detection</a><br>
+<a href="#4.5. Interprocedural analysis">4.5. Interprocedural analysis</a><br>
+<a href="#4.6. Source files">4.6. Source files</a><br>
+<a href="#5. Inline substitution">5. Inline substitution</a><br>
+<a href="#5.1. Introduction">5.1. Introduction</a><br>
+<a href="#5.2. Parameters and local variables.">5.2. Parameters and local variables.</a><br>
+<a href="#5.3. Feasibility and desirability analysis">5.3. Feasibility and desirability analysis</a><br>
+<a href="#5.4. Heuristic rules">5.4. Heuristic rules</a><br>
+<a href="#5.5. Implementation">5.5. Implementation</a><br>
+<a href="#5.5.1. Data structures">5.5.1. Data structures</a><br>
+<a href="#5.5.1.1. The procedure table">5.5.1.1. The procedure table</a><br>
+<a href="#5.5.1.2. Call-count information">5.5.1.2. Call-count information</a><br>
+<a href="#5.5.1.3. The call-list">5.5.1.3. The call-list</a><br>
+<a href="#5.5.2. The first subphase: procedure analysis">5.5.2. The first subphase: procedure analysis</a><br>
+<a href="#5.5.3. The second subphase: making decisions">5.5.3. The second subphase: making decisions</a><br>
+<a href="#5.5.4. The third subphase: doing transformations">5.5.4. The third subphase: doing transformations</a><br>
+<a href="#5.6. Source files of IL">5.6. Source files of IL</a><br>
+<a href="#6. Strength reduction">6. Strength reduction</a><br>
+<a href="#6.1. Introduction">6.1. Introduction</a><br>
+<a href="#6.2. The model of strength reduction">6.2. The model of strength reduction</a><br>
+<a href="#6.2.1. Induction variables">6.2.1. Induction variables</a><br>
+<a href="#6.2.2. Recognized expressions">6.2.2. Recognized expressions</a><br>
+<a href="#6.2.3. Transformations">6.2.3. Transformations</a><br>
+<a href="#6.3. Implementation">6.3. Implementation</a><br>
+<a href="#6.3.1. Finding induction variables">6.3.1. Finding induction variables</a><br>
+<a href="#6.3.2. Optimizing expressions">6.3.2. Optimizing expressions</a><br>
+<a href="#6.4. Source files of SR">6.4. Source files of SR</a><br>
+<a href="#7. Common subexpression elimination">7. Common subexpression elimination</a><br>
+<a href="#7.1. Introduction">7.1. Introduction</a><br>
+<a href="#7.2. Specification of the Common Subexpression Elimination phase">7.2. Specification of the Common Subexpression Elimination phase</a><br>
+<a href="#7.2.1. The working window">7.2.1. The working window</a><br>
+<a href="#7.2.2. Recognized expressions.">7.2.2. Recognized expressions.</a><br>
+<a href="#7.2.3. Transformations">7.2.3. Transformations</a><br>
+<a href="#7.3. Implementation">7.3. Implementation</a><br>
+<a href="#7.3.1. The value number method">7.3.1. The value number method</a><br>
+<a href="#7.3.2. Entities">7.3.2. Entities</a><br>
+<a href="#7.3.3. Parsing expressions">7.3.3. Parsing expressions</a><br>
+<a href="#7.3.4. Updating entities">7.3.4. Updating entities</a><br>
+<a href="#7.3.5. Changing the EM text">7.3.5. Changing the EM text</a><br>
+<a href="#7.3.6. Desirability analysis">7.3.6. Desirability analysis</a><br>
+<a href="#7.3.7. The algorithm">7.3.7. The algorithm</a><br>
+<a href="#7.4. Implementation.">7.4. Implementation.</a><br>
+<a href="#7.4.1. Partioning the EM instructions">7.4.1. Partioning the EM instructions</a><br>
+<a href="#7.4.2. Parsing expressions">7.4.2. Parsing expressions</a><br>
+<a href="#7.4.3. Updating entities">7.4.3. Updating entities</a><br>
+<a href="#7.4.4. Additions and replacements.">7.4.4. Additions and replacements.</a><br>
+<a href="#7.4.5. Desirability analysis">7.4.5. Desirability analysis</a><br>
+<a href="#7.4.6. The algorithm">7.4.6. The algorithm</a><br>
+<a href="#7.5. Source files of CS">7.5. Source files of CS</a><br>
+<a href="#8. Stack pollution">8. Stack pollution</a><br>
+<a href="#8.1. Introduction">8.1. Introduction</a><br>
+<a href="#8.2. Implementation">8.2. Implementation</a><br>
+<a href="#9. Cross jumping">9. Cross jumping</a><br>
+<a href="#9.1. Introduction">9.1. Introduction</a><br>
+<a href="#9.2. Implementation">9.2. Implementation</a><br>
+<a href="#10. Branch Optimization">10. Branch Optimization</a><br>
+<a href="#10.1. Introduction">10.1. Introduction</a><br>
+<a href="#10.1.1. Fusion of basic blocks">10.1.1. Fusion of basic blocks</a><br>
+<a href="#10.1.2. While-loop optimization">10.1.2. While-loop optimization</a><br>
+<a href="#10.2. Implementation">10.2. Implementation</a><br>
+<a href="#11. Use-Definition analysis">11. Use-Definition analysis</a><br>
+<a href="#11.1. Introduction">11.1. Introduction</a><br>
+<a href="#11.2. Data flow information">11.2. Data flow information</a><br>
+<a href="#11.2.1. Use-Definition information">11.2.1. Use-Definition information</a><br>
+<a href="#11.2.2. Copy information">11.2.2. Copy information</a><br>
+<a href="#11.3. Pointers and subroutine calls">11.3. Pointers and subroutine calls</a><br>
+<a href="#11.4. Implementation">11.4. Implementation</a><br>
+<a href="#11.5. Source files of UD">11.5. Source files of UD</a><br>
+<a href="#12. Live-Variable analysis">12. Live-Variable analysis</a><br>
+<a href="#12.1. Introduction">12.1. Introduction</a><br>
+<a href="#12.2. Implementation">12.2. Implementation</a><br>
+<a href="#13. Register Allocation">13. Register Allocation</a><br>
+<a href="#13.1. Introduction">13.1. Introduction</a><br>
+<a href="#13.2. Usage of registers in ACK compilers">13.2. Usage of registers in ACK compilers</a><br>
+<a href="#13.2.1. Usage of registers without the intervention of the Global Optimizer">13.2.1. Usage of registers without the intervention of the Global Optimizer</a><br>
+<a href="#13.2.2. The role of the Global Optimizer">13.2.2. The role of the Global Optimizer</a><br>
+<a href="#13.2.3. The interface between the register allocator and the code generator">13.2.3. The interface between the register allocator and the code generator</a><br>
+<a href="#13.3. The register allocation phase">13.3. The register allocation phase</a><br>
+<a href="#13.3.1. Overview">13.3.1. Overview</a><br>
+<a href="#13.3.2. The item recognition subphase">13.3.2. The item recognition subphase</a><br>
+<a href="#13.3.3. The allocation determination subphase">13.3.3. The allocation determination subphase</a><br>
+<a href="#13.3.4. The rivals computation subphase">13.3.4. The rivals computation subphase</a><br>
+<a href="#13.3.5. The profits computation subphase">13.3.5. The profits computation subphase</a><br>
+<a href="#13.3.6. The packing subphase">13.3.6. The packing subphase</a><br>
+<a href="#13.3.7. The transformation subphase">13.3.7. The transformation subphase</a><br>
+<a href="#13.4. Source files of RA">13.4. Source files of RA</a><br>
+<a href="#14. Compact assembly generation">14. Compact assembly generation</a><br>
+<a href="#14.1. Introduction">14.1. Introduction</a><br>
+<a href="#14.2. Implementation">14.2. Implementation</a><br>
+<a href="#Acknowledgements">Acknowledgements</a><br>
+<a href="#References">References</a><br>
+<a href="#References">References</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>H.E. Bal</i><br>
+Vrije Universiteit<br>
+Wiskundig Seminarium, Amsterdam</p>
+
+<p>The EM Global Optimizer is part of the Amsterdam
+Compiler Kit, a toolkit for making retargetable compilers.
+It optimizes the intermediate code common to all compilers
+of the toolkit (EM), so it can be used for all programming
+languages and all processors supported by the kit.</p>
+
+<p>The optimizer is based on well-understood concepts like
+control flow analysis and data flow analysis. It performs
+the following optimizations: Inline Substitution, Strength
+Reduction, Common Subexpression Elimination, Stack
+Pollution, Cross Jumping, Branch Optimization, Copy
+Propagation, Constant Propagation, Dead Code Elimination and
+Register Allocation.</p>
+
+<p>This report describes the design of the optimizer and
+several of its implementation issues.</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p align=center><img src="grohtml-102721.png"></p>
+
+<p>The EM Global Optimizer is part of a software toolkit
+for making production-quality retargetable compilers. This
+toolkit, called the Amsterdam Compiler Kit [Tane81a,
+Tane83b] runs under the Unix*</p>
+
+<p align=center><img src="grohtml-102722.png"></p>
+
+<p>operating system.<br>
+The main design philosophy of the toolkit is to use a
+language- and machine-independent intermediate code, called
+EM. [Tane83a] The basic compilation process can be split up
+into two parts. A language-specific front end translates the
+source program into EM. A machine-specific back end
+transforms EM to assembly code of the target machine.</p>
+
+<p>The global optimizer is an optional phase of the
+compilation process, and can be used to obtain machine code
+of a higher quality. The optimizer transforms EM-code to
+better EM-code, so it comes between the front end and the
+back end. It can be used with any combination of languages
+and machines, as far as they are supported by the compiler
+kit.</p>
+
+<p>This report describes the design of the global optimizer
+and several of its implementation issues. Measurements can
+be found in. [Bal86a]</p>
+<a name="2. Overview of the global optimizer"></a>
+<h2>2. Overview of the global optimizer</h2>
+<a name="2.1. The ACK compilation process"></a>
+<h2>2.1. The ACK compilation process</h2>
+
+<p>The EM Global Optimizer is one of three optimizers that
+are part of the Amsterdam Compiler Kit (ACK). The phases of
+ACK are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>A Front End translates a source program to EM</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The Peephole Optimizer [a] reads EM code and produces
+&rsquo;better&rsquo; EM code. It performs a number of
+optimizations (mostly peephole optimizations) such as
+constant folding, strength reduction and unreachable code
+elimination.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The Global Optimizer further improves the EM code.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The Code Generator transforms EM to assembly code of the
+target computer.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The Target Optimizer improves the assembly code.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>An Assembler/Loader generates an executable file.</p>
+</td>
+</table>
+
+<p>For a more extensive overview of the ACK compilation
+process, we refer to. [Tane81a, Tane83b]</p>
+
+<p>The input of the Global Optimizer may consist of files
+and libraries. Every file or module in the library must
+contain EM code in Compact Assembly Language format.
+[Tane83a, section 11.2] The output consists of one such EM
+file. The input files and libraries together need not
+constitute an entire program, although as much of the
+program as possible should be supplied. The more information
+about the program the optimizer gets, the better its output
+code will be.</p>
+
+<p>The Global Optimizer is language- and
+machine-independent, i.e. it can be used for all languages
+and machines supported by ACK. Yet, it puts some unavoidable
+restrictions on the EM code produced by the Front End (see
+below). It must have some knowledge of the target machine.
+This knowledge is expressed in a machine description table
+which is passed as argument to the optimizer. This table
+does not contain very detailed information about the target
+(such as its instruction set and addressing modes).</p>
+<a name="2.2. The EM code"></a>
+<h2>2.2. The EM code</h2>
+
+<p>The definition of EM, the intermediate code of all ACK
+compilers, is given in a separate document. [Tane83a] We
+will only discuss some features of EM that are most relevant
+to the Global Optimizer.</p>
+
+<p>EM is the assembly code of a virtual <i>stack
+machine</i>. All operations are performed on the top of the
+stack. For example, the statement &quot;A := B + 3&quot; may
+be expressed in EM as:</p>
+
+<p align=center><img src="grohtml-102723.png"></p>
+
+<p>So EM is essentially a <i>postfix</i> code.</p>
+
+<p>EM has a rich instruction set, containing several
+arithmetic and logical operators. It also contains
+special-case instructions (such as INCrement).</p>
+
+<p>EM has <i>global</i> (<i>external</i>) variables,
+accessible by all procedures and <i>local</i> variables,
+accessible by a few (nested) procedures. The local variables
+of a lexically enclosing procedure may be accessed via a
+<i>static link</i>. EM has instructions to follow the static
+chain. There are EM instruction to allow a procedure to
+access its local variables directly (such as LOL and STL
+above). Local variables are referenced via an offset in the
+stack frame of the procedure, rather than by their names
+(e.g. -2 and -4 above). The EM code does not contain the
+(source language) type of the variables.</p>
+
+<p>All structured statements in the source program are
+expressed in low level jump instructions. Besides
+conditional and unconditional branch instructions, there are
+two case instructions (CSA and CSB), to allow efficient
+translation of case statements.</p>
+<a name="2.3. Requirements on the EM input"></a>
+<h2>2.3. Requirements on the EM input</h2>
+
+<p>As the optimizer should be useful for all languages, it
+clearly should not put severe restrictions on the EM code of
+the input. There is, however, one immovable requirement: it
+must be possible to determine the <i>flow of control</i> of
+the input program. As virtually all global optimizations are
+based on control flow information, the optimizer would be
+totally powerless without it. For this reason we restrict
+the usage of the case jump instructions (CSA/CSB) of EM.
+Such an instruction is always called with the address of a
+case descriptor on top the the stack. [Tane83a section 7.4]
+This descriptor contains the labels of all possible
+destinations of the jump. We demand that all case
+descriptors are allocated in a global data fragment of type
+ROM, i.e. the case descriptors may not be modifyable.
+Furthermore, any case instruction should be immediately
+preceded by a LAE (Load Address External) instruction, that
+loads the address of the descriptor, so the descriptor can
+be uniquely identified.</p>
+
+<p>The optimizer will work improperly if the user deceives
+the control flow. We will give two methods to do this.</p>
+
+<p>In &quot;C&quot; the notorious library routines
+&quot;setjmp&quot; and &quot;longjmp&quot; [Kern79a] may be
+used to jump out of a procedure, but can also be used for a
+number of other stuffy purposes, for example, to create an
+extra entry point in a loop.</p>
+<pre>      while (condition) {
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>....<br>
+setjmp(buf);<br>
+...</p>
+</table>
+
+<p>}<br>
+...<br>
+longjmp(buf);</p>
+
+<p>The invocation to longjmp actually is a jump to the
+place of the last call to setjmp with the same argument
+(buf). As the calls to setjmp and longjmp are
+indistinguishable from normal procedure calls, the optimizer
+will not see the danger. No need to say that several loop
+optimizations will behave unexpectedly when presented with
+such pathological input.</p>
+
+<p>Another way to deceive the flow of control is by using
+exception handling routines. Ada*</p>
+
+<p align=center><img src="grohtml-102724.png"></p>
+
+<p>has clearly recognized the dangers of exception
+handling, but other languages (such as PL/I) have not.
+[Ichb79a]</p>
+
+<p>The optimizer will be more effective if the EM input
+contains some extra information about the source program.
+Especially the <i>register message</i> is very important.
+These messages indicate which local variables may never be
+accessed indirectly. Most optimizations benefit
+significantly by this information.</p>
+
+<p>The Inline Substitution technique needs to know how many
+bytes of formal parameters every procedure accesses. Only
+calls to procedures for which the EM code contains this
+information will be substituted in line.</p>
+<a name="2.4. Structure of the optimizer"></a>
+<h2>2.4. Structure of the optimizer</h2>
+
+<p>The Global Optimizer is organized as a number of
+<i>phases</i>, each one performing some task. The main
+structure is as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>IC</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>the Intermediate Code construction phase transforms EM
+into the intermediate code (ic) of the optimizer</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>CF</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>the Control Flow phase extends the ic with control flow
+information and interprocedural information</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>OPTs</p>
+</td>
+<td width="4%"></td>
+<td width="88%">
+
+<p>zero or more optimization phases, each one performing
+one or more related optimizations</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>CA</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>the Compact Assembly phase generates Compact Assembly
+Language EM code out of ic.</p>
+</td>
+</table>
+
+<p>An important issue in the design of a global optimizer
+is the interaction between optimization techniques. It is
+often advantageous to combine several techniques in one
+algorithm that takes into account all interactions between
+them. Ideally, one single algorithm should be developed that
+does all optimizations simultaneously and deals with all
+possible interactions. In practice, such an algorithm is
+still far out of reach. Instead some rather ad hoc (albeit
+important) combinations are chosen, such as Common
+Subexpression Elimination and Register Allocation. [Prab80a,
+Seth70a]</p>
+
+<p>In the Em Global Optimizer there is one separate
+algorithm for every technique. Note that this does not mean
+that all techniques are independent of each other.</p>
+
+<p>In principle, the optimization phases can be run in any
+order; a phase may even be run more than once. However, the
+following rules should be obeyed:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the Live Variable analysis phase (LV) must be run prior
+to Register Allocation (RA), as RA uses information
+outputted by LV.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>RA should be the last phase; this is a consequence of
+the way the interface between RA and the Code Generator is
+defined.</p>
+</td>
+</table>
+
+<p>The ordering of the phases has significant impact on the
+quality of the produced code. In [Leve79a] two kinds of
+phase ordering problems are distinguished. If two techniques
+A and B both take away opportunities of each other, there is
+a &quot;negative&quot; ordering problem. If, on the other
+hand, both A and B introduce new optimization opportunities
+for each other, the problem is called &quot;positive&quot;.
+In the Global Optimizer the following interactions must be
+taken into account:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Inline Substitution (IL) may create new opportunities
+for most other techniques, so it should be run as early as
+possible</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Use Definition analysis (UD) may introduce opportunities
+for LV.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Strength Reduction may create opportunities for UD</p>
+</td>
+</table>
+
+<p>The optimizer has a default phase ordering, which can be
+changed by the user.</p>
+<a name="2.5. Structure of this document"></a>
+<h2>2.5. Structure of this document</h2>
+
+<p>The remaining chapters of this document each describe
+one phase of the optimizer. For every phase, we describe its
+task, its design, its implementation, and its source files.
+The latter two sections are intended to aid the maintenance
+of the optimizer and can be skipped by the initial
+reader.</p>
+<a name="2.6. References"></a>
+<h2>2.6. References</h2>
+
+<p>There are very few modern textbooks on optimization.
+Chapters 12, 13, and 14 of [Aho78a] are a good introduction
+to the subject. Wulf et. al. [Wulf75a] describe one specific
+optimizing (Bliss) compiler. Anklam et. al. [Ankl82a]
+discuss code generation and optimization in compilers for
+one specific machine (a Vax-11). Kirchgaesner et. al.
+[Kirc83a] present a brief description of many optimizations;
+the report also contains a lengthy (over 60 pages)
+bibliography.</p>
+
+<p>The number of articles on optimization is quite
+impressive. The Lowry and Medlock paper on the Fortran H
+compiler [Lowr69a] is a classical one. Other papers on
+global optimization are. [Faim80a, Perk79a, Harr79a,
+More79a, Mint79a] Freudenberger [Freu83a] describes an
+optimizer for a Very High Level Language (SETL). The
+Production-Quality Compiler-Compiler (PQCC) project uses
+very sophisticated compiler techniques, as described in.
+[Leve80a, Leve79a, Wulf80a]</p>
+
+<p>Several Ph.D. theses are dedicated to optimization.
+Davidson [Davi81a] outlines a machine-independent peephole
+optimizer that improves assembly code. Katkus [Katk73a]
+describes how efficient programs can be obtained at little
+cost by optimizing only a small part of a program.
+Photopoulos [Phot81a] discusses the idea of generating
+interpreted intermediate code as well as assembly code, to
+obtain programs that are both small and fast. Shaffer
+[Shaf78a] describes the theory of automatic subroutine
+generation. Leverett [Leve81a] deals with register
+allocation in the PQCC compilers.</p>
+
+<p>References to articles about specific optimization
+techniques will be given in later chapters.</p>
+<a name="3. The Intermediate Code and the IC phase"></a>
+<h2>3. The Intermediate Code and the IC phase</h2>
+
+<p>In this chapter the intermediate code of the EM global
+optimizer will be defined. The &rsquo;Intermediate Code
+construction&rsquo; phase (IC), which builds the initial
+intermediate code from EM Compact Assembly Language, will be
+described.</p>
+<a name="3.1. Introduction"></a>
+<h2>3.1. Introduction</h2>
+
+<p>The EM global optimizer is a multi pass program, hence
+there is a need for an intermediate code. Usually, programs
+in the Amsterdam Compiler Kit use the Compact Assembly
+Language format [Tane83a, section 11.2] for this purpose.
+Although this code has some convenient features, such as
+being compact, it is quite unsuitable in our case, because
+of a number of reasons. At first, the code lacks global
+information about whole procedures or whole basic blocks.
+Second, it uses identifiers (&rsquo;names&rsquo;) to bind
+defining and applied occurrences of procedures, data labels
+and instruction labels. Although this is usual in high level
+programming languages, it is awkward in an intermediate code
+that must be read many times. Each pass of the optimizer
+would have to incorporate an identifier look-up mechanism to
+associate a defining occurrence with each applied occurrence
+of an identifier. Finally, EM programs are used to declare
+blocks of bytes, rather than variables. A &rsquo;hol
+6&rsquo; instruction may be used to declare three 2-byte
+variables. Clearly, the optimizer wants to deal with
+variables, and not with rows of bytes.</p>
+
+<p>To overcome these problems, we have developed a new
+intermediate code. This code does not merely consist of the
+EM instructions, but also contains global information in the
+form of tables and graphs. Before describing the
+intermediate code we will first leap aside to outline the
+problems one generally encounters when trying to store
+complex data structures such as graphs outside the program,
+i.e. in a file. We trust this will enhance the
+comprehensibility of the intermediate code definition and
+the design and implementation of the IC phase.</p>
+<a name="3.2. Representation of complex data structures in a sequential file"></a>
+<h2>3.2. Representation of complex data structures in a sequential file</h2>
+
+<p>Most programmers are quite used to deal with complex
+data structures, such as arrays, graphs and trees. There are
+some particular problems that occur when storing such a data
+structure in a sequential file. We call data that is kept in
+main memory internal ,as opposed to external data that is
+kept in a file outside the program.</p>
+
+<p>We assume a simple data structure of a scalar type
+(integer, floating point number) has some known external
+representation. An array having elements of a scalar type
+can be represented externally easily, by successively
+representing its elements. The external representation may
+be preceded by a number, giving the length of the array.
+Now, consider a linear, singly linked list, the elements of
+which look like:</p>
+<pre>     record
+             data: scalar_type;
+             next: pointer_type;
+     end;
+</pre>
+
+<p>It is significant to note that the &quot;next&quot;
+fields of the elements only have a meaning within main
+memory. The field contains the address of some location in
+main memory. If a list element is written to a file in some
+program, and read by another program, the element will be
+allocated at a different address in main memory. Hence this
+address value is completely useless outside the program.</p>
+
+<p>One may represent the list by ignoring these
+&quot;next&quot; fields and storing the data items in the
+order they are linked. The &quot;next&quot; fields are
+represented <i>implicitly</i>. When the file is read again,
+the same list can be reconstructed. In order to know where
+the external representation of the list ends, it may be
+useful to put the length of the list in front of it.</p>
+
+<p>Note that arrays and linear lists have the same external
+representation.</p>
+
+<p>A doubly linked, linear list, with elements of the
+type:</p>
+<pre>     record
+             data: scalar_type;
+             next,
+             previous: pointer_type;
+     end
+</pre>
+
+<p>can be represented in precisely the same way. Both the
+&quot;next&quot; and the &quot;previous&quot; fields are
+represented implicitly.</p>
+
+<p>Next, consider a binary tree, the nodes of which have
+type:</p>
+<pre>     record
+             data: scalar_type;
+             left,
+             right: pointer_type;
+     end
+</pre>
+
+<p>Such a tree can be represented sequentially, by storing
+its nodes in some fixed order, e.g. prefix order. A special
+null data item may be used to denote a missing left or right
+son. For example, let the scalar type be integer, and let
+the null item be 0. Then the tree of fig. 3.1(a) can be
+represented as in fig. 3.1(b).</p>
+<pre>                             4
+                           /   \
+                         9      12
+                       /  \    /  \
+                     12    3   4   6
+                          / \  \  /
+                          8  1  5 1
+
+
+     Fig. 3.1(a) A binary tree
+
+
+
+
+     4 9 12 0 0 3 8 0 0 1 0 0 12 4 0 5 0 0 6 1 0 0 0
+
+
+     Fig. 3.1(b) Its sequential representation
+</pre>
+
+<p>We are still able to represent the pointer fields
+(&quot;left&quot; and &quot;right&quot;) implicitly.</p>
+
+<p>Finally, consider a general graph , where each node has
+a &quot;data&quot; field and pointer fields, with no
+restriction on where they may point to. Now we&rsquo;re at
+the end of our tale. There is no way to represent the
+pointers implicitly, like we did with lists and trees. In
+order to represent them explicitly, we use the following
+scheme. Every node gets an extra field, containing some
+unique number that identifies the node. We call this number
+its id. A pointer is represented externally as the id of the
+node it points to. When reading the file we use a table that
+maps an id to the address of its node. In general this table
+will not be completely filled in until we have read the
+entire external representation of the graph and allocated
+internal memory locations for every node. Hence we cannot
+reconstruct the graph in one scan. That is, there may be
+some pointers from node A to B, where B is placed after A in
+the sequential file than A. When we read the node of A we
+cannot map the id of B to the address of node B, as we have
+not yet allocated node B. We can overcome this problem if
+the size of every node is known in advance. In this case we
+can allocate memory for a node on first reference. Else, the
+mapping from id to pointer cannot be done while reading
+nodes. The mapping can be done either in an extra scan or at
+every reference to the node.</p>
+<a name="3.3. Definition of the intermediate code"></a>
+<h2>3.3. Definition of the intermediate code</h2>
+
+<p>The intermediate code of the optimizer consists of
+several components:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p>the object table</p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="38%">
+
+<p>the procedure table</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p>the em code</p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="46%">
+
+<p>the control flow graphs</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="28%">
+
+<p>the loop table</p>
+</td>
+<td width="61%">
+</td>
+</table>
+
+<p>These components are described in the next sections. The
+syntactic structure of every component is described by a set
+of context free syntax rules, with the following
+conventions:</p>
+
+<p align=center><img src="grohtml-102725.png"></p>
+<a name="3.3.1. The object table"></a>
+<h2>3.3.1. The object table</h2>
+
+<p>EM programs declare blocks of bytes rather than (global)
+variables. A typical program may declare &rsquo;HOL
+7780&rsquo; to allocate space for 8 I/O buffers, 2 large
+arrays and 10 scalar variables. The optimizer wants to deal
+with objects like variables, buffers and arrays and
+certainly not with huge numbers of bytes. Therefore the
+intermediate code contains information about which global
+objects are used. This information can be obtained from an
+EM program by just looking at the operands of instruction
+such as LOE, LAE, LDE, STE, SDE, INE, DEE and ZRE.</p>
+
+<p>The object table consists of a list of datablock
+entries. Each such entry represents a declaration like HOL,
+BSS, CON or ROM. There are five kinds of datablock entries.
+The fifth kind, UNKNOWN, denotes a declaration in a
+separately compiled file that is not made available to the
+optimizer. Each datablock entry contains the type of the
+block, its size, and a description of the objects that
+belong to it. If it is a rom, it also contains a list of
+values given as arguments to the rom instruction, provided
+that this list contains only integer numbers. An object has
+an offset (within its datablock) and a size. The size need
+not always be determinable. Both datablock and object
+contain a unique identifying number (see previous section
+for their use).</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-102726.png"></p>
+
+<p>A data block has only one flag: &quot;external&quot;,
+indicating whether the data label is externally visible. The
+syntax for &quot;argument&quot; will be given later on (see
+em_text).</p>
+<a name="3.3.2. The procedure table"></a>
+<h2>3.3.2. The procedure table</h2>
+
+<p>The procedure table contains global information about
+all procedures that are made available to the optimizer and
+that are needed by the EM program. (Library units may not be
+needed, see section 3.5). The table has one entry for every
+procedure.</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-102727.png"></p>
+
+<p>The number of bytes of formal parameters accessed by a
+procedure is determined by the front ends and passed via a
+message (parameter message) to the optimizer. If the front
+end is not able to determine this number (e.g. the parameter
+may be an array of dynamic size or the procedure may have a
+variable number of arguments) the attribute contains the
+value &rsquo;UNKNOWN_SIZE&rsquo;.<br>
+A procedure has the following flags:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>external: true if the proc. is externally visible</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>bodyseen: true if its code is available as EM text</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>calunknown: true if it calls a procedure that has its
+bodyseen flag not set</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>environ: true if it uses or changes a (non-global)
+variable in a lexically enclosing procedure</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>lpi: true if is used as operand of an lpi instruction,
+so it may be called indirect</p>
+</td>
+</table>
+
+<p>The change and use attributes both have one flag:
+&quot;indirect&quot;, indicating whether the procedure does
+a &rsquo;use indirect&rsquo; or a &rsquo;store
+indirect&rsquo; (indirect means through a pointer).</p>
+<a name="3.3.3. The EM text"></a>
+<h2>3.3.3. The EM text</h2>
+
+<p>The EM text contains the EM instructions. Every EM
+instruction has an operation code (opcode) and 0 or 1
+operands. EM pseudo instructions can have more than 1
+operand. The opcode is just a small (8 bit) integer.</p>
+
+<p>There are several kinds of operands, which we will refer
+to as types. Many EM instructions can have more than one
+type of operand. The types and their encodings in Compact
+Assembly Language are discussed extensively in. [Tane83a,
+section 11.2] Of special interest is the way numeric values
+are represented. Of prime importance is the machine
+independency of the representation. Ultimately, one could
+store every integer just as a string of the characters
+&rsquo;0&rsquo; to &rsquo;9&rsquo;. As doing arithmetic on
+strings is awkward, Compact Assembly Language allows several
+alternatives. The main idea is to look at the value of the
+integer. Integers that fit in 16, 32 or 64 bits are
+represented as a row of resp. 2, 4 and 8 bytes, preceded by
+an indication of how many bytes are used. Longer integers
+are represented as strings; this is only allowed within
+pseudo instructions, however. This concept works very well
+for target machines with reasonable word sizes. At present,
+most ACK software cannot be used for word sizes higher than
+32 bits, although the handles for using larger word sizes
+are present in the design of the EM code. In the
+intermediate code we essentially use the same ideas. We
+allow three representations of integers.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>integers that fit in a short are represented as a
+short</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>integers that fit in a long but not in a short are
+represented as longs</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>all remaining integers are represented as strings (only
+allowed in pseudos).</p>
+</td>
+</table>
+
+<p>The terms short and long are defined in [Ritc78a,
+section 4] and depend only on the source machine (i.e. the
+machine on which ACK runs), not on the target machines. For
+historical reasons a long will often be called an
+offset.</p>
+
+<p>Operands can also be instruction labels, objects or
+procedures. Instruction labels are denoted by a label
+identifier, which can be distinguished from a normal
+identifier.</p>
+
+<p>The operand of a pseudo instruction can be a list of
+arguments. Arguments can have the same type as operands,
+except for the type short, which is not used for arguments.
+Furthermore, an argument can be a string or a string
+representation of a signed integer, unsigned integer or
+floating point number. If the number of arguments is not
+fully determined by the pseudo instruction (e.g. a ROM
+pseudo can have any number of arguments), then the list is
+terminated by a special argument of type CEND.</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-102728.png"></p>
+<a name="3.3.4. The control flow graphs"></a>
+<h2>3.3.4. The control flow graphs</h2>
+
+<p>Each procedure can be divided into a number of basic
+blocks. A basic block is a piece of code with no jumps in,
+except at the beginning, and no jumps out, except at the
+end.</p>
+
+<p>Every basic block has a set of successors, which are
+basic blocks that can follow it immediately in the dynamic
+execution sequence. The predecessors are the basic blocks of
+which this one is a successor. The successor and predecessor
+attributes of all basic blocks of a single procedure are
+said to form the control flow graph of that procedure.</p>
+
+<p>Another important attribute is the immediate dominator.
+A basic block B dominates a block C if every path in the
+graph from the procedure entry block to C goes through B.
+The immediate dominator of C is the closest dominator of C
+on any path from the entry block. (Note that the dominator
+relation is transitive, so the immediate dominator is well
+defined.)</p>
+
+<p>A basic block also has an attribute containing the
+identifiers of every loop that the block belongs to (see
+next section for loops).</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-102729.png"></p>
+
+<p>The flag bits can have the values &rsquo;firm&rsquo; and
+&rsquo;strong&rsquo;, which are explained below.</p>
+<a name="3.3.5. The loop tables"></a>
+<h2>3.3.5. The loop tables</h2>
+
+<p>Every procedure has an associated loop table containing
+information about all the loops in the procedure. Loops can
+be detected by a close inspection of the control flow graph.
+The main idea is to look for two basic blocks, B and C, for
+which the following holds:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="42%">
+
+<p>B is a successor of C</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="42%">
+
+<p>B is a dominator of C</p>
+</td>
+<td width="47%">
+</td>
+</table>
+
+<p>B is called the loop entry and C is called the loop end.
+Intuitively, C contains a jump backwards to the beginning of
+the loop (B).</p>
+
+<p>A loop L1 is said to be nested within loop L2 if all
+basic blocks of L1 are also part of L2. It is important to
+note that loops could originally be written as a well
+structured for -or while loop or as a messy goto loop. Hence
+loops may partly overlap without one being nested inside the
+other. The nesting level of a loop is the number of loops in
+which it is nested (so it is 0 for an outermost loop). The
+details of loop detection will be discussed later.</p>
+
+<p>It is often desirable to know whether a basic block gets
+executed during every iteration of a loop. This leads to the
+following definitions:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A basic block B of a loop L is said to be a <i>firm</i>
+block of L if B is executed on all successive iterations of
+L, with the only possible exception of the last
+iteration.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A basic block B of a loop L is said to be a
+<i>strong</i> block of L if B is executed on all successive
+iterations of L.</p>
+</td>
+</table>
+
+<p>Note that a strong block is also a firm block. If a
+block is part of a conditional statement, it is neither
+strong nor firm, as it may be skipped during some iterations
+(see Fig. 3.2).</p>
+<pre>     loop
+            if cond1 then
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>... -- this code will not</p>
+<td width="19%"></td>
+<td width="10%">
+
+<p>-- result in a firm or strong block</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>end if;<br>
+... -- strong (always executed)<br>
+exit when cond2;<br>
+... -- firm (not executed on last iteration).<br>
+end loop;</p>
+
+<p>Fig. 3.2 Example of firm and strong block</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-1027210.png"></p>
+<a name="3.4. External representation of the intermediate code"></a>
+<h2>3.4. External representation of the intermediate code</h2>
+
+<p>The syntax of the intermediate code was given in the
+previous section. In this section we will make some remarks
+about the representation of the code in sequential
+files.</p>
+
+<p>We use sequential files in order to avoid the
+bookkeeping of complex file indices. As a consequence of
+this decision we can&rsquo;t store all components of the
+intermediate code in one file. If a phase wishes to change
+some attribute of a procedure, or wants to add or delete
+entire procedures (inline substitution may do the latter),
+the procedure table will only be fully updated after the
+entire EM text has been scanned. Yet, the next phase
+undoubtedly wants to read the procedure table before it
+starts working on the EM text. Hence there is an ordering
+problem, which can be solved easily by putting the procedure
+table in a separate file. Similarly, the data block table is
+kept in a file of its own.</p>
+
+<p>The control flow graphs (CFGs) could be mixed with the
+EM text. Rather, we have chosen to put them in a separate
+file too. The control flow graph file should be regarded as
+a file that imposes some structure on the EM-text file, just
+as an overhead sheet containing a picture of a Flow Chart
+may be put on an overhead sheet containing statements. The
+loop tables are also put in the CFG file. A loop imposes an
+extra structure on the CFGs and hence on the EM text. So
+there are four files:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p>the EM-text file</p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p>the procedure table file</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="42%">
+
+<p>the object table file</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p>the CFG and loop tables file</p>
+</td>
+<td width="33%">
+</td>
+</table>
+
+<p>Every table is preceded by its length, in order to tell
+where it ends. The CFG file also contains the number of
+instructions of every basic block, indicating which part of
+the EM text belongs to that block.</p>
+<pre>     syntax
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-1027211.png"></p>
+<a name="3.5. The Intermediate Code construction phase"></a>
+<h2>3.5. The Intermediate Code construction phase</h2>
+
+<p>The first phase of the global optimizer, called IC,
+constructs a major part of the intermediate code. To be
+specific, it produces:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p>the EM text</p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p>the object table</p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p>part of the procedure table</p>
+</td>
+<td width="35%">
+</td>
+</table>
+
+<p>The calling, change and use attributes of a procedure
+and all its flags except the external and bodyseen flags are
+computed by the next phase (Control Flow phase).</p>
+
+<p>As explained before, the intermediate code does not
+contain any names of variables or procedures. The normal
+identifiers are replaced by identifying numbers. Yet, the
+output of the global optimizer must contain normal
+identifiers, as this output is in Compact Assembly Language
+format. We certainly want all externally visible names to be
+the same in the input as in the output, because the
+optimized EM module may be a library unit, used by other
+modules. IC dumps the names of all procedures and data
+labels on two files:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the procedure dump file, containing tuples (P_ID,
+procedure name)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the data dump file, containing tuples (D_ID, data label
+name)</p>
+</td>
+</table>
+
+<p>The names of instruction labels are not dumped, as they
+are not visible outside the procedure in which they are
+defined.</p>
+
+<p>The input to IC consists of one or more files. Each file
+is either an EM module in Compact Assembly Language format,
+or a Unix archive file (library) containing such modules. IC
+only extracts those modules from a library that are needed
+somehow, just as a linker does. It is advisable to present
+as much code of the EM program as possible to the optimizer,
+although it is not required to present the whole program. If
+a procedure is called somewhere in the EM text, but its body
+(text) is not included in the input, its bodyseen flag in
+the procedure table will still be off. Whenever such a
+procedure is called, we assume the worst case for
+everything; it will change and use all variables it has
+access to, it will call every procedure etc.</p>
+
+<p>Similarly, if a data label is used but not defined, the
+PSEUDO attribute in its data block will be set to
+UNKNOWN.</p>
+<a name="3.5.1. Implementation"></a>
+<h2>3.5.1. Implementation</h2>
+
+<p>Part of the code for the EM Peephole Optimizer [b] has
+been used for IC. Especially the routines that read and
+unravel Compact Assembly Language and the identifier lookup
+mechanism have been used. New code was added to recognize
+objects, build the object and procedure tables and to output
+the intermediate code.</p>
+
+<p>IC uses singly linked linear lists for both the
+procedure and object table. Hence there are no limits on the
+size of such a table (except for the trivial fact that it
+must fit in main memory). Both tables are outputted after
+all EM code has been processed. IC reads the EM text of one
+entire procedure at a time, processes it and appends the
+modified code to the EM text file. EM code is represented
+internally as a doubly linked linear list of EM
+instructions.</p>
+
+<p>Objects are recognized by looking at the operands of
+instructions that reference global data. If we come across
+the instructions:</p>
+
+<p align=center><img src="grohtml-1027212.png"></p>
+
+<p>we conclude that the data block preceded by the data
+label X contains an object at offset 6 of size twice the
+word size, and an object at offset 20 of unknown size.</p>
+
+<p>A data block entry of the object table is allocated at
+the first reference to a data label. If this reference is a
+defining occurrence or a INA pseudo instruction, the label
+is not externally visible [Tane83a, section 11.1.4.3] In
+this case, the external flag of the data block is turned
+off. If the first reference is an applied occurrence or a
+EXA pseudo instruction, the flag is set. We record this
+information, because the optimizer may change the order of
+defining and applied occurrences. The INA and EXA pseudos
+are removed from the EM text. They may be regenerated by the
+last phase of the optimizer.</p>
+
+<p>Similar rules hold for the procedure table and the INP
+and EXP pseudos.</p>
+<a name="3.5.2. Source files of IC"></a>
+<h2>3.5.2. Source files of IC</h2>
+
+<p>The source files of IC consist of the files ic.c, ic.h
+and several packages. ic.h contains type definitions, macros
+and variable declarations that may be used by ic.c and by
+every package. ic.c contains the definitions of these
+variables, the procedure main and some high level I/O
+routines used by main.</p>
+
+<p>Every package xxx consists of two files. ic_xxx.h
+contains type definitions, macros, variable declarations and
+procedure declarations that may be used by every .c file
+that includes this .h file. The file ic_xxx.c provides the
+definitions of these variables and the implementation of the
+declared procedures. IC uses the following packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>lookup:</p>
+</td>
+<td width="22%"></td>
+<td width="64%">
+
+<p>procedures that loop up procedure, data label and
+instruction label names; procedures to dump the procedure
+and data label names.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>lib:</p>
+</td>
+<td width="28%"></td>
+<td width="64%">
+
+<p>one procedure that gets the next useful input module;
+while scanning archives, it skips unnecessary modules.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>aux:</p>
+</td>
+<td width="28%"></td>
+<td width="54%">
+
+<p>several auxiliary routines.</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>io:</p>
+</td>
+<td width="30%"></td>
+<td width="64%">
+
+<p>low-level I/O routines that unravel the Compact Assembly
+Language.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>put:</p>
+</td>
+<td width="28%"></td>
+<td width="64%">
+
+<p>routines that output the intermediate code</p>
+</td>
+</table>
+<a name="4. The Control Flow Phase"></a>
+<h2>4. The Control Flow Phase</h2>
+
+<p>In the previous chapter we described the intermediate
+code of the global optimizer. We also specified which part
+of this code was constructed by the IC phase of the
+optimizer. The Control Flow Phase (<i>CF</i>) does the
+remainder of the job, i.e. it determines:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="46%">
+
+<p>the control flow graphs</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>the loop tables</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the calling, change and use attributes of the procedure
+table entries</p>
+</td>
+</table>
+
+<p>CF operates on one procedure at a time. For every
+procedure it first reads the EM instructions from the
+EM-text file and groups them into basic blocks. For every
+basic block, its successors and predecessors are determined,
+resulting in the control flow graph. Next, the immediate
+dominator of every basic block is computed. Using these
+dominators, any loop in the procedure is detected. Finally,
+interprocedural analysis is done, after which we will know
+the global effects of every procedure call on its
+environment.</p>
+
+<p>CF uses the same internal data structures for the
+procedure table and object table as IC.</p>
+<a name="4.1. Partitioning into basic blocks"></a>
+<h2>4.1. Partitioning into basic blocks</h2>
+
+<p>With regard to flow of control, we distinguish three
+kinds of EM instructions: jump instructions, instruction
+label definitions and normal instructions. Jump instructions
+are all conditional or unconditional branch instructions,
+the case instructions (CSA/CSB) and the RET (return)
+instruction. A procedure call (CAL) is not considered to be
+a jump. A defining occurrence of an instruction label is
+regarded as an EM instruction.</p>
+
+<p>An instruction starts a new basic block, in any of the
+following cases:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>It is the first instruction of a procedure</p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>It is the first of a list of instruction label defining
+occurrences</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p>It follows a jump</p>
+</td>
+<td width="55%">
+</td>
+</table>
+
+<p>If there are several consecutive instruction labels
+(which is highly unusual), all of them are put in the same
+basic block. Note that several cases may overlap, e.g. a
+label definition at the beginning of a procedure or a label
+following a jump.</p>
+
+<p>A simple Finite State Machine is used to model the above
+rules. It also recognizes the end of a procedure, marked by
+an END pseudo. The basic blocks are stored internally as a
+doubly linked linear list. The blocks are linked in textual
+order. Every node of this list has the attributes described
+in the previous chapter (see syntax rule for basic_block).
+Furthermore, every node contains a pointer to its EM
+instructions, which are represented internally as a linear,
+doubly linked list, just as in the IC phase. However,
+instead of one list per procedure (as in IC) there is now
+one list per basic block.</p>
+
+<p>On the fly, a table is build that maps every label
+identifier to the label definition instruction. This table
+is used for computing the control flow. The table is stored
+as a dynamically allocated array. The length of the array is
+the number of labels of the current procedure; this value
+can be found in the procedure table, where it was stored by
+IC.</p>
+<a name="4.2. Control Flow"></a>
+<h2>4.2. Control Flow</h2>
+
+<p>A <i>successor</i> of a basic block B is a block C that
+can be executed immediately after B. C is said to be a
+<i>predecessor</i> of B. A block ending with a RET
+instruction has no successors. Such a block is called a
+<i>return block</i>. Any block that has no predecessors
+cannot be executed at all (i.e. it is unreachable), unless
+it is the first block of a procedure, called the
+<i>procedure entry block</i>.</p>
+
+<p>Internally, the successor and predecessor attributes of
+a basic block are stored as <i>sets</i>. Alternatively, one
+may regard all these sets of all basic blocks as a
+conceptual <i>graph</i>, in which there is an edge from B to
+C if C is in the successor set of B. We call this conceptual
+graph the <i>Control Flow Graph</i>.</p>
+
+<p>The only successor of a basic block ending on an
+unconditional branch instruction is the block that contains
+the label definition of the target of the jump. The target
+instruction can be found via the LAB_ID that is the operand
+of the jump instruction, by using the label-map table
+mentioned above. If the last instruction of a block is a
+conditional jump, the successors are the target block and
+the textually next block. The last instruction can also be a
+case jump instruction (CSA or CSB). We then analyze the case
+descriptor, to find all possible target instructions and
+their associated blocks. We require the case descriptor to
+be allocated in a ROM, so it cannot be changed dynamically.
+A case jump via an alterable descriptor could in principle
+go to any label in the program. In the presence of such an
+uncontrolled jump, hardly any optimization can be done. We
+do not expect any front end to generate such a descriptor,
+however, because of the controlled nature of case statements
+in high level languages. If the basic block does not end in
+a jump instruction, its only successor is the textually next
+block.</p>
+<a name="4.3. Immediate dominators"></a>
+<h2>4.3. Immediate dominators</h2>
+
+<p>A basic block B dominates a block C if every path in the
+control flow graph from the procedure entry block to C goes
+through B. The immediate dominator of C is the closest
+dominator of C on any path from the entry block. See also
+[Aho78a, section 13.1.]</p>
+
+<p>There are a number of algorithms to compute the
+immediate dominator relation.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Purdom and Moore give an algorithm that is easy to
+program and easy to describe (although the description they
+give is unreadable; it is given in a very messy Algol60
+program full of gotos). [Purd72a]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Aho and Ullman present a bitvector algorithm, which is
+also easy to program and to understand. (See [Aho78a,
+section 13.1.]).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>3</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Lengauer and Tarjan introduce a fast algorithm that is
+hard to understand, yet remarkably easy to implement.
+[Leng79a]</p>
+</td>
+</table>
+
+<p>The Purdom-Moore algorithm is very slow if the number of
+basic blocks in the flow graph is large. The Aho-Ullman
+algorithm in fact computes the dominator relation, from
+which the immediate dominator relation can be computed in
+time quadratic to the number of basic blocks, worst case.
+The storage requirement is also quadratic to the number of
+blocks. The running time of the third algorithm is
+proportional to:</p>
+<pre>     (number of edges in the graph) * log(number of blocks).
+</pre>
+
+<p>We have chosen this algorithm because it is fast (as
+shown by experiments done by Lengauer and Tarjan), it is
+easy to program and requires little data space.</p>
+<a name="4.4. Loop detection"></a>
+<h2>4.4. Loop detection</h2>
+
+<p>Loops are detected by using the loop construction
+algorithm of. [Aho78a, section 13.1.] This algorithm uses
+<i>back edges</i>. A back edge is an edge from B to C in the
+CFG, whose head (C) dominates its tail (B). The loop
+associated with this back edge consists of C plus all nodes
+in the CFG that can reach B without going through C.</p>
+
+<p>As an example of how the algorithm works, consider the
+piece of program of Fig. 4.1. First just look at the program
+and try to see what part of the code constitutes the
+loop.</p>
+<pre>     loop
+        if cond then                       1
+           -- lots of simple
+           -- assignment
+           -- statements              2          3
+           exit; -- exit loop
+        else
+           S; -- one statement
+        end if;
+     end loop;
+
+
+     Fig. 4.1 A misleading loop
+</pre>
+
+<p>Although a human being may be easily deceived by the
+brackets &quot;loop&quot; and &quot;end loop&quot;, the loop
+detection algorithm will correctly reply that only the test
+for &quot;cond&quot; and the single statement in the
+false-part of the if statement are part of the loop! The
+statements in the true-part only get executed once, so there
+really is no reason at all to say they&rsquo;re part of the
+loop too. The CFG contains one back edge,
+&quot;3-&gt;1&quot;. As node 3 cannot be reached from node
+2, the latter node is not part of the loop.</p>
+
+<p>A source of problems with the algorithm is the fact that
+different back edges may result in the same loop. Such an
+ill-structured loop is called a <i>messy</i> loop. After a
+loop has been constructed, it is checked if it is really a
+new loop.</p>
+
+<p>Loops can partly overlap, without one being nested
+inside the other. This is the case in the program of Fig.
+4.2.</p>
+<pre>     1:                              1
+        S1;
+     2:
+        S2;                          2
+        if cond then
+           goto 4;
+        S3;                     3         4
+        goto 1;
+     4:
+        S4;
+        goto 1;
+
+
+     Fig. 4.2 Partly overlapping loops
+</pre>
+
+<p>There are two back edges &quot;3-&gt;1&quot; and
+&quot;4-&gt;1&quot;, resulting in the loops {1,2,3} and
+{1,2,4}. With every basic block we associate a set of all
+loops it is part of. It is not sufficient just to record its
+most enclosing loop.</p>
+
+<p>After all loops of a procedure are detected, we
+determine the nesting level of every loop. Finally, we find
+all strong and firm blocks of the loop. If the loop has only
+one back edge (i.e. it is not messy), the set of firm blocks
+consists of the head of this back edge and its dominators in
+the loop (including the loop entry block). A firm block is
+also strong if it is not a successor of a block that may
+exit the loop; a block may exit a loop if it has an
+(immediate) successor that is not part of the loop. For
+messy loops we do not determine the strong and firm blocks.
+These loops are expected to occur very rarely.</p>
+<a name="4.5. Interprocedural analysis"></a>
+<h2>4.5. Interprocedural analysis</h2>
+
+<p>It is often desirable to know the effects a procedure
+call may have. The optimization below is only possible if we
+know for sure that the call to P cannot change A.</p>
+
+<p align=center><img src="grohtml-1027213.png"></p>
+
+<p>Although it is not possible to predict exactly all the
+effects a procedure call has, we may determine a kind of
+upper bound for it. So we compute all variables that may be
+changed by P, although they need not be changed at every
+invocation of P. We can get hold of this set by just looking
+at all assignment (store) instructions in the body of P. EM
+also has a set of <i>indirect</i> assignment instructions,
+i.e. assignment through a pointer variable. In general, it
+is not possible to determine which variable is affected by
+such an assignment. In these cases, we just record the fact
+that P does an indirect assignment. Note that this does not
+mean that all variables are potentially affected, as the
+front ends may generate messages telling that certain
+variables can never be accessed indirectly. We also set a
+flag if P does a use (load) indirect. Note that we only have
+to look at <i>global</i> variables. If P changes or uses any
+of its locals, this has no effect on its environment. Local
+variables of a lexically enclosing procedure can only be
+accessed indirectly.</p>
+
+<p>A procedure P may of course call another procedure. To
+determine the effects of a call to P, we also must know the
+effects of a call to the second procedure. This second one
+may call a third one, and so on. Effectively, we need to
+compute the <i>transitive closure</i> of the effects. To do
+this, we determine for every procedure which other
+procedures it calls. This set is the &quot;calling&quot;
+attribute of a procedure. One may regard all these sets as a
+conceptual graph, in which there is an edge from P to Q if Q
+is in the calling set of P. This graph will be referred to
+as the <i>call graph</i>. (Note the resemblance with the
+control flow graph).</p>
+
+<p>We can detect which procedures are called by P by
+looking at all CAL instructions in its body. Unfortunately,
+a procedure may also be called indirectly, via a CAI
+instruction. Yet, only procedures that are used as operand
+of an LPI instruction can be called indirect, because this
+is the only way to take the address of a procedure. We
+determine for every procedure whether it does a CAI
+instruction. We also build a set of all procedures used as
+operand of an LPI.</p>
+
+<p>After all procedures have been processed (i.e. all CFGs
+are constructed, all loops are detected, all procedures are
+analyzed to see which variables they may change, which
+procedures they call, whether they do a CAI or are used in
+an LPI) the transitive closure of all interprocedural
+information is computed. During the same process, the
+calling set of every procedure that uses a CAI is extended
+with the above mentioned set of all procedures that can be
+called indirect.</p>
+<a name="4.6. Source files"></a>
+<h2>4.6. Source files</h2>
+
+<p>The sources of CF are in the following files and
+packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>cf.h:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>cf.c:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>the routine main; interprocedural analysis; transitive
+closure</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>succ:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>control flow (successor and predecessor)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>idom:</p>
+</td>
+<td width="18%"></td>
+<td width="40%">
+
+<p>immediate dominators</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>loop:</p>
+</td>
+<td width="18%"></td>
+<td width="28%">
+
+<p>loop detection</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>get:</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>read object and procedure table; read EM text and
+partition it into basic blocks</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>put:</p>
+</td>
+<td width="20%"></td>
+<td width="60%">
+
+<p>write tables, CFGs and EM text</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<a name="5. Inline substitution"></a>
+<h2>5. Inline substitution</h2>
+<a name="5.1. Introduction"></a>
+<h2>5.1. Introduction</h2>
+
+<p>The Inline Substitution technique (IL) tries to decrease
+the overhead associated with procedure calls (invocations).
+During a procedure call, several actions must be undertaken
+to set up the right environment for the called procedure.
+[John81a] On return from the procedure, most of these
+effects must be undone. This entire process introduces
+significant costs in execution time as well as in object
+code size.</p>
+
+<p>The inline substitution technique replaces some of the
+calls by the modified body of the called procedure, hence
+eliminating the overhead. Furthermore, as the calling and
+called procedure are now integrated, they can be optimized
+together, using other techniques of the optimizer. This
+often leads to extra opportunities for optimization
+[Ball79a, Cart77a, Sche77a]</p>
+
+<p>An inline substitution of a call to a procedure P
+increases the size of the program, unless P is very small or
+P is called only once. In the latter case, P can be
+eliminated. In practice, procedures that are called only
+once occur quite frequently, due to the introduction of
+structured programming. (Carter [Cart82a] states that almost
+50% of the Pascal procedures he analyzed were called just
+once).</p>
+
+<p>Scheifler [Sche77a] has a more general view of inline
+substitution. In his model, the program under consideration
+is allowed to grow by a certain amount, i.e. code size is
+sacrificed to speed up the program. The above two cases are
+just special cases of his model, obtained by setting the
+size-change to (approximately) zero. He formulates the
+substitution problem as follows:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>&quot;Given a program, a subset of all invocations, a
+maximum program size, and a maximum procedure size, find a
+sequence of substitutions that minimizes the expected
+execution time.&quot;</p>
+</td>
+</table>
+
+<p>Scheifler shows that this problem is NP-complete
+[Aho74a, chapter 10] by reduction to the Knapsack Problem.
+Heuristics will have to be used to find a near-optimal
+solution.</p>
+
+<p>In the following chapters we will extend
+Scheifler&rsquo;s view and adapt it to the EM Global
+Optimizer. We will first describe the transformations that
+have to be applied to the EM text when a call is substituted
+in line. Next we will examine in which cases inline
+substitution is not possible or desirable. Heuristics will
+be developed for chosing a good sequence of substitutions.
+These heuristics make no demand on the user (such as making
+profiles [Sche77a] or giving pragmats [Ichb83a, section
+6.3.2]), although the model could easily be extended to use
+such information. Finally, we will discuss the
+implementation of the IL phase of the optimizer.</p>
+
+<p>We will often use the term inline expansion as a synonym
+of inline substitution.<br>
+The inverse technique of procedure abstraction (automatic
+subroutine generation) [Shaf78a] will not be discussed in
+this report.</p>
+<a name="5.2. Parameters and local variables."></a>
+<h2>5.2. Parameters and local variables.</h2>
+
+<p>In the EM calling sequence, the calling procedure pushes
+its parameters on the stack before doing the CAL. The called
+routine first saves some status information on the stack and
+then allocates space for its own locals (also on the stack).
+Usually, one special purpose register, the Local Base (LB)
+register, is used to access both the locals and the
+parameters. If memory is highly segmented, the stack frames
+of the caller and the callee may be allocated in different
+fragments; an extra Argument Base (AB) register is used in
+this case to access the actual parameters. See 4.2 of
+[Tane83a] for further details.</p>
+
+<p>If a procedure call is expanded in line, there are two
+problems:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>No stack frame will be allocated for the called
+procedure; we must find another place to put its locals.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The LB register cannot be used to access the actual
+parameters; as the CAL instruction is deleted, the LB will
+still point to the local base of the <i>calling</i>
+procedure.</p>
+</td>
+</table>
+
+<p>The local variables of the called procedure will be put
+in the stack frame of the calling procedure, just after its
+own locals. The size of the stack frame of the calling
+procedure will be increased during its entire lifetime.
+Therefore our model will allow a limit to be set on the
+number of bytes for locals that the called procedure may
+have (see next section).</p>
+
+<p>There are several alternatives to access the parameters.
+An actual parameter may be any auxiliary expression, which
+we will refer to as the <i>actual parameter expression</i>.
+The value of this expression is stored in a location on the
+stack (see above), the <i>parameter location</i>.<br>
+The alternatives for accessing parameters are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>save the value of the stackpointer at the point of the
+CAL in a temporary variable X; this variable can be used to
+simulate the AB register, i.e. parameter locations are
+accessed via an offset to the value of X.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>create a new temporary local variable T for the
+parameter (in the stack frame of the caller); every access
+to the parameter location must be changed into an access to
+T.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>do not evaluate the actual parameter expression before
+the call; instead, substitute this expression for every use
+of the parameter location.</p>
+</td>
+</table>
+
+<p>The first method may be expensive if X is not put in a
+register. We will not use this method. The time required to
+evaluate and access the parameters when the second method is
+used will not differ much from the normal calling sequence
+(i.e. not in line call). It is not expensive, but there are
+no extra savings either. The third method is essentially the
+&rsquo;by name&rsquo; parameter mechanism of Algol60. If the
+actual parameter is just a numeric constant, it is
+advantageous to use it. Yet, there are several circumstances
+under which it cannot or should not be used. We will deal
+with this in the next section.<br>
+In general we will use the third method, if it is possible
+and desirable. Such parameters will be called <i>in line
+parameters</i>. In all other cases we will use the second
+method.</p>
+<a name="5.3. Feasibility and desirability analysis"></a>
+<h2>5.3. Feasibility and desirability analysis</h2>
+
+<p>Feasibility and desirability analysis of in line
+substitution differ somewhat from most other techniques.
+Usually, much effort is needed to find a feasible
+opportunity for optimization (e.g. a redundant
+subexpression). Desirability analysis then checks if it is
+really advantageous to do the optimization. For IL,
+opportunities are easy to find. To see if an in line
+expansion is desirable will not be hard either. Yet, the
+main problem is to find the most desirable ones. We will
+deal with this problem later and we will first attend
+feasibility and desirability analysis.</p>
+
+<p>There are several reasons why a procedure invocation
+cannot or should not be expanded in line.</p>
+
+<p>A call to a procedure P cannot be expanded in line in
+any of the following cases:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The body of P is not available as EM text. Clearly,
+there is no way to do the substitution.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P, or any procedure called by P (transitively), follows
+the chain of statically enclosing procedures (via a LXL or
+LXA instruction) or follows the chain of dynamically
+enclosing procedures (via a DCH). If the call were expanded
+in line, one level would be removed from the chains, leading
+to total chaos. This chaos could be solved by patching up
+every LXL, LXA or DCH in all procedures that could be part
+of the chains, but this is hard to implement.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P, or any procedure called by P (transitively), calls a
+procedure whose body is not available as EM text. The
+unknown procedure may use an LXL, LXA or DCH. However, in
+several languages a separately compiled procedure has no
+access to the static or dynamic chain. In this case this
+point does not apply.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P, or any procedure called by P (transitively), uses the
+LPB instruction, which converts a local base to an argument
+base; as the locals and parameters are stored in a
+non-standard way (differing from the normal EM calling
+sequence) this instruction would yield incorrect
+results.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The total number of bytes of the parameters of P is not
+known. P may be a procedure with a variable number of
+parameters or may have an array of dynamic size as value
+parameter.</p>
+</td>
+</table>
+
+<p>It is undesirable to expand a call to a procedure P in
+line in any of the following cases:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P is large, i.e. the number of EM instructions of P
+exceeds some threshold. The expanded code would be large
+too. Furthermore, several programs in ACK, including the
+global optimizer itself, may run out of memory if they they
+have to run in a small address space and are provided very
+large procedures. The threshold may be set to infinite, in
+which case this point does not apply.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P has many local variables. All these variables would
+have to be allocated in the stack frame of the calling
+procedure.</p>
+</td>
+</table>
+
+<p>If a call may be expanded in line, we have to decide how
+to access its parameters. In the previous section we stated
+that we would use in line parameters whenever possible and
+desirable. There are several reasons why a parameter cannot
+or should not be expanded in line.</p>
+
+<p>No parameter of a procedure P can be expanded in line,
+in any of the following cases:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P, or any procedure called by P (transitively), does a
+store-indirect or a use-indirect (i.e. through a pointer).
+However, if the front-end has generated messages telling
+that certain parameters can not be accessed indirectly,
+those parameters may be expanded in line.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P, or any procedure called by P (transitively), calls a
+procedure whose body is not available as EM text. The
+unknown procedure may do a store-indirect or a use-indirect.
+However, the same remark about front-end messages as for 1.
+holds here.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The address of a parameter location is taken (via a
+LAL). In the normal calling sequence, all parameters are
+stored sequentially. If the address of one parameter
+location is taken, the address of any other parameter
+location can be computed from it. Hence we must put every
+parameter in a temporary location; furthermore, all these
+locations must be in the same order as for the normal
+calling sequence.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P has overlapping parameters; for example, it uses the
+parameter at offset 10 both as a 2 byte and as a 4 byte
+parameter. Such code may be produced by the front ends if
+the formal parameter is of some record type with
+variants.</p>
+</td>
+</table>
+
+<p>Sometimes a specific parameter must not be expanded in
+line.<br>
+An actual parameter expression cannot be expanded in line in
+any of the following cases:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P stores into the parameter location. Even if the actual
+parameter expression is a simple variable, it is incorrect
+to change the &rsquo;store into formal&rsquo; into a
+&rsquo;store into actual&rsquo;, because of the parameter
+mechanism used. In Pascal, the following expansion is
+incorrect:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<pre>     procedure p (x:integer);
+     begin
+        x := 20;
+     end;
+     ...
+     a := 10;                a := 10;
+     p(a);        ---&gt;       a := 20;
+     write(a);               write(a);
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>P changes any of the operands of the actual parameter
+expression. If the expression is expanded and evaluated
+after the operand has been changed, the wrong value will be
+used.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The actual parameter expression has side effects. It
+must be evaluated only once, at the place of the call.</p>
+</td>
+</table>
+
+<p>It is undesirable to expand an actual parameter in line
+in the following case:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="2%"></td>
+<td width="94%">
+
+<p>The parameter is used more than once (dynamically) and
+the actual parameter expression is not just a simple
+variable or constant.</p>
+</td>
+</table>
+<a name="5.4. Heuristic rules"></a>
+<h2>5.4. Heuristic rules</h2>
+
+<p>Using the information described in the previous section,
+we can find all calls that can be expanded in line, and for
+which this expansion is desirable. In general, we cannot
+expand all these calls, so we have to choose the
+&rsquo;best&rsquo; ones. With every CAL instruction that may
+be expanded, we associate a <i>pay off</i>, which expresses
+how desirable it is to expand this specific CAL.</p>
+
+<p>Let Tc denote the portion of EM text involved in a
+specific call, i.e. the pushing of the actual parameter
+expressions, the CAL itself, the popping of the parameters
+and the pushing of the result (if any, via an LFR). Let Te
+denote the EM text that would be obtained by expanding the
+call in line. Let Pc be the original program and Pe the
+program with Te substituted for Tc. The pay off of the CAL
+depends on two factors:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p>T = execution_time(Pe) - execution_time(Pc)</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="66%">
+
+<p>S = code_size(Pe) - code_size(Pc)</p>
+</td>
+<td width="23%">
+</td>
+</table>
+
+<p>The change in execution time (T) depends on:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>T1 = execution_time(Te) - execution_time(Tc)</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="84%">
+
+<p>N = number of times Te or Tc get executed.</p>
+</td>
+<td width="5%">
+</td>
+</table>
+
+<p>We assume that T1 will be the same every time the code
+gets executed. This is a reasonable assumption. (Note that
+we are talking about one CAL, not about different calls to
+the same procedure). Hence</p>
+<pre>     T = N * T1
+</pre>
+
+<p>T1 can be estimated by a careful analysis of the
+transformations that are performed. Below, we list
+everything that will be different when a call is expanded in
+line:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The CAL instruction is not executed. This saves a
+subroutine jump.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The instructions in the procedure prolog are not
+executed. These instructions, generated from the PRO pseudo,
+save some machine registers (including the old LB), set the
+new LB and allocate space for the locals of the called
+routine. The savings may be less if there are no locals to
+allocate.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>In line parameters are not evaluated before the call and
+are not pushed on the stack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>All remaining parameters are stored in local variables,
+instead of being pushed on the stack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>If the number of parameters is nonzero, the ASP
+instruction after the CAL is not executed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Every reference to an in line parameter is substituted
+by the parameter expression.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>RET (return) instructions are replaced by BRA (branch)
+instructions. If the called procedure &rsquo;falls
+through&rsquo; (i.e. it has only one RET, at the end of its
+code), even the BRA is not needed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The LFR (fetch function result) is not executed</p>
+</td>
+</table>
+
+<p>Besides these changes, which are caused directly by IL,
+other changes may occur as IL influences other optimization
+techniques, such as Register Allocation and Constant
+Propagation. Our heuristic rules do not take into account
+the quite inpredictable effects on Register Allocation. It
+does, however, favour calls that have numeric
+<i>constants</i> as parameter; especially the constant
+&quot;0&quot; as an inline parameter gets high scores, as
+further optimizations may often be possible.</p>
+
+<p>It cannot be determined statically how often a CAL
+instruction gets executed. We will use <i>loop nesting</i>
+information here. The nesting level of the loop in which the
+CAL appears (if any) will be used as an indication for the
+number of times it gets executed.</p>
+
+<p>Based on all these facts, the pay off of a call will be
+computed. The following model was developed empirically.
+Assume procedure P calls procedure Q. The call takes place
+in basic block B.</p>
+
+<p align=center><img src="grohtml-1027214.png"></p>
+
+<p>S stands for the size increase of the program, which is
+slightly less than the size of Q. The size of a procedure is
+taken to be its number of (non-pseudo) EM instructions. The
+terms &quot;loop nesting level&quot; and &quot;firm&quot;
+were defined in the chapter on the Intermediate Code
+(section &quot;loop tables&quot;). If a call is not inside a
+loop and the calling procedure is itself never called from a
+loop (transitively), then the call will probably be executed
+at most once. Such a call is never expanded in line (its pay
+off is zero). If the calling procedure doesn&rsquo;t have
+local variables, a penalty (L) is introduced, as it will
+most likely get local variables if the call gets
+expanded.</p>
+<a name="5.5. Implementation"></a>
+<h2>5.5. Implementation</h2>
+
+<p>A major factor in the implementation of Inline
+Substitution is the requirement not to use an excessive
+amount of memory. IL essentially analyzes the entire
+program; it makes decisions based on which procedure calls
+appear in the whole program. Yet, because of the memory
+restriction, it is not feasible to read the entire program
+in main memory. To solve this problem, the IL phase has been
+split up into three subphases that are executed
+sequentially:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>analyze every procedure; see how it accesses its
+parameters; simultaneously collect all calls appearing in
+the whole program an put them in a <i>call-list</i>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>use the call-list and decide which calls will be
+substituted in line.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>take the decisions of subphase 2 and modify the program
+accordingly.</p>
+</td>
+</table>
+
+<p>Subphases 1 and 3 scan the input program; only subphase
+3 modifies it. It is essential that the decisions can be
+made in subphase 2 without using the input program, provided
+that subphase 1 puts enough information in the call-list.
+Subphase 2 keeps the entire call-list in main memory and
+repeatedly scans it, to find the next best candidate for
+expansion.</p>
+
+<p>We will specify the data structures used by IL before
+describing the subphases.</p>
+<a name="5.5.1. Data structures"></a>
+<h2>5.5.1. Data structures</h2>
+<a name="5.5.1.1. The procedure table"></a>
+<h2>5.5.1.1. The procedure table</h2>
+
+<p>In subphase 1 information is gathered about every
+procedure and added to the procedure table. This information
+is used by the heuristic rules. A proctable entry for
+procedure p has the following extra information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>is it allowed to substitute an invocation of p in
+line?</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>is it allowed to put any parameter of such a call in
+line?</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p>the size of p (number of EM instructions)</p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="44%">
+
+<p>does p &rsquo;fall through&rsquo;?</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>a description of the formal parameters that p accesses;
+this information is obtained by looking at the code of p.
+For every parameter f, we record:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>the offset of f</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>the type of f (word, double word, pointer)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>may the corresponding actual parameter be put in
+line?</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p>is f ever accessed indirectly?</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>if f used: never, once or more than once?</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p>the number of times p is called (see below)</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the file address of its call-count information (see
+below).</p>
+</td>
+</table>
+<a name="5.5.1.2. Call-count information"></a>
+<h2>5.5.1.2. Call-count information</h2>
+
+<p>As a result of Inline Substitution, some procedures may
+become useless, because all their invocations have been
+substituted in line. One of the tasks of IL is to keep track
+which procedures are no longer called. Note that IL is
+especially keen on procedures that are called only once
+(possibly as a result of expanding all other calls to it).
+So we want to know how many times a procedure is called
+<i>during</i> Inline Substitution. It is not good enough to
+compute this information afterwards. The task is rather
+complex, because the number of times a procedure is called
+varies during the entire process:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>If a call to p is substituted in line, the number of
+calls to p gets decremented by 1.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>If a call to p is substituted in line, and p contains n
+calls to q, then the number of calls to q gets incremented
+by n.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>If a procedure p is removed (because it is no longer
+called) and p contains n calls to q, then the number of
+calls to q gets decremented by n.</p>
+</td>
+</table>
+
+<p>(Note that p may be the same as q, if p is
+recursive).<br>
+So we actually want to have the following information:</p>
+<pre>     NRCALL(p,q) = number of call to q appearing in p,
+
+
+     for all procedures p and q that may be put in line.
+</pre>
+
+<p>This information, called <i>call-count information</i>
+is computed by the first subphase. It is stored in a file.
+It is represented as a number of lists, rather than as a
+(very sparse) matrix. Every procedure has a list of
+(proc,count) pairs, telling which procedures it calls, and
+how many times. The file address of its call-count list is
+stored in its proctable entry. Whenever this information is
+needed, it is fetched from the file, using direct access.
+The proctable entry also contains the number of times a
+procedure is called, at any moment.</p>
+<a name="5.5.1.3. The call-list"></a>
+<h2>5.5.1.3. The call-list</h2>
+
+<p>The call-list is the major data structure use by IL.
+Every item of the list describes one procedure call. It
+contains the following attributes:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p>the calling procedure (caller)</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="58%">
+
+<p>the called procedure (callee)</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>identification of the CAL instruction (sequence
+number)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the loop nesting level; our heuristic rules appreciate
+calls inside a loop (or even inside a loop nested inside
+another loop, etc.) more than other calls</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the actual parameter expressions involved in the call;
+for every actual, we record:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="58%">
+
+<p>the EM code of the expression</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>the number of bytes of its result (size)</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>an indication if the actual may be put in line</p>
+</td>
+</table>
+
+<p>The structure of the call-list is rather complex.
+Whenever a call is expanded in line, new calls will suddenly
+appear in the program, that were not contained in the
+original body of the calling subroutine. These calls are
+inherited from the called procedure. We will refer to these
+invocations as <i>nested calls</i> (see Fig. 5.1).</p>
+
+<p align=center><img src="grohtml-1027215.png"></p>
+
+<p align=center><img src="grohtml-1027216.png"></p>
+
+<p>Fig. 5.1 Example of nested procedure calls</p>
+
+<p>Nested calls may subsequently be put in line too
+(probably resulting in a yet deeper nesting level, etc.). So
+the call-list does not always reflect the source program,
+but changes dynamically, as decisions are made. If a call to
+p is expanded, all calls appearing in p will be added to the
+call-list.<br>
+A convenient and elegant way to represent the call-list is
+to use a LISP-like list. [Poel72a] Calls that appear at the
+same level are linked in the CDR direction. If a call C to a
+procedure p is expanded, all calls appearing in p are put in
+a sub-list of C, i.e. in its CAR. In the example above,
+before the decision to expand the call to p is made, the
+call-list of procedure r looks like:</p>
+<pre>     (call-to-x, call-to-p, call-to-y)
+</pre>
+
+<p>After the decision, it looks like:</p>
+<pre>     (call-to-x, (call-to-p*, call-to-a, call-to-b), call-to-y)
+</pre>
+
+<p>The call to p is marked, because it has been
+substituted. Whenever IL wants to traverse the call-list of
+some procedure, it uses the well-known LISP technique of
+recursion in the CAR direction and iteration in the CDR
+direction (see page 1.19-2 of [Poel72a] ). All list
+traversals look like:</p>
+<pre>     traverse(list)
+     {
+         for (c = first(list); c != 0; c = CDR(c)) {
+             if (c is marked) {
+                 traverse(CAR(c));
+             } else {
+                 do something with c
+             }
+         }
+     }
+</pre>
+
+<p>The entire call-list consists of a number of LISP-like
+lists, one for every procedure. The proctable entry of a
+procedure contains a pointer to the beginning of the
+list.</p>
+<a name="5.5.2. The first subphase: procedure analysis"></a>
+<h2>5.5.2. The first subphase: procedure analysis</h2>
+
+<p>The tasks of the first subphase are to determine several
+attributes of every procedure and to construct the basic
+call-list, i.e. without nested calls. The size of a
+procedure is determined by simply counting its EM
+instructions. Pseudo instructions are skipped. A procedure
+does not &rsquo;fall through&rsquo; if its CFG contains a
+basic block that is not the last block of the CFG and that
+ends on a RET instruction. The formal parameters of a
+procedure are determined by inspection of its code.</p>
+
+<p>The call-list in constructed by looking at all CAL
+instructions appearing in the program. The call-list should
+only contain calls to procedures that may be put in line.
+This fact is only known if the procedure was analyzed
+earlier. If a call to a procedure p appears in the program
+before the body of p, the call will always be put in the
+call-list. If p is later found to be unsuitable, the call
+will be removed from the list by the second subphase.</p>
+
+<p>An important issue is the recognition of the actual
+parameter expressions of the call. The front ends produces
+messages telling how many bytes of formal parameters every
+procedure accesses. (If there is no such message for a
+procedure, it cannot be put in line). The actual parameters
+together must account for the same number of bytes.A
+recursive descent parser is used to parse side-effect free
+EM expressions. It uses a table and some auxiliary routines
+to determine how many bytes every EM instruction pops from
+the stack and how many bytes it pushes onto the stack. These
+numbers depend on the EM instruction, its argument, and the
+wordsize and pointersize of the target machine. Initially,
+the parser has to recognize the number of bytes specified in
+the formals-message, say N. Assume the first instruction
+before the CAL pops S bytes and pushes R bytes. If R &gt; N,
+too many bytes are recognized and the parser fails. Else, it
+calls itself recursively to recognize the S bytes used as
+operand of the instruction. If it succeeds in doing so, it
+continues with the next instruction, i.e. the first
+instruction before the code recognized by the recursive
+call, to recognize N-R more bytes. The result is a number of
+EM instructions that collectively push N bytes. If an
+instruction is come across that has side-effects (e.g. a
+store or a procedure call) or of which R and S cannot be
+computed statically (e.g. a LOS), it fails.<br>
+Note that the parser traverses the code backwards. As EM
+code is essentially postfix code, the parser works top
+down.</p>
+
+<p>If the parser fails to recognize the parameters, the
+call will not be substituted in line. If the parameters can
+be determined, they still have to match the formal
+parameters of the called procedure. This check is performed
+by the second subphase; it cannot be done here, because it
+is possible that the called procedure has not been analyzed
+yet.</p>
+
+<p>The entire call-list is written to a file, to be
+processed by the second subphase.</p>
+<a name="5.5.3. The second subphase: making decisions"></a>
+<h2>5.5.3. The second subphase: making decisions</h2>
+
+<p>The task of the second subphase is quite easy to
+understand. It reads the call-list file, builds an incore
+call-list and deletes every call that may not be expanded in
+line (either because the called procedure may not be put in
+line, or because the actual parameters of the call do not
+match the formal parameters of the called procedure). It
+assigns a <i>pay-off</i> to every call, indicating how
+desirable it is to expand it.</p>
+
+<p>The subphase repeatedly scans the call-list and takes
+the call with the highest ratio. The chosen one gets marked,
+and the call-list is extended with the nested calls, as
+described above. These nested calls are also assigned a
+ratio, and will be considered too during the next scans.<br>
+After every decision the number of times every procedure is
+called is updated, using the call-count information.
+Meanwhile, the subphase keeps track of the amount of space
+left available. If all space is used, or if there are no
+more calls left to be expanded, it exits this loop. Finally,
+calls to procedures that are called only once are also
+chosen.</p>
+
+<p>The actual parameters of a call are only needed by this
+subphase to assign a ratio to a call. To save some space,
+these actuals are not kept in main memory. They are removed
+after the call has been read and a ratio has been assigned
+to it. So this subphase works with <i>abstracts</i> of
+calls. After all work has been done, the actual parameters
+of the chosen calls are retrieved from a file, as they are
+needed by the transformation subphase.</p>
+<a name="5.5.4. The third subphase: doing transformations"></a>
+<h2>5.5.4. The third subphase: doing transformations</h2>
+
+<p>The third subphase makes the actual modifications to the
+EM text. It is directed by the decisions made in the
+previous subphase, as expressed via the call-list. The
+call-list read by this subphase contains only calls that
+were selected for expansion. The list is ordered in the same
+way as the EM text, i.e. if a call C1 appears before a call
+C2 in the call-list, C1 also appears before C2 in the EM
+text. So the EM text is traversed linearly, the calls that
+have to be substituted are determined and the modifications
+are made. If a procedure is come across that is no longer
+needed, it is simply not written to the output EM file. The
+substitution of a call takes place in distinct steps:</p>
+
+<p>change the calling sequence</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The actual parameter expressions are changed. Parameters
+that are put in line are removed. All remaining ones must
+store their result in a temporary local variable, rather
+than push it on the stack. The CAL instruction and any ASP
+(to pop actual parameters) or LFR (to fetch the result of a
+function) are deleted.</p>
+</td>
+</table>
+
+<p>fetch the text of the called procedure</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>Direct disk access is used to to read the text of the
+called procedure. The file offset is obtained from the
+proctable entry.</p>
+</td>
+</table>
+
+<p>allocate bytes for locals and temporaries</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The local variables of the called procedure will be put
+in the stack frame of the calling procedure. The same
+applies to any temporary variables that hold the result of
+parameters that were not put in line. The proctable entry of
+the caller is updated.</p>
+</td>
+</table>
+
+<p>put a label after the CAL</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>If the called procedure contains a RET (return)
+instruction somewhere in the middle of its text (i.e. it
+does not fall through), the RET must be changed into a BRA
+(branch), to jump over the remainder of the text. This label
+is not needed if the called procedure falls through.</p>
+</td>
+</table>
+
+<p>copy the text of the called procedure and modify it</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>References to local variables of the called routine and
+to parameters that are not put in line are changed to refer
+to the new local of the caller. References to in line
+parameters are replaced by the actual parameter expression.
+Returns (RETs) are either deleted or replaced by a BRA.
+Messages containing information about local variables or
+parameters are changed. Global data declarations and the PRO
+and END pseudos are removed. Instruction labels and
+references to them are changed to make sure they do not have
+the same identifying number as labels in the calling
+procedure.</p>
+</td>
+</table>
+
+<p>insert the modified text</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The pseudos of the called procedure are put after the
+pseudos of the calling procedure. The real text of the
+callee is put at the place where the CAL was.</p>
+</td>
+</table>
+
+<p>take care of nested substitutions</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The expanded procedure may contain calls that have to be
+expanded too (nested calls). If the descriptor of this call
+contains actual parameter expressions, the code of the
+expressions has to be changed the same way as the code of
+the callee was changed. Next, the entire process of finding
+CALs and doing the substitutions is repeated
+recursively.</p>
+</td>
+</table>
+<a name="5.6. Source files of IL"></a>
+<h2>5.6. Source files of IL</h2>
+
+<p>The sources of IL are in the following files and
+packages (the prefixes 1_, 2_ and 3_ refer to the three
+subphases):</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>il.h:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>il.c:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>the routine main; the driving routines of the three
+subphases</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>1_anal:</p>
+</td>
+<td width="14%"></td>
+<td width="72%">
+
+<p>contains a subroutine that analyzes a procedure</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>1_cal:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>contains a subroutine that analyzes a call</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>1_aux:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements auxiliary procedures used by subphase 1</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>2_aux:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements auxiliary procedures used by subphase 2</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>3_subst:</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the driving routine for doing the substitution</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>3_change:</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>lower level routines that do certain modifications</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>3_aux:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements auxiliary procedures used by subphase 3</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>aux:</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>implements auxiliary procedures used by several
+subphases.</p>
+</td>
+</table>
+<a name="6. Strength reduction"></a>
+<h2>6. Strength reduction</h2>
+<a name="6.1. Introduction"></a>
+<h2>6.1. Introduction</h2>
+
+<p>The Strength Reduction optimization technique (SR) tries
+to replace expensive operators by cheaper ones, in order to
+decrease the execution time of the program. A classical
+example is replacing a &rsquo;multiplication by 2&rsquo; by
+an addition or a shift instruction. These kinds of local
+transformations are already done by the EM Peephole
+Optimizer. Strength reduction can also be applied more
+generally to operators used in a loop.</p>
+
+<p align=center><img src="grohtml-1027217.png"></p>
+
+<p>Fig. 6.1 An example of Strenght Reduction</p>
+
+<p>In Fig. 6.1, a multiplication inside a loop is replaced
+by an addition inside the loop and a multiplication outside
+the loop. Clearly, this is a global optimization; it cannot
+be done by a peephole optimizer.</p>
+
+<p>In some cases a related technique, <i>test
+replacement</i>, can be used to eliminate the loop variable
+i. This technique will not be discussed in this report.<br>
+In the example above, the resulting code can be further
+optimized by using constant propagation. Obviously, this is
+not the task of the Strength Reduction phase.</p>
+<a name="6.2. The model of strength reduction"></a>
+<h2>6.2. The model of strength reduction</h2>
+
+<p>In this section we will describe the transformations
+performed by Strength Reduction (SR). Before doing so, we
+will introduce the central notion of an induction
+variable.</p>
+<a name="6.2.1. Induction variables"></a>
+<h2>6.2.1. Induction variables</h2>
+
+<p>SR looks for variables whose values form an arithmetic
+progression at the beginning of a loop. These variables are
+called induction variables. The most frequently occurring
+example of such a variable is a loop-variable in a
+high-order programming language. Several quite sophisticated
+models of strength reduction can be found in the literature.
+[Cock77a, Alle81a, Lowr69a, Aho78a] In these models the
+notion of an induction variable is far more general than the
+intuitive notion of a loop-variable. The definition of an
+induction variable we present here is more restricted,
+yielding a simpler model and simpler transformations. We
+think the principle source for strength reduction lies in
+expressions using a loop-variable, i.e. a variable that is
+incremented or decremented by the same amount after every
+loop iteration, and that cannot be changed in any other
+way.</p>
+
+<p>Of course, the EM code does not contain high level
+constructs such as for-statements. We will define an
+induction variable in terms of the Intermediate Code of the
+optimizer. Note that the notions of a loop in the EM text
+and of a firm basic block were defined in section 3.3.5.</p>
+
+<p>definition<br>
+An induction variable i of a loop L is a local variable that
+is never accessed indirectly, whose size is the word size of
+the target machine, and that is assigned exactly once within
+L, the assignment:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>being of the form i := i + c or i := c +i, c is a
+constant called the <i>step value</i> of i.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="62%">
+
+<p>occurring in a firm block of L.</p>
+</td>
+<td width="27%">
+</td>
+</table>
+
+<p>(Note that the first restriction on the assignment is
+not described in terms of the Intermediate Code; we will
+give such a description later; the current definition is
+easier to understand however).</p>
+<a name="6.2.2. Recognized expressions"></a>
+<h2>6.2.2. Recognized expressions</h2>
+
+<p>SR recognizes certain expressions using an induction
+variable and replaces them by cheaper ones. Two kinds of
+expensive operations are recognized: multiplication and
+array address computations. The expressions that are
+simplified must use an induction variable as an operand of a
+multiplication or as index in an array expression.</p>
+
+<p>Often a linear function of an induction variable is
+used, rather than the variable itself. In these cases
+optimization is still possible. We call such expressions
+<i>iv-expressions</i>.</p>
+
+<p>definition:<br>
+An iv-expression of an induction variable i of a loop L is
+an expression that:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>uses only the operators + and - (unary as well as
+binary)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p>uses i as operand exactly once</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>uses (besides i) only constants or variables that are
+never changed in L as operands.</p>
+</td>
+</table>
+
+<p>The expressions recognized by SR are of the following
+forms:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(1)</p>
+</td>
+<td width="4%"></td>
+<td width="48%">
+
+<p>iv_expression * constant</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(2)</p>
+</td>
+<td width="4%"></td>
+<td width="48%">
+
+<p>constant * iv_expression</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(3)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>A[iv-expression] := (assign to array element)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(4)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>A[iv-expression] (use array element)</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(5)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>&amp; A[iv-expression] (take address of array
+element)</p>
+</td>
+</table>
+
+<p>(Note that EM has different instructions to use an array
+element, store into one, or take the address of one, resp.
+LAR, SAR, and AAR).<br>
+The size of the elements of A must be known statically. In
+cases (3) and (4) this size must equal the word size of the
+target machine.</p>
+<a name="6.2.3. Transformations"></a>
+<h2>6.2.3. Transformations</h2>
+
+<p>With every recognized expression we associate a new
+temporary local variable TMP, allocated in the stack frame
+of the procedure containing the expression. At any program
+point within the loop, TMP will contain the following
+value:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p>multiplication:</p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p>the current value of iv-expression * constant</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>arrays:</p>
+</td>
+<td width="22%"></td>
+<td width="64%">
+
+<p>the current value of &amp;A[iv-expression].</p>
+</td>
+</table>
+
+<p>In the second case, TMP essentially is a pointer
+variable, pointing to the element of A that is currently in
+use.<br>
+If the same expression occurs several times in the loop, the
+same temporary local is used each time.</p>
+
+<p>Three transformations are applied to the EM text:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(1)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>TMP is initialized with the right value. This
+initialization takes place just before the loop.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(2)</p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p>The recognized expression is simplified.</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(3)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>TMP is incremented; this takes place just after the
+induction variable is incremented.</p>
+</td>
+</table>
+
+<p>For multiplication, the initial value of TMP is the
+value of the recognized expression at the program point
+immediately before the loop. For arrays, TMP is initialized
+with the address of the first array element that is
+accessed. So the initialization code is:</p>
+<pre>     TMP := iv-expression * constant;  or
+     TMP := &amp;A[iv-expression]
+</pre>
+
+<p>At the point immediately before the loop, the induction
+variable will already have been initialized, so the value
+used in the code above will be the value it has during the
+first iteration.</p>
+
+<p>For multiplication, the recognized expression can simply
+be replaced by TMP. For array optimizations, the replacement
+depends on the form:</p>
+
+<p align=center><img src="grohtml-1027218.png"></p>
+
+<p>The &rsquo;*&rsquo; denotes the indirect operator. (Note
+that EM has different instructions to do an assign-indirect
+and a use-indirect). As the size of the array elements is
+restricted to be the word size in case (3) and (4), only one
+EM instruction needs to be generated in all cases.</p>
+
+<p>The amount by which TMP is incremented is:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p>multiplication:</p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p>step value * constant</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>arrays:</p>
+</td>
+<td width="22%"></td>
+<td width="50%">
+
+<p>step value * element size</p>
+</td>
+<td width="13%">
+</td>
+</table>
+
+<p>Note that the step value (see definition of induction
+variable above), the constant, and the element size (see
+previous section) can all be determined statically. If the
+sign of the induction variable in the iv-expression is
+negative, the amount must be negated.</p>
+
+<p>The transformations are demonstrated by an example.</p>
+
+<p align=center><img src="grohtml-1027219.png"></p>
+
+<p>Fig. 6.2 Example of complex Strength Reduction
+transformations</p>
+
+<p>The expression &rsquo;(6-i)*5&rsquo; is recognized
+twice. The constant is 5. The step value is -3. The sign of
+i in the recognized expression is &rsquo;-&rsquo;. So the
+increment value of TMP is -(-3*5) = +15.</p>
+<a name="6.3. Implementation"></a>
+<h2>6.3. Implementation</h2>
+
+<p>Like most phases, SR deals with one procedure at a time.
+Within a procedure, SR works on one loop at a time. Loops
+are processed in textual order. If loops are nested inside
+each other, SR starts with the outermost loop and proceeds
+in the inwards direction. This order is chosen, because it
+enables the optimization of multi-dimensional array address
+computations, if the elements are accessed in the usual way
+(i.e. row after row, rather than column after column). For
+every loop, SR first detects all induction variables and
+then tries to recognize expressions that can be
+optimized.</p>
+<a name="6.3.1. Finding induction variables"></a>
+<h2>6.3.1. Finding induction variables</h2>
+
+<p>The process of finding induction variables can
+conveniently be split up into two parts. First, the EM text
+of the loop is scanned to find all <i>candidate</i>
+induction variables, which are word-sized local variables
+that are assigned precisely once in the loop, within a firm
+block. Second, for every candidate, the single assignment is
+inspected, to see if it has the form required by the
+definition of an induction variable.</p>
+
+<p>Candidates are found by scanning the EM code of the
+loop. During this scan, two sets are maintained. The set
+&quot;cand&quot; contains all variables that were assigned
+exactly once so far, within a firm block. The set
+&quot;dismiss&quot; contains all variables that should not
+be made a candidate. Initially, both sets are empty. If a
+variable is assigned to, it is put in the cand set, if three
+conditions are met:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the variable was not in cand or dismiss already</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>the assignment takes place in a firm block</p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the assignment is not a ZRL instruction (assignment by
+zero) or a SDL instruction (store double local).</p>
+</td>
+</table>
+
+<p>If any condition fails, the variable is dismissed from
+cand (if it was there already) and put in dismiss (if it was
+not there already).<br>
+All variables for which no register message was generated
+(i.e. those variables that may be accessed indirectly) are
+assumed to be changed in the loop.<br>
+All variables that remain in cand are candidate induction
+variables.</p>
+
+<p>From the set of candidates, the induction variables can
+be determined, by inspecting the single assignment. The
+assignment must match one of the EM patterns below.
+(&rsquo;x&rsquo; is the candidate. &rsquo;ws&rsquo; is the
+word size of the target machine.</p>
+
+<p align=center><img src="grohtml-1027220.png"></p>
+
+<p>From the patterns the step size of the induction
+variable can also be determined. These step sizes are
+displayed on the right hand side.</p>
+
+<p>For every induction variable we maintain the following
+information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the offset of the variable in the stackframe of its
+procedure</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>a pointer to the EM text of the assignment statement</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="28%">
+
+<p>the step value</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<a name="6.3.2. Optimizing expressions"></a>
+<h2>6.3.2. Optimizing expressions</h2>
+
+<p>If any induction variables of the loop were found, the
+EM text of the loop is scanned again, to detect expressions
+that can be optimized. SR scans for multiplication and array
+instructions. Whenever it finds such an instruction, it
+analyses the code in front of it. If an expression is to be
+optimized, it must be generated by the following syntax
+rules.</p>
+
+<p align=center><img src="grohtml-1027221.png"></p>
+
+<p>An &rsquo;address&rsquo; is an EM instruction that loads
+an address on the stack. An instruction like LOL may be an
+&rsquo;address&rsquo;, if the size of an address (pointer
+size, =ps) is the same as the word size. If the pointer size
+is twice the word size, instructions like LDL are an
+&rsquo;address&rsquo;. (The addresses in the third grammar
+rule denote resp. the array address and the array descriptor
+address).</p>
+
+<p align=center><img src="grohtml-1027222.png"></p>
+
+<p>The notion of an iv-expression was introduced
+earlier.</p>
+
+<p align=center><img src="grohtml-1027223.png"></p>
+
+<p>An iv_expression must satisfy one additional constraint:
+it must use exactly one operand that is an induction
+variable. A simple, hand written, top-down parser is used to
+recognize an iv-expression. It scans the EM code from right
+to left (recall that EM is essentially postfix). It uses
+semantic attributes (inherited as well as derived) to check
+the additional constraint.</p>
+
+<p>All information assembled during the recognition process
+is put in a &rsquo;code_info&rsquo; structure. This
+structure contains the following information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p>the optimizable code itself</p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>the loop and basic block the code is part of</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="44%">
+
+<p>the induction variable</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="34%">
+
+<p>the iv-expression</p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the sign of the induction variable in the
+iv-expression</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the offset and size of the temporary local variable</p>
+</td>
+</table>
+
+<p>-</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>the expensive operator (MLI, LAR etc.)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the instruction that loads the constant (for
+multiplication) or the array descriptor (for arrays).</p>
+</td>
+</table>
+
+<p>The entire transformation process is driven by this
+information. As the EM text is represented internally as a
+list, this process consists mainly of straightforward list
+manipulations.<br>
+The initialization code must be put immediately before the
+loop entry. For this purpose a <i>header block</i> is
+created that has the loop entry block as its only successor
+and that dominates the entry block. The CFG and all
+relations (SUCC,PRED, IDOM, LOOPS etc.) are updated.<br>
+An EM instruction that will replace the optimizable code is
+created and put at the place of the old code. The list
+representing the old optimizable code is used to create a
+list for the initializing code, as they are similar. Only
+two modifications are required:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>if the expensive operator is a LAR or SAR, it must be
+replaced by an AAR, as the initial value of TMP is the
+<i>address</i> of the first array element that is
+accessed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>code must be appended to store the result of the
+expression in TMP.</p>
+</td>
+</table>
+
+<p>Finally, code to increment TMP is created and put after
+the code of the single assignment to the induction variable.
+The generated code uses either an integer addition (ADI) or
+an integer-to-pointer addition (ADS) to do the
+increment.</p>
+
+<p>SR maintains a set of all expressions that have already
+been recognized in the present loop. Such expressions are
+said to be <i>available</i>. If an expression is recognized
+that is already available, no new temporary local variable
+is allocated for it, and the code to initialize and
+increment the local is not generated.</p>
+<a name="6.4. Source files of SR"></a>
+<h2>6.4. Source files of SR</h2>
+
+<p>The sources of SR are in the following files and
+packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>sr.h:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>sr.c:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>the routine main; a driving routine to process (possibly
+nested) loops in the right order</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>iv</p>
+</td>
+<td width="24%"></td>
+<td width="72%">
+
+<p>implements a procedure that finds the induction
+variables of a loop</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>reduce</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements a procedure that finds optimizable
+expressions and that does the transformations</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>cand</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>implements a procedure that finds the candidate
+induction variables; used to implement iv</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>xform</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>implements several useful routines that transform lists
+of EM text or a CFG; used to implement reduce</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>expr</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>implements a procedure that parses iv-expressions</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>aux</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>implements several auxiliary procedures.</p>
+</td>
+</table>
+<a name="7. Common subexpression elimination"></a>
+<h2>7. Common subexpression elimination</h2>
+<a name="7.1. Introduction"></a>
+<h2>7.1. Introduction</h2>
+
+<p>The Common Subexpression Elimination optimization
+technique (CS) tries to eliminate multiple computations of
+EM expressions that yield the same result. It places the
+result of one such computation in a temporary variable, and
+replaces the other computations by a reference to this
+temporary variable. The primary goal of this technique is to
+decrease the execution time of the program, but in general
+it will save space too.</p>
+
+<p>As an example of the application of Common Subexpression
+Elimination, consider the piece of program in Fig.
+7.1(a).</p>
+
+<p align=center><img src="grohtml-1027224.png"></p>
+
+<p>Fig. 7.1 Examples of Common Subexpression
+Elimination</p>
+
+<p>If neither a nor b is changed in CODE, the instructions
+can be replaced by those of Fig. 7.1(b), which saves one
+multiplication, but costs an extra store instruction. If the
+value of x is not changed in CODE either, the instructions
+can be replaced by those of Fig. 7.1(c). In this case the
+extra store is not needed.</p>
+
+<p>In the following sections we will describe which
+transformations are done by CS and how this phase was
+implemented.</p>
+<a name="7.2. Specification of the Common Subexpression Elimination phase"></a>
+<h2>7.2. Specification of the Common Subexpression Elimination phase</h2>
+
+<p>In this section we will describe the window through
+which CS examines the code, the expressions recognized by
+CS, and finally the changes made to the code.</p>
+<a name="7.2.1. The working window"></a>
+<h2>7.2.1. The working window</h2>
+
+<p>The CS algorithm is applied to the largest sequence of
+textually adjacent basic blocks B1,..,Bn, for which</p>
+<pre>     PRED(Bj) = {Bj-1},  j = 2,..,n.
+</pre>
+
+<p>Intuitively, this window consists of straight line code,
+with only one entry point (at the beginning); it may contain
+jumps, which should all have their targets outside the
+window. This is illustrated in Fig. 7.2.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>x := a * b;</p>
+<td width="9%"></td>
+<td width="10%">
+
+<p>(1)<br>
+if x &lt; 10 then</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>(2)<br>
+y := a * b;</p>
+</td>
+<td width="20%"></td>
+<td width="10%">
+
+<p>(3)</p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+</table>
+
+<p>Fig. 7.2 The working window of CS</p>
+
+<p>Line (2) can only be executed after line (1). Likewise,
+line (3) can only be executed after line (2). Both a and b
+have the same values at line (1) and at line (3).</p>
+
+<p>Larger windows were avoided. In Fig. 7.3, the value of a
+at line (4) may have been obtained at more than one
+point.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>x := a * b;</p>
+<td width="9%"></td>
+<td width="10%">
+
+<p>(1)<br>
+if x &lt; 10 then</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>(2)<br>
+a := 100;</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>(3)<br>
+y := a * b;</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>(4)</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+
+<p>Fig. 7.3 Several working windows</p>
+<a name="7.2.2. Recognized expressions."></a>
+<h2>7.2.2. Recognized expressions.</h2>
+
+<p>The computations eliminated by CS need not be normal
+expressions (like &quot;a * b&quot;), but can even consist
+of a single operand that is expensive to access, such as an
+array element or a record field. If an array element is
+used, its address is computed implicitly. CS is able to
+eliminate either the element itself or its address,
+whichever one is most profitable. A variable of a textually
+enclosing procedure may also be expensive to access,
+depending on the lexical level difference.</p>
+<a name="7.2.3. Transformations"></a>
+<h2>7.2.3. Transformations</h2>
+
+<p>CS creates a new temporary local variable (TMP) for
+every eliminated expression, unless it is able to use an
+existing local variable. It emits code to initialize this
+variable with the result of the expression. Most recurrences
+of the expression can simply be replaced by a reference to
+TMP. If the address of an array element is recognized as a
+common subexpression, references to the element itself are
+replaced by indirect references through TMP (see Fig.
+7.4).</p>
+
+<p align=center><img src="grohtml-1027225.png"></p>
+
+<p>Fig. 7.4 Elimination of an array address computation</p>
+
+<p>Here, &rsquo;&amp;&rsquo; is the &rsquo;address
+of&rsquo; operator, and unary &rsquo;*&rsquo; is the
+indirection operator. (Note that EM actually has different
+instructions to do a use-indirect or an
+assign-indirect.)</p>
+<a name="7.3. Implementation"></a>
+<h2>7.3. Implementation</h2>
+<a name="7.3.1. The value number method"></a>
+<h2>7.3.1. The value number method</h2>
+
+<p>To determine whether two expressions have the same
+result, there must be some way to determine whether their
+operands have the same values. We use a system of <i>value
+numbers</i> [Kenn81a] in which each distinct value of
+whatever type, created or used within the working window,
+receives a unique identifying number, its value number. Two
+items have the same value number if and only if, based only
+upon information from the instructions in the window, their
+values are provably identical. For example, after processing
+the statement</p>
+<pre>     a := 4;
+</pre>
+
+<p>the variable a and the constant 4 have the same value
+number.</p>
+
+<p>The value number of the result of an expression depends
+only on the kind of operator and the value number(s) of the
+operand(s). The expressions need not be textually equal, as
+shown in Fig. 7.5.</p>
+
+<p align=center><img src="grohtml-1027226.png"></p>
+
+<p>Fig. 7.5 Different expressions with the same value
+number</p>
+
+<p>At line (1) a receives the same value number as c. At
+line (2) d receives the same value number as b. At line (4)
+the expression &quot;c * d&quot; receives the same value
+number as the expression &quot;a * b&quot; at line (2),
+because the value numbers of their left and right operands
+are the same, and the operator (*) is the same.</p>
+
+<p>As another example of the value number method, consider
+Fig. 7.6.</p>
+
+<p align=center><img src="grohtml-1027227.png"></p>
+
+<p>Fig. 7.6 Identical expressions with the different value
+numbers</p>
+
+<p>Although textually the expressions &quot;a * b&quot; in
+line 1 and line 3 are equal, a will have different value
+numbers at line 3 and line 1. The two expressions will not
+mistakenly be recognized as equivalent.</p>
+<a name="7.3.2. Entities"></a>
+<h2>7.3.2. Entities</h2>
+
+<p>The Value Number Method distinguishes between operators
+and operands. The value numbers of operands are stored in a
+table, called the <i>symbol table</i>. The value number of a
+subexpression depends on the (root) operator of the
+expression and on the value numbers of its operands. A table
+of &quot;available expressions&quot; is used to do this
+mapping.</p>
+
+<p>CS recognizes the following kinds of EM operands, called
+<i>entities</i>:</p>
+<pre>     - constant
+     - local variable
+     - external variable
+     - indirectly accessed entity
+     - offsetted entity
+     - address of local variable
+     - address of external variable
+     - address of offsetted entity
+     - address of local base
+     - address of argument base
+     - array element
+     - procedure identifier
+     - floating zero
+     - local base
+     - heap pointer
+     - ignore mask
+</pre>
+
+<p>Whenever a new entity is encountered in the working
+window, it is entered in the symbol table and given a brand
+new value number. Most entities have attributes (e.g. the
+offset in the current stackframe for local variables), which
+are also stored in the symbol table.</p>
+
+<p>An entity is called static if its value cannot be
+changed (e.g. a constant or an address).</p>
+<a name="7.3.3. Parsing expressions"></a>
+<h2>7.3.3. Parsing expressions</h2>
+
+<p>Common subexpressions are recognized by simulating the
+behaviour of the EM machine. The EM code is parsed from left
+to right; as EM is postfix code, this is a bottom up parse.
+At any point the current state of the EM runtime stack is
+reflected by a simulated &quot;fake stack&quot;, containing
+descriptions of the parsed operands and expressions. A
+descriptor consists of:</p>
+<pre>     (1) the value number of the operand or expression
+     (2) the size of the operand or expression
+     (3) a pointer to the first line of EM-code
+         that constitutes the operand or expression
+</pre>
+
+<p>Note that operands may consist of several EM
+instructions. Whenever an operator is encountered, the
+descriptors of its operands are on top of the fake stack.
+The operator and the value numbers of the operands are used
+as indices in the table of available expressions, to
+determine the value number of the expression.</p>
+
+<p>During the parsing process, we keep track of the first
+line of each expression; we need this information when we
+decide to eliminate the expression.</p>
+<a name="7.3.4. Updating entities"></a>
+<h2>7.3.4. Updating entities</h2>
+
+<p>An entity is assigned a value number when it is used for
+the first time in the working window. If the entity is used
+as left hand side of an assignment, it gets the value number
+of the right hand side. Sometimes the effects of an
+instruction on an entity cannot be determined exactly; the
+current value and value number of the entity may become
+inconsistent. Hence the current value number must be
+forgotten. This is achieved by giving the entity a new value
+number that was not used before. The entity is said to be
+<i>killed</i>.</p>
+
+<p>As information is lost when an entity is killed, CS
+tries to save as many entities as possible. In case of an
+indirect assignment through a pointer, some analysis is done
+to see which variables cannot be altered. For a procedure
+call, the interprocedural information contained in the
+procedure table is used to restrict the set of entities that
+may be changed by the call. Local variables for which the
+front end generated a register message can never be changed
+by an indirect assignment or a procedure call.</p>
+<a name="7.3.5. Changing the EM text"></a>
+<h2>7.3.5. Changing the EM text</h2>
+
+<p>When a new expression comes available, it is checked
+whether its result is saved in a local that may go in a
+register. The last line of the expression must be followed
+by a STL or SDL instruction (depending on the size of the
+result) and a register message must be present for this
+local. If there is such a local, it is recorded in the
+available expressions table. Each time a new occurrence of
+this expression is found, the value number of the local is
+compared against the value number of the result. If they are
+different the local cannot be used and is forgotten.</p>
+
+<p>The available expressions are linked in a list. New
+expressions are linked at the head of the list. In this way
+expressions that are contained within other expressions
+appear later in the list, because EM-expressions are
+postfix. The elimination process walks through the list,
+starting at the head, to find the largest expressions first.
+If an expression is eliminated, any expression later on in
+the list, contained in the former expression, is removed
+from the list, as expressions can only be eliminated
+once.</p>
+
+<p>A STL or SDL is emitted after the first occurrence of
+the expression, unless there was an existing local variable
+that could hold the result.</p>
+<a name="7.3.6. Desirability analysis"></a>
+<h2>7.3.6. Desirability analysis</h2>
+
+<p>Although the global optimizer works on EM code, the goal
+is to improve the quality of the object code. Therefore some
+machine-dependent information is needed to decide whether it
+is desirable to eliminate a given expression. Because it is
+impossible for the CS phase to know exactly what code will
+be generated, some heuristics are used. CS essentially looks
+for some special cases that should not be eliminated. These
+special cases can be turned on or off for a given machine,
+as indicated in a machine descriptor file.</p>
+
+<p>Some operators can sometimes be translated into an
+addressing mode for the machine at hand. Such an operator is
+only eliminated if its operand is itself expensive, i.e. it
+is not just a simple load. The machine descriptor file
+contains a set of such operators.</p>
+
+<p>Eliminating the loading of the Local Base or the
+Argument Base by the LXL resp. LXA instruction is only
+beneficial if the difference in lexical levels exceeds a
+certain threshold. The machine descriptor file contains this
+threshold.</p>
+
+<p>Replacing a SAR or a LAR by an AAR followed by a LOI may
+possibly increase the size of the object code. We assume
+that this is only possible when the size of the array
+element is greater than some limit.</p>
+
+<p>There are back ends that can very efficiently translate
+the index computing instruction sequence LOC SLI ADS. If
+this is the case, the SLI instruction between a LOC and an
+ADS is not eliminated.</p>
+
+<p>To handle unforseen cases, the descriptor file may also
+contain a set of operators that should never be
+eliminated.</p>
+<a name="7.3.7. The algorithm"></a>
+<h2>7.3.7. The algorithm</h2>
+
+<p>After these preparatory explanations, the algorithm
+itself is easy to understand. For each instruction within
+the current window, the following steps are performed in the
+given order :</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Check if this instruction defines an entity. If so, the
+set of entities is updated accordingly.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Kill all entities that might be affected by this
+instruction.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Simulate the instruction on the fake-stack. If this
+instruction is an operator, update the list of available
+expressions accordingly.</p>
+</td>
+</table>
+
+<p>The result of this process is a list of available
+expressions plus the information needed to eliminate them.
+Expressions that are desirable to eliminate are eliminated.
+Next, the window is shifted and the process is repeated.</p>
+<a name="7.4. Implementation."></a>
+<h2>7.4. Implementation.</h2>
+
+<p>In this section we will discuss the implementation of
+the CS phase. We will first describe the basic actions that
+are undertaken by the algorithm, than the algorithm
+itself.</p>
+<a name="7.4.1. Partioning the EM instructions"></a>
+<h2>7.4.1. Partioning the EM instructions</h2>
+
+<p>There are over 100 EM instructions. For our purpose we
+partition this huge set into groups of instructions which
+can be more or less conveniently handled together.</p>
+
+<p>There are groups for all sorts of load instructions:
+simple loads, expensive loads, loads of an array element. A
+load is considered <i>expensive</i> when more than one EM
+instructions are involved in loading it. The load of a
+lexical entity is also considered expensive. For instance:
+LOF is expensive, LAL is not. LAR forms a group on its own,
+because it is not only an expensive load, but also
+implicitly includes the ternary operator AAR, which computes
+the address of the array element.</p>
+
+<p>There are groups for all sorts of operators: unary,
+binary, and ternary. The groups of operators are further
+partitioned according to the size of their operand(s) and
+result.</p>
+
+<p>There are groups for all sorts of stores: direct,
+indirect, array element. The SAR forms a group on its own
+for the same reason as appeared with LAR.</p>
+
+<p>The effect of the remaining instructions is less clear.
+They do not help very much in parsing expressions or in
+constructing our pseudo symboltable. They are partitioned
+according to the following criteria:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>They change the value of an entity without using the
+stack (e.g. ZRL, DEE).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="74%">
+
+<p>They are subroutine calls (CAI, CAL).</p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>They change the stack in some irreproduceable way (e.g.
+ASP, LFR, DUP).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>They have no effect whatever on the stack or on the
+entities. This does not mean they can be deleted, but they
+can be ignored for the moment (e.g. MES, LIN, NOP).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>Their effect is too complicate too compute, so we just
+assume worst case behaviour. Hopefully, they do not occur
+very often. (e.g. MON, STR, BLM).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>They signal the end of the basic block (e.g. BLT, RET,
+TRP).</p>
+</td>
+</table>
+<a name="7.4.2. Parsing expressions"></a>
+<h2>7.4.2. Parsing expressions</h2>
+
+<p>To recognize expressions, we simulate the behaviour of
+the EM machine, by means of a fake-stack. When we scan the
+instructions in sequential order, we first encounter the
+instructions that load the operands on the stack, and then
+the instruction that indicates the operator, because EM
+expressions are postfix. When we find an instruction to load
+an operand, we load on the fake-stack a struct with the
+following information:</p>
+
+<p align=center><img src="grohtml-1027228.png"></p>
+
+<p>In most cases, (3) will point to the line that loaded
+the operand (e.g. LOL, LOC), i.e. there is only one line
+that refers to this operand, but sometimes some information
+must be popped to load the operand (e.g. LOI, LAR). This
+information must have been pushed before, so we also pop a
+pointer to the first line that pushed the information. This
+line is now the first line that defines the operand.</p>
+
+<p>When we find the operator instruction, we pop its
+operand(s) from the fake-stack. The first line that defines
+the first operand is now the first line of the expression.
+We now have all information to determine whether the just
+parsed expression has occurred before. We also know the
+first and last line of the expression; we need this when we
+decide to eliminate it. Associated with each available
+expression is a set of which the elements contains the first
+and last line of a recurrence of this expression.</p>
+
+<p>Not only will the operand(s) be popped from the
+fake-stack, but the following will be pushed:</p>
+
+<p align=center><img src="grohtml-1027229.png"></p>
+
+<p>In this way an item on the fake-stack always contains
+the necessary information. EM expressions are parsed bottum
+up.</p>
+<a name="7.4.3. Updating entities"></a>
+<h2>7.4.3. Updating entities</h2>
+
+<p>As said before, we build our private
+&quot;symboltable&quot;, while scanning the EM-instructions.
+The behaviour of the EM-machine is not only reflected in the
+fake-stack, but also in the entities. When an entity is
+created, we do not yet know its value, so we assign a brand
+new value number to it. Each time a store-instruction is
+encountered, we change the value number of the target entity
+of this store to the value number of the token that was
+popped from the fake-stack. Because entities may overlap, we
+must also &quot;forget&quot; the value numbers of entities
+that might be affected by this store. Each such entity will
+be <i>killed</i>, i.e. assigned a brand new valuenumber.</p>
+
+<p>Because we lose information when we forget the value
+number of an entity, we try to save as much entities as
+possible. When we store into an external, we don&rsquo;t
+have to kill locals and vice versa. Furthermore, we can see
+whether two locals or two externals overlap, because we know
+the offset from the local base, resp. the offset within the
+data block, and the size. The situation becomes more
+complicated when we have to consider indirection. The worst
+case is that we store through an unknown pointer. In that
+case we kill all entities except those locals for which a
+so-called <i>register message</i> has been generated; this
+register message indicates that this local can never be
+accessed indirectly. If we know this pointer we can be more
+careful. If it points to a local then the entity that is
+accessed through this pointer can never overlap with an
+external. If it points to an external this entity can never
+overlap with a local. Furthermore, in the latter case, we
+can find the data block this entity belongs to. Since
+pointer arithmetic is only defined within a data block, this
+entity can never overlap with entities that are known to
+belong to another data block.</p>
+
+<p>Not only after a store-instruction but also after a
+subroutine-call it may be necessary to kill entities; the
+subroutine may affect global variables or store through a
+pointer. If a subroutine is called that is not available as
+EM-text, we assume worst case behaviour, i.e. we kill all
+entities without register message.</p>
+<a name="7.4.4. Additions and replacements."></a>
+<h2>7.4.4. Additions and replacements.</h2>
+
+<p>When a new expression comes available, we check whether
+the result is saved in a local that may go in a register.
+The last line of the expression must be followed by a STL or
+SDL instruction, depending on the size of the result (resp.
+WS and 2*WS), and a register message must be present for
+this local. If we have found such a local, we store a
+pointer to it with the available expression. Each time a new
+occurrence of this expression is found, we compare the value
+number of the local against the value number of the result.
+When they are different we remove the pointer to it, because
+we cannot use it.</p>
+
+<p>The available expressions are singly linked in a list.
+When a new expression comes available, we link it at the
+head of the list. In this way expressions that are contained
+within other expressions appear later in the list, because
+EM-expressions are postfix. When we are going to eliminate
+expressions, we walk through the list, starting at the head,
+to find the largest expressions first. When we decide to
+eliminate an expression, we look at the expressions in the
+tail of the list, starting from where we are now, to delete
+expressions that are contained within the chosen one because
+we cannot eliminate an expression more than once.</p>
+
+<p>When we are going to eliminate expressions, and we do
+not have a local that holds the result, we emit a STL or SDL
+after the line where the expression was first found. The
+other occurrences are simply removed, unless they contain
+instructions that not only have effect on the stack; e.g.
+messages, stores, calls. Before each instruction that needs
+the result on the stack, we emit a LOL or LDL. When the
+expression was an AAR, but the instruction was a LAR or a
+SAR, we append a LOI resp. a STI of the number of bytes in
+an array-element after each LOL/LDL.</p>
+<a name="7.4.5. Desirability analysis"></a>
+<h2>7.4.5. Desirability analysis</h2>
+
+<p>Although the global optimizer works on EM code, the goal
+is to improve the quality of the object code. Therefore we
+need some machine dependent information to decide whether it
+is desirable to eliminate a given expression. Because it is
+impossible for the CS phase to know exactly what code will
+be generated, we use some heuristics. In most cases it will
+save time when we eliminate an operator, so we just do it.
+We only look for some special cases.</p>
+
+<p>Some operators can in some cases be translated into an
+addressing mode for the machine at hand. We only eliminate
+such an operator, when its operand is itself
+&quot;expensive&quot;, i.e. not just a simple load. The user
+of the CS phase has to supply a set of such operators.</p>
+
+<p>Eliminating the loading of the Local Base or the
+Argument Base by the LXL resp. LXA instruction is only
+beneficial when the number of lexical levels we have to go
+back exceeds a certain threshold. This threshold will be
+different when registers are saved by the back end. The user
+must supply this threshold.</p>
+
+<p>Replacing a SAR or a LAR by an AAR followed by a LOI may
+possibly increase the size of the object code. We assume
+that this is only possible when the size of the array
+element is greater than some (user-supplied) limit.</p>
+
+<p>There are back ends that can very efficiently translate
+the index computing instruction sequence LOC SLI ADS. If
+this is the case, we do not eliminate the SLI instruction
+between a LOC and an ADS.</p>
+
+<p>To handle unforeseen cases, the user may also supply a
+set of operators that should never be eliminated.</p>
+<a name="7.4.6. The algorithm"></a>
+<h2>7.4.6. The algorithm</h2>
+
+<p>After these preparatory explanations, we can be short
+about the algorithm itself. For each instruction within our
+window, the following steps are performed in the order
+given:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>We check if this instructin defines an entity. If this
+is the case the set of entities is updated accordingly.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>We kill all entities that might be affected by this
+instruction.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The instruction is simulated on the fake-stack. Copy
+propagation is done. If this instruction is an operator, we
+update the list of available expressions accordingly.</p>
+</td>
+</table>
+
+<p>When we have processed all instructions this way, we
+have built a list of available expressions plus the
+information we need to eliminate them. Those expressions of
+which desirability analysis tells us so, we eliminate. The
+we shift our window and continue.</p>
+<a name="7.5. Source files of CS"></a>
+<h2>7.5. Source files of CS</h2>
+
+<p>The sources of CS are in the following files and
+packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>cs.h</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>cs.c</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>the routine main; a driving routine to process the basic
+blocks in the right order</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>vnm</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>implements a procedure that performs the value numbering
+on one basic block</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>eliminate</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>implements a procedure that does the transformations, if
+desirable</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>avail</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>implements a procedure that manipulates the list of
+available expressions</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>entity</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements a procedure that manipulates the set of
+entities</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>getentity</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>implements a procedure that extracts the pseudo
+symboltable information from EM-instructions; uses a small
+table</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>kill</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>implements several routines that find the entities that
+might be changed by EM-instructions and kill them</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>partition</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>implements several routines that partition the huge set
+of EM-instructions into more or less manageable, more or
+less logical chunks</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>profit</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>implements a procedure that decides whether it is
+advantageous to eliminate an expression; also removes
+expressions with side-effects</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>stack</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>implements the fake-stack and operations on it</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>alloc</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>implements several allocation routines</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>aux</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>implements several auxiliary routines</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>debug</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>implements several routines to provide debugging and
+verbose output</p>
+</td>
+</table>
+<a name="8. Stack pollution"></a>
+<h2>8. Stack pollution</h2>
+<a name="8.1. Introduction"></a>
+<h2>8.1. Introduction</h2>
+
+<p>The &quot;Stack Pollution&quot; optimization technique
+(SP) decreases the costs (time as well as space) of
+procedure calls. In the EM calling sequence, the actual
+parameters are popped from the stack by the <i>calling</i>
+procedure. The ASP (Adjust Stack Pointer) instruction is
+used for this purpose. A call in EM is shown in Fig. 8.1</p>
+
+<p align=center><img src="grohtml-1027230.png"></p>
+
+<p>Fig. 8.1 An example procedure call in Pascal and EM</p>
+
+<p>As procedure calls occur often in most programs, the ASP
+is one of the most frequently used EM instructions.</p>
+
+<p>The main intention of removing the actual parameters
+after a procedure call is to avoid the stack size to
+increase rapidly. Yet, in some cases, it is possible to
+<i>delay</i> or even <i>avoid</i> the removal of the
+parameters without letting the stack grow significantly. In
+this way, considerable savings in code size and execution
+time may be achieved, at the cost of a slightly increased
+stack size.</p>
+
+<p>A stack adjustment may be delayed if there is some other
+stack adjustment later on in the same basic block. The two
+ASPs can be combined into one.</p>
+
+<p align=center><img src="grohtml-1027231.png"></p>
+
+<p>Fig. 8.2 An example of local Stack Pollution</p>
+
+<p>The stacksize will be increased only temporarily. If the
+basic block contains another ASP, the ASP 10 may
+subsequently be combined with that next ASP, and so on.</p>
+
+<p>For some back ends, a stack adjustment also takes place
+at the point of a procedure return. There is no need to
+specify the number of bytes to be popped at a return. This
+provides an opportunity to remove ASPs more globally. If all
+ASPs outside any loop are removed, the increase of the stack
+size will still only be small, as no such ASP is executed
+more than once without an intervening return from the
+procedure it is part of.</p>
+
+<p>This second approach is not generally applicable to all
+target machines, as some back ends require the stack to be
+cleaned up at the point of a procedure return.</p>
+<a name="8.2. Implementation"></a>
+<h2>8.2. Implementation</h2>
+
+<p>There is one main problem the implementation has to
+solve. In EM, the stack is not only used for passing
+parameters, but also for evaluating expressions. Hence, ASP
+instructions can only be combined or removed if certain
+conditions are satisfied.</p>
+
+<p>Two consecutive ASPs of one basic block can only be
+combined (as described above) if:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>On no point of text in between the two ASPs, any item is
+popped from the stack that was pushed onto it before the
+first ASP.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The number of bytes popped from the stack by the second
+ASP must equal the number of bytes pushed since the first
+ASP.</p>
+</td>
+</table>
+
+<p>Condition 1. is not satisfied in Fig. 8.3.</p>
+
+<p align=center><img src="grohtml-1027232.png"></p>
+
+<p>Fig. 8.3 An illegal transformation</p>
+
+<p>If the first ASP were removed (delayed), the first ADI
+would add 10 and f(10), instead of 5 and f(10).</p>
+
+<p>Condition 2. is not satisfied in Fig. 8.4.</p>
+
+<p align=center><img src="grohtml-1027233.png"></p>
+
+<p>Fig. 8.4 A second illegal transformation</p>
+
+<p>If the two ASPs were combined into one &rsquo;ASP
+4&rsquo;, the constant 5 would have been popped, rather than
+the parameter 10 (so &rsquo;10 + f(10)*g(30)&rsquo; would
+have been computed).</p>
+
+<p>The second approach to deleting ASPs (i.e. let the
+procedure return do the stack clean-up) is only applied to
+the last ASP of every basic block. Any preceding ASPs are
+dealt with by the first approach. The last ASP of a basic
+block B will only be removed if:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>on no path in the control flow graph from B to any block
+containing a RET (return) there is a basic block that, at
+some point of its text, pops items from the stack that it
+has not itself pushed earlier.</p>
+</td>
+</table>
+
+<p>Clearly, if this condition is satisfied, no harm can be
+done; no other basic block will ever access items that were
+pushed on the stack before the ASP.</p>
+
+<p>The number of bytes pushed onto or popped from the stack
+can be easily encoded in a so called &quot;pop-push
+table&quot;. The numbers in general depend on the target
+machine word- and pointer size and on the argument given to
+the instruction. For example, an ADS instruction is
+described by:</p>
+<pre>        -a-p+p
+</pre>
+
+<p>which means: an &rsquo;ADS n&rsquo; first pops an n-byte
+value (n being the argument), next pops a pointer-size value
+and finally pushes a pointer-size value. For some
+infrequently used EM instructions the pop-push numbers
+cannot be computed statically.</p>
+
+<p>The stack pollution algorithm first performs a depth
+first search over the control flow graph and marks all
+blocks that do not satisfy the global condition. Next it
+visits all basic blocks in turn. For every pair of adjacent
+ASPs, it checks conditions 1. and 2. and combines the ASPs
+if they are satisfied. The new ASP may be used as first ASP
+in the next pair. If a condition fails, it simply continues
+with the next ASP. Finally, the last ASP is removed if:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>nothing has been popped from the stack after the last
+ASP that was pushed before it</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the block was not marked by the depth first search</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p>the block is not in a loop</p>
+</td>
+<td width="37%">
+</td>
+</table>
+<a name="9. Cross jumping"></a>
+<h2>9. Cross jumping</h2>
+<a name="9.1. Introduction"></a>
+<h2>9.1. Introduction</h2>
+
+<p>The &quot;Cross Jumping&quot; optimization technique
+(CJ) [Wulf75a] is basically a space optimization technique.
+It looks for pairs of basic blocks (B1,B2), for which:</p>
+<pre>     SUCC(B1) = SUCC(B2) = {S}
+</pre>
+
+<p>(So B1 and B2 both have one and the same successor). If
+the last few non-branch instructions are the same for B1 and
+B2, one such sequence can be eliminated.</p>
+<pre>     Pascal:
+
+
+     if cond then
+         S1
+         S3
+     else
+         S2
+         S3
+
+
+     (pseudo) EM:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</pre>
+
+<p align=center><img src="grohtml-1027234.png"></p>
+
+<p>Fig. 9.1 An example of Cross Jumping</p>
+
+<p>As the basic blocks have the same successor, at least
+one of them ends in an unconditional branch instruction
+(BRA). Hence no extra branch instruction is ever needed,
+just the target of an existing branch needs to be changed;
+neither the program size nor the execution time will ever
+increase. In general, the execution time will remain the
+same, unless further optimizations can be applied because of
+this optimization.</p>
+
+<p>This optimization is particularly effective, because it
+cannot always be done by the programmer at the source level,
+as demonstrated by the Fig. 8.2.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>Pascal:</p>
+</table>
+
+<p>if cond then<br>
+x := f(4)<br>
+else<br>
+x := g(5)</p>
+
+<p>EM:</p>
+
+<p align=center><img src="grohtml-1027235.png"></p>
+
+<p>Fig. 9.2 Effectiveness of Cross Jumping</p>
+
+<p>At the source level there is no common tail, but at the
+EM level there is a common tail.</p>
+<a name="9.2. Implementation"></a>
+<h2>9.2. Implementation</h2>
+
+<p>The implementation of cross jumping is rather
+straightforward. The technique is applied to one procedure
+at a time. The control flow graph of the procedure is
+scanned for pairs of basic blocks with the same (single)
+successor and with common tails. Note that there may be more
+than two such blocks (e.g. as the result of a case
+statement). This is dealt with by repeating the entire
+process until no further optimizations can de done for the
+current procedure.</p>
+
+<p>If a suitable pair of basic blocks has been found, the
+control flow graph must be altered. One of the basic blocks
+must be split into two. The control flow graphs before and
+after the optimization are shown in Fig. 9.3 and Fig.
+9.4.</p>
+<pre>             --------                                --------
+             |      |                                |      |
+             | S1   |                                | S2   |
+             | S3   |                                | S3   |
+             |      |                                |      |
+             --------                                --------
+                |                                       |
+                |------------------|--------------------|
+                                   |
+                                   v
+
+
+     Fig. 9.3 CFG before optimization
+</pre>
+<pre>             --------                                --------
+             |      |                                |      |
+             | S1   |                                | S2   |
+             |      |                                |      |
+             --------                                --------
+                |                                       |
+                |--------------------&lt;------------------|
+                v
+             --------
+             |      |
+             | S3   |
+             |      |
+             --------
+                |
+                v
+
+
+     Fig. 9.4 CFG after optimization
+</pre>
+
+<p>Some attributes of the three resulting blocks (such as
+immediate dominator) are updated.</p>
+
+<p>In some cases, cross jumping might split the computation
+of an expression into two, by inserting a branch somewhere
+in the middle. Most code generators will generate very poor
+assembly code when presented with such EM code. Therefor,
+cross jumping is not performed in these cases.</p>
+<a name="10. Branch Optimization"></a>
+<h2>10. Branch Optimization</h2>
+<a name="10.1. Introduction"></a>
+<h2>10.1. Introduction</h2>
+
+<p>The Branch Optimization phase (BO) performs two related
+(branch) optimizations.</p>
+<a name="10.1.1. Fusion of basic blocks"></a>
+<h2>10.1.1. Fusion of basic blocks</h2>
+
+<p>If two basic blocks B1 and B2 have the following
+properties:</p>
+<pre>     SUCC(B1) = {B2}
+     PRED(B2) = {B1}
+</pre>
+
+<p>then B1 and B2 can be combined into one basic block. If
+B1 ends in an unconditional jump to the beginning of B2,
+this jump can be eliminated, hence saving a little execution
+time and object code size. This technique can be used to
+eliminate some deficiencies introduced by the front ends
+(for example, the &quot;C&quot; front end translates switch
+statements inefficiently due to its one pass nature).</p>
+<a name="10.1.2. While-loop optimization"></a>
+<h2>10.1.2. While-loop optimization</h2>
+
+<p>The straightforward way to translate a while loop is to
+put the test for loop termination at the beginning of the
+loop.</p>
+<pre>     while cond loop                       LAB1: Test cond
+        body of the loop     ---&gt;                Branch On False To LAB2
+     end loop                                    code for body of loop
+                                                 Branch To LAB1
+                                           LAB2:
+
+
+     Fig. 10.1 Example of Branch Optimization
+</pre>
+
+<p>If the condition fails at the Nth iteration, the
+following code gets executed (dynamically):</p>
+
+<p align=center><img src="grohtml-1027236.png"></p>
+
+<p>An alternative translation is:</p>
+<pre>          Branch To LAB2
+     LAB1:
+          code for body of loop
+     LAB2:
+          Test cond
+          Branch On True To LAB1
+</pre>
+
+<p>This translation results in the following profile:</p>
+
+<p align=center><img src="grohtml-1027237.png"></p>
+
+<p>So the second translation will be significantly faster
+if N &gt;&gt; 2. If N=2, execution time will be slightly
+increased. On the average, the program will be speeded up.
+Note that the code sizes of the two translations will be the
+same.</p>
+<a name="10.2. Implementation"></a>
+<h2>10.2. Implementation</h2>
+
+<p>The basic block fusion technique is implemented by
+traversing the control flow graph of a procedure, looking
+for basic blocks B with only one successor (S). If one is
+found, it is checked if S has only one predecessor (which
+has to be B). If so, the two basic blocks can in principle
+be combined. However, as one basic block will have to be
+moved, the textual order of the basic blocks will be
+altered. This reordering causes severe problems in the
+presence of conditional jumps. For example, if S ends in a
+conditional branch, the basic block that comes textually
+next to S must stay in that position. So the transformation
+in Fig. 10.2 is illegal.</p>
+
+<p align=center><img src="grohtml-1027238.png"></p>
+
+<p>Fig. 10.2 An illegal transformation of Branch
+Optimization</p>
+
+<p>If B is moved towards S the same problem occurs if the
+block before B ends in a conditional jump. The problem could
+be solved by adding one extra branch, but this would reduce
+the gains of the optimization to zero. Hence the
+optimization will only be done if the block that follows S
+(in the textual order) is not a successor of S. This
+condition assures that S does not end in a conditional
+branch. The condition always holds for the code generated by
+the &quot;C&quot; front end for a switch statement.</p>
+
+<p>After the transformation has been performed, some
+attributes of the basic blocks involved (such as successor
+and predecessor sets and immediate dominator) must be
+recomputed.</p>
+
+<p>The while-loop technique is applied to one loop at a
+time. The list of basic blocks of the loop is traversed to
+find a block B that satisfies the following conditions:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the textually next block to B is not part of the
+loop</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the last instruction of B is an unconditional branch;
+hence B has only one successor, say S</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the textually next block of B is a successor of S</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the last instruction of S is a conditional branch</p>
+</td>
+</table>
+
+<p>If such a block B is found, the control flow graph is
+changed as depicted in Fig. 10.3.</p>
+<pre>            |                                    |
+            |                                    v
+            v                                    |
+            |-----&lt;------|                       -----&gt;-----|
+        ____|____        |                                  |
+        |       |        |               |-------|          |
+        |  S1   |        |               |       v          |
+        |  Bcc  |        |               |     ....         |
+     |--|       |        |               |                  |
+     |  ---------        |               |   ----|----      |
+     |                   |               |   |       |      |
+     |     ....          ^               |   |  S2   |      |
+     |                   |               |   |       |      |
+     |   ---------       |               |   |       |      |
+     v   |       |       |               ^   ---------      |
+     |   |  S2   |       |               |       |          |
+     |   | BRA   |       |               |       |-----&lt;-----
+     |   |       |       |               |       v
+     |   ---------       |               |   ____|____
+     |       |           |               |   |       |
+     |       ------&gt;------               |   |  S1   |
+     |                                   |   |  Bnn  |
+     |-------|                           |   |       |
+             |                           |   ----|----
+             v                           |       |
+                                         |----&lt;--|
+                                                 |
+                                                 v
+
+
+     Fig. 10.3 Transformation of the CFG by Branch Optimization
+</pre>
+<a name="11. Use-Definition analysis"></a>
+<h2>11. Use-Definition analysis</h2>
+<a name="11.1. Introduction"></a>
+<h2>11.1. Introduction</h2>
+
+<p>The &quot;Use-Definition analysis&quot; phase (UD)
+consists of two related optimization techniques that both
+depend on &quot;Use-Definition&quot; information. The
+techniques are Copy Propagation and Constant Propagation.
+They are best explained via an example (see Figs. 11.1 and
+11.2).</p>
+<pre>        (1)  A := B                  A := B
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>... --&gt; ...</p>
+</table>
+
+<p>(2) use(A) use(B)</p>
+
+<p>Fig. 11.1 An example of Copy Propagation</p>
+<pre>        (1)  A := 12                  A := 12
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>... --&gt; ...</p>
+</table>
+
+<p>(2) use(A) use(12)</p>
+
+<p>Fig. 11.2 An example of Constant Propagation</p>
+
+<p>Both optimizations have to check that the value of A at
+line (2) can only be obtained at line (1). Copy Propagation
+also has to assure that the value of B is the same at line
+(1) as at line (2).</p>
+
+<p>One purpose of both transformations is to introduce
+opportunities for the Dead Code Elimination optimization. If
+the variable A is used nowhere else, the assignment A := B
+becomes useless and can be eliminated.<br>
+If B is less expensive to access than A (e.g. this is
+sometimes the case if A is a local variable and B is a
+global variable), Copy Propagation directly improves the
+code itself. If A is cheaper to access the transformation
+will not be performed. Likewise, a constant as operand may
+be cheeper than a variable. Having a constant as operand may
+also facilitate other optimizations.</p>
+
+<p>The design of UD is based on the theory described in
+section 14.1 and 14.3 of. [Aho78a] As a main departure from
+that theory, we do not demand the statement A := B to become
+redundant after Copy Propagation. If B is cheaper to access
+than A, the optimization is always performed; if B is more
+expensive than A, we never do the transformation. If A and B
+are equally expensive UD uses the heuristic rule to replace
+infrequently used variables by frequently used ones. This
+rule increases the chances of the assignment to become
+useless.</p>
+
+<p>In the next section we will give a brief outline of the
+data flow theory used for the implementation of UD.</p>
+<a name="11.2. Data flow information"></a>
+<h2>11.2. Data flow information</h2>
+<a name="11.2.1. Use-Definition information"></a>
+<h2>11.2.1. Use-Definition information</h2>
+
+<p>A <i>definition</i> of a variable A is an assignment to
+A. A definition is said to <i>reach</i> a point p if there
+is a path in the control flow graph from the definition to
+p, such that A is not redefined on that path.</p>
+
+<p>For every basic block B, we define the following
+sets:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>GEN[b]</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>the set of definitions in b that reach the end of b.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>KILL[b]</p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p>the set of definitions outside b that define a variable
+that is changed in b.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>IN[b]</p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p>the set of all definitions reaching the beginning of
+b.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>OUT[b]</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>the set of all definitions reaching the end of b.</p>
+</td>
+</table>
+
+<p>GEN and KILL can be determined by inspecting the code of
+the procedure. IN and OUT are computed by solving the
+following data flow equations:</p>
+<pre>     (1)    OUT[b] = IN[b] - KILL[b] + GEN[b]
+     (2)    IN[b]  = OUT[p1] + ... + OUT[pn],
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>where PRED(b) = {p1, ... , pn}</p>
+</table>
+<a name="11.2.2. Copy information"></a>
+<h2>11.2.2. Copy information</h2>
+
+<p>A <i>copy</i> is a definition of the form &quot;A :=
+B&quot;. A copy is said to be <i>generated</i> in a basic
+block n if it occurs in n and there is no subsequent
+assignment to B in n. A copy is said to be <i>killed</i> in
+n if:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>it occurs in n and there is a subsequent assignment to B
+within n, or</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>it occurs outside n, the definition A := B reaches the
+beginning of n and B is changed in n (note that a copy also
+is a definition).</p>
+</td>
+</table>
+
+<p>A copy <i>reaches</i> a point p, if there are no
+assignments to B on any path in the control flow graph from
+the copy to p.</p>
+
+<p>We define the following sets:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>C_GEN[b]</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p>the set of all copies in b generated in b.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>C_KILL[b]</p>
+</td>
+<td width="4%"></td>
+<td width="68%">
+
+<p>the set of all copies killed in b.</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>C_IN[b]</p>
+</td>
+<td width="8%"></td>
+<td width="78%">
+
+<p>the set of all copies reaching the beginning of b.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>C_OUT[b]</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p>the set of all copies reaching the end of b.</p>
+</td>
+</table>
+
+<p>C_IN and C_OUT are computed by solving the following
+equations: (root is the entry node of the current procedure;
+&rsquo;*&rsquo; denotes set intersection)</p>
+<pre>     (1)    C_OUT[b] = C_IN[b] - C_KILL[b] + C_GEN[b]
+     (2)    C_IN[b]  = C_OUT[p1] * ... * C_OUT[pn],
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>where PRED(b) = {p1, ... , pn} and b /= root</p>
+</table>
+
+<p>C_IN[root] = {all copies}</p>
+<a name="11.3. Pointers and subroutine calls"></a>
+<h2>11.3. Pointers and subroutine calls</h2>
+
+<p>The theory outlined above assumes that variables can
+only be changed by a direct assignment. This condition does
+not hold for EM. In case of an assignment through a pointer
+variable, it is in general impossible to see which variable
+is affected by the assignment. Similar problems occur in the
+presence of procedure calls. Therefore we distinguish two
+kinds of definitions:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>an <i>explicit</i> definition is a direct assignment to
+one specific variable</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>an <i>implicit</i> definition is the potential
+alteration of a variable as a result of a procedure call or
+an indirect assignment.</p>
+</td>
+</table>
+
+<p>An indirect assignment causes implicit definitions to
+all variables that may be accessed indirectly, i.e. all
+local variables for which no register message was generated
+and all global variables. If a procedure contains an
+indirect assignment it may change the same set of variables,
+else it may change some global variables directly. The KILL,
+GEN, IN and OUT sets contain explicit as well as implicit
+definitions.</p>
+<a name="11.4. Implementation"></a>
+<h2>11.4. Implementation</h2>
+
+<p>UD first builds a number of tables:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>locals:</p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p>contains information about the local variables of the
+current procedure (offset,size,whether a register message
+was found for it and, if so, the score field of that
+message)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>defs:</p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p>a table of all explicit definitions appearing in the
+current procedure.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>copies:</p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p>a table of all copies appearing in the current
+procedure.</p>
+</td>
+</table>
+
+<p>Every variable (local as well as global), definition and
+copy is identified by a unique number, which is the index in
+the table. All tables are constructed by traversing the EM
+code. A fourth table, &quot;vardefs&quot; is used, indexed
+by a &rsquo;variable number&rsquo;, which contains for every
+variable the set of explicit definitions of it. Also, for
+each basic block b, the set CHGVARS containing all variables
+changed by it is computed.</p>
+
+<p>The GEN sets are obtained in one scan over the EM text,
+by analyzing every EM instruction. The KILL set of a basic
+block b is computed by looking at the set of variables
+changed by b (i.e. CHGVARS[b]). For every such variable v,
+all explicit definitions to v (i.e. vardefs[v]) that are not
+in GEN[b] are added to KILL[b]. Also, the implicit
+defininition of v is added to KILL[b]. Next, the data flow
+equations for use-definition information are solved, using a
+straight forward, iterative algorithm. All sets are
+represented as bitvectors, so the operations on sets (union,
+difference) can be implemented efficiently.</p>
+
+<p>The C_GEN and C_KILL sets are computed simultaneously in
+one scan over the EM text. For every copy A := B appearing
+in basic block b we do the following:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>for every basic block n /= b that changes B, see if the
+definition A := B reaches the beginning of n (i.e. check if
+the index number of A := B in the &quot;defs&quot; table is
+an element of IN[n]); if so, add the copy to C_KILL[n]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>if B is redefined later on in b, add the copy to
+C_KILL[b], else add it to C_GEN[b]</p>
+</td>
+</table>
+
+<p>C_IN and C_OUT are computed from C_GEN and C_KILL via
+the second set of data flow equations.</p>
+
+<p>Finally, in one last scan all opportunities for
+optimization are detected. For every use u of a variable A,
+we check if there is a unique explicit definition d reaching
+u.</p>
+
+<p>If the definition is a copy A := B and B has the same
+value at d as at u, then the use of A at u may be changed
+into B. The latter condition can be verified as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>if u and d are in the same basic block, see if there is
+any assignment to B in between d and u</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>if u and d are in different basic blocks, the condition
+is satisfied if there is no assignment to B in the block of
+u prior to u and d is in C_IN[b].</p>
+</td>
+</table>
+
+<p>Before the transformation is actually done, UD first
+makes sure the alteration is really desirable, as described
+before. The information needed for this purpose (access
+costs of local and global variables) is read from a machine
+descriptor file.</p>
+
+<p>If the only definition reaching u has the form &quot;A
+:= constant&quot;, the use of A at u is replaced by the
+constant.</p>
+<a name="11.5. Source files of UD"></a>
+<h2>11.5. Source files of UD</h2>
+
+<p>The sources of UD are in the following files and
+packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>ud.h:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>ud.c:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>the routine main; initialization of target machine
+dependent tables</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>defs:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>routines to compute the GEN and KILL sets and routines
+to analyse EM instructions</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>const:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>routines involved in constant propagation</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>copy:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>routines involved in copy propagation</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>aux:</p>
+</td>
+<td width="20%"></td>
+<td width="54%">
+
+<p>contains auxiliary routines</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<a name="12. Live-Variable analysis"></a>
+<h2>12. Live-Variable analysis</h2>
+<a name="12.1. Introduction"></a>
+<h2>12.1. Introduction</h2>
+
+<p>The &quot;Live-Variable analysis&quot; optimization
+technique (LV) performs some code improvements and computes
+information that may be used by subsequent optimizations.
+The main task of this phase is the computation of
+<i>live-variable information</i>. [Aho78a section 14.4] A
+variable A is said to be <i>dead</i> at some point p of the
+program text, if on no path in the control flow graph from p
+to a RET (return), A can be used before being changed; else
+A is said to be <i>live</i>.</p>
+
+<p>A statement of the form</p>
+<pre>     VARIABLE := EXPRESSION
+</pre>
+
+<p>is said to be dead if the left hand side variable is
+dead just after the statement and the right hand side
+expression has no side effects (i.e. it doesn&rsquo;t change
+any variable). Such a statement can be eliminated entirely.
+Dead code will seldom be present in the original program,
+but it may be the result of earlier optimizations, such as
+copy propagation.</p>
+
+<p>Live-variable information is passed to other phases via
+messages in the EM code. Live/dead messages are generated at
+points in the EM text where variables become dead or live.
+This information is especially useful for the Register
+Allocation phase.</p>
+<a name="12.2. Implementation"></a>
+<h2>12.2. Implementation</h2>
+
+<p>The implementation uses algorithm 14.6 of. [Aho78a]
+First two sets DEF and USE are computed for every basic
+block b:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>DEF(b)</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>the set of all variables that are assigned a value in b
+before being used</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>USE(b)</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>the set of all variables that may be used in b before
+being changed.</p>
+</td>
+</table>
+
+<p>(So variables that may, but need not, be used resp.
+changed via a procedure call or through a pointer are
+included in USE but not in DEF). The next step is to compute
+the sets IN and OUT :</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>IN[b]</p>
+</td>
+<td width="8%"></td>
+<td width="82%">
+
+<p>the set of all variables that are live at the beginning
+of b</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>OUT[b]</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>the set of all variables that are live at the end of
+b</p>
+</td>
+</table>
+
+<p>IN and OUT can be computed for all blocks simultaneously
+by solving the data flow equations:</p>
+<pre>     (1)   IN[b] = OUT[b] - DEF[b] + USE[b]
+     [2]   OUT[b] = IN[s1] + ... + IN[sn] ;
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>where SUCC[b] = {s1, ... , sn}</p>
+</table>
+
+<p>The equations are solved by a similar algorithm as for
+the Use Definition equations (see previous chapter).</p>
+
+<p>Finally, each basic block is visited in turn to remove
+its dead code and to emit the live/dead messages. Every
+basic block b is traversed from its last instruction
+backwards to the beginning of b. Initially, all variables
+that are dead at the end of b are marked dead. All others
+are marked live. If we come across an assignment to a
+variable X that was marked live, a live-message is put after
+the assignment and X is marked dead; if X was marked dead,
+the assignment may be removed, provided that the right hand
+side expression contains no side effects. If we come across
+a use of a variable X that was marked dead, a dead-message
+is put after the use and X is marked live. So at any point,
+the mark of X tells whether X is live or dead immediately
+before that point. A message is also generated at the start
+of a basic block for every variable that was live at the end
+of the (textually) previous block, but dead at the entry of
+this block, or v.v.</p>
+
+<p>Only local variables are considered. This significantly
+reduces the memory needed by this phase, eases the
+implementation and is hardly less efficient than considering
+all variables. (Note that it is very hard to prove that an
+assignment to a global variable is dead).</p>
+<a name="13. Register Allocation"></a>
+<h2>13. Register Allocation</h2>
+<a name="13.1. Introduction"></a>
+<h2>13.1. Introduction</h2>
+
+<p>The efficient usage of the general purpose registers of
+the target machine plays a key role in any optimizing
+compiler. This subject, often referred to as <i>Register
+Allocation</i>, has great impact on both the code generator
+and the optimizing part of such a compiler. The code
+generator needs registers for at least the evaluation of
+arithmetic expressions; the optimizer uses the registers to
+decrease the access costs of frequently used entities (such
+as variables). The design of an optimizing compiler must pay
+great attention to the cooperation of optimization, register
+allocation and code generation.</p>
+
+<p>Register allocation has received much attention in
+literature (see [Leve81a, Chai81a, Frei74a] and
+[Site79a]).</p>
+<a name="13.2. Usage of registers in ACK compilers"></a>
+<h2>13.2. Usage of registers in ACK compilers</h2>
+
+<p>We will first describe the major design decisions of the
+Amsterdam Compiler Kit, as far as they concern register
+allocation. Subsequently we will outline the role of the
+Global Optimizer in the register allocation process and the
+interface between the code generator and the optimizer.</p>
+<a name="13.2.1. Usage of registers without the intervention of the Global Optimizer"></a>
+<h2>13.2.1. Usage of registers without the intervention of the Global Optimizer</h2>
+
+<p>Registers are used for two purposes:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="88%">
+
+<p>for the evaluation of arithmetic expressions</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>to hold local variables, for the duration of the
+procedure they are local to.</p>
+</td>
+</table>
+
+<p>It is essential to note that no translation part of the
+compilers, except for the code generator, knows anything at
+all about the register set of the target computer. Hence all
+decisions about registers are ultimately made by the code
+generator. Earlier phases of a compiler can only
+<i>advise</i> the code generator.</p>
+
+<p>The code generator splits the register set into two: a
+fixed part for the evaluation of expressions (called
+<i>scratch</i> registers) and a fixed part to store local
+variables. This partitioning, which depends only on the
+target computer, significantly reduces the complexity of
+register allocation, at the penalty of some loss of code
+quality.</p>
+
+<p>The code generator has some (machine-dependent)
+knowledge of the access costs of memory locations and
+registers and of the costs of saving and restoring
+registers. (Registers are always saved by the <i>called</i>
+procedure). This knowledge is expressed in a set of
+procedures for each target machine. The code generator also
+knows how many registers there are and of which type they
+are. A register can be of type <i>pointer</i>, <i>floating
+point</i> or <i>general</i>.</p>
+
+<p>The front ends of the compilers determine which local
+variables may be put in a register; such a variable may
+never be accessed indirectly (i.e. through a pointer). The
+front end also determines the types and sizes of these
+variables. The type can be any of the register types or the
+type <i>loop variable</i>, which denotes a general-typed
+variable that is used as loop variable in a for-statement.
+All this information is collected in a <i>register
+message</i> in the EM code. Such a message is a pseudo EM
+instruction. This message also contains a <i>score</i>
+field, indicating how desirable it is to put this variable
+in a register. A front end may assign a high score to a
+variable if it was declared as a register variable (which is
+only possible in some languages, such as &quot;C&quot;). Any
+compiler phase before the code generator may change this
+score field, if it has reason to do so. The code generator
+bases its decisions on the information contained in the
+register message, most notably on the score.</p>
+
+<p>If the global optimizer is not used, the score fields
+are set by the Peephole Optimizer. This optimizer simply
+counts the number of occurrences of every local (register)
+variable and adds this count to the score provided by the
+front end. In this way a simple, yet quite effective
+register allocation scheme is achieved.</p>
+<a name="13.2.2. The role of the Global Optimizer"></a>
+<h2>13.2.2. The role of the Global Optimizer</h2>
+
+<p>The Global Optimizer essentially tries to improve the
+scheme outlined above. It uses the following principles for
+this purpose:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Entities are not always assigned a register for the
+duration of an entire procedure; smaller regions of the
+program text may be considered too.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>several variables may be put in the same register
+simultaneously, provided at most one of them is live at any
+point.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>besides local variables, other entities (such as
+constants and addresses of variables and procedures) may be
+put in a register.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="76%">
+
+<p>more accurate cost estimates are used.</p>
+</td>
+<td width="13%">
+</td>
+</table>
+
+<p>To perform its task, the optimizer must have some
+knowledge of the target machine.</p>
+<a name="13.2.3. The interface between the register allocator and the code generator"></a>
+<h2>13.2.3. The interface between the register allocator and the code generator</h2>
+
+<p>The RA phase of the optimizer must somehow be able to
+express its decisions. Such decisions may look like:
+&rsquo;put constant 1283 in a register from line 12 to line
+40&rsquo;. To be precise, RA must be able to tell the code
+generator to:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="74%">
+
+<p>initialize a register with some value</p>
+</td>
+<td width="15%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="64%">
+
+<p>update an entity from a register</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>replace all occurrences of an entity in a certain region
+of text by a reference to the register.</p>
+</td>
+</table>
+
+<p>At least three problems occur here: the code generator
+is only used to put local variables in registers, it only
+assigns a register to a variable for the duration of an
+entire procedure and it is not used to have some earlier
+compiler phase make all the decisions.</p>
+
+<p>All problems are solved by one mechanism, that involves
+no changes to the code generator. With every (non-scratch)
+register R that will be used in a procedure P, we associate
+a new variable T, local to P. The size of T is the same as
+the size of R. A register message is generated for T with an
+exceptionally high score. The scores of all original
+register messages are set to zero. Consequently, the code
+generator will always assign precisely those new variables
+to a register. If the optimizer wants to put some entity,
+say the constant 1283, in a register, it emits the code
+&quot;T := 1283&quot; and replaces all occurrences of
+&rsquo;1283&rsquo; by T. Similarly, it can put the address
+of a procedure in T and replace all calls to that procedure
+by indirect calls. Furthermore, it can put several different
+entities in T (and thus in R) during the lifetime of P.</p>
+
+<p>In principle, the code generated by the optimizer in
+this way would always be valid EM code, even if the
+optimizer would be presented a totally wrong description of
+the target computer register set. In practice, it would be a
+waste of data as well as text space to allocate memory for
+these new variables, as they will always be assigned a
+register (in the correct order of events). Hence, no memory
+locations are allocated for them. For this reason they are
+called pseudo local variables.</p>
+<a name="13.3. The register allocation phase"></a>
+<h2>13.3. The register allocation phase</h2>
+<a name="13.3.1. Overview"></a>
+<h2>13.3.1. Overview</h2>
+
+<p>The RA phase deals with one procedure at a time. For
+every procedure, it first determines which entities may be
+put in a register. Such an entity is called an <i>item</i>.
+For every item it decides during which parts of the
+procedure it might be assigned a register. Such a region is
+called a <i>timespan</i>. For any item, several (possibly
+overlapping) timespans may be considered. A pair
+(item,timespan) is called an <i>allocation</i>. If the items
+of two allocations are both live at some point of time in
+the intersections of their timespans, these allocations are
+said to be <i>rivals</i> of each other, as they cannot be
+assigned the same register. The rivals-set of every
+allocation is computed. Next, the gains of assigning a
+register to an allocation are estimated, for every
+allocation. With all this information, decisions are made
+which allocations to store in which registers
+(<i>packing</i>). Finally, the EM text is transformed to
+reflect these decisions.</p>
+<a name="13.3.2. The item recognition subphase"></a>
+<h2>13.3.2. The item recognition subphase</h2>
+
+<p>RA tries to put the following entities in a
+register:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>a local variable for which a register message was
+found</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the address of a local variable for which no register
+message was found</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="64%">
+
+<p>the address of a global variable</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p>the address of a procedure</p>
+</td>
+<td width="37%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="38%">
+
+<p>a numeric constant.</p>
+</td>
+<td width="51%">
+</td>
+</table>
+
+<p>Only the <i>address</i> of a global variable may be put
+in a register, not the variable itself. This approach avoids
+the very complex problems that would be caused by procedure
+calls and indirect pointer references (see [Aho78a sections
+14.7 and 14.8] and [Spil71a]). Still, on most machines
+accessing a global variable using indirect addressing
+through a register is much cheaper than accessing it via its
+address. Similarly, if the address of a procedure is put in
+a register, the procedure can be called via an indirect
+call.</p>
+
+<p>With every item we associate a register type. This type
+is</p>
+<pre>     for local variables: the type contained in the register message
+     for addresses of variables and procedures: the pointer type
+     for constants: the general type
+</pre>
+
+<p>An entity other than a local variable is not taken to be
+an item if it is used only once within the current
+procedure.</p>
+
+<p>An item is said to be <i>live</i> at some point of the
+program text if its value may be used before it is changed.
+As addresses and constants are never changed, all items but
+local variables are always live. The region of text during
+which a local variable is live is determined via the
+live/dead messages generated by the Live Variable analysis
+phase of the Global Optimizer.</p>
+<a name="13.3.3. The allocation determination subphase"></a>
+<h2>13.3.3. The allocation determination subphase</h2>
+
+<p>If a procedure has more items than registers, it may be
+advantageous to put an item in a register only during those
+parts of the procedure where it is most heavily used. Such a
+part will be called a timespan. With every item we may
+associate a set of timespans. If two timespans of an item
+overlap, at most one of them may be granted a register, as
+there is no use in putting the same item in two registers
+simultaneously. If two timespans of an item are distinct,
+both may be chosen; the item will possibly be put in two
+different registers during different parts of the procedure.
+The timespan may also consist of the whole procedure.</p>
+
+<p>A list of (item,timespan) pairs (allocations) is build,
+which will be the input to the decision making subphase of
+RA (packing subphase). This allocation list is the main data
+structure of RA. The description of the remainder of RA will
+be in terms of allocations rather than items. The phrase
+&quot;to assign a register to an allocation&quot; means
+&quot;to assign a register to the item of the allocation for
+the duration of the timespan of the allocation&quot;.
+Subsequent subphases will add more information to this
+list.</p>
+
+<p>Several factors must be taken into account when a
+timespan for an item is constructed:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>At any <i>entry point</i> of the timespan where the item
+is live, the register must be initialized with the item</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>At any exit point of the timespan where the item is
+live, the item must be updated.</p>
+</td>
+</table>
+
+<p>In order to decrease these costs, we will only consider
+timespans with one entry point and no live exit points.</p>
+<a name="13.3.4. The rivals computation subphase"></a>
+<h2>13.3.4. The rivals computation subphase</h2>
+
+<p>As stated before, several different items may be put in
+the same register, provided they are not live
+simultaneously. For every allocation we determine the
+intersection of its timespan and the lifetime of its item
+(i.e. the part of the procedure during which the item is
+live). The allocation is said to be busy during this
+intersection. If two allocations are ever busy
+simultaneously they are said to be rivals of each other. The
+rivals information is added to the allocation list.</p>
+<a name="13.3.5. The profits computation subphase"></a>
+<h2>13.3.5. The profits computation subphase</h2>
+
+<p>To make good decisions, the packing subphase needs to
+know which allocations can be assigned the same register
+(rivals information) and how much is gained by granting an
+allocation a register.</p>
+
+<p>Besides the gains of using a register instead of an
+item, two kinds of overhead costs must be taken into
+account:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the register must be initialized with the item</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the register must be saved at procedure entry and
+restored at procedure exit.</p>
+</td>
+</table>
+
+<p>The latter costs should not be due to a single
+allocation, as several allocations can be assigned the same
+register. These costs are dealt with after packing has been
+done. They do not influence the decisions of the packing
+algorithm, they may only undo them.</p>
+
+<p>The actual profits consist of improvements of execution
+time and code size. As the former is far more difficult to
+estimate , we will discuss code size improvements first.</p>
+
+<p>The gains of putting a certain item in a register
+depends on how the item is used. Suppose the item is a
+pointer variable. On machines that do not have a
+double-indirect addressing mode, two instructions are needed
+to dereference the variable if it is not in a register, but
+only one if it is put in a register. If the variable is not
+dereferenced, but simply copied, one instruction may be
+sufficient in both cases. So the gains of putting a pointer
+variable in a register are higher if the variable is
+dereferenced often.</p>
+
+<p>To make accurate estimates, detailed knowledge of the
+target machine and of the code generator would be needed.
+Therefore, a simplification has been made that substantially
+limits the amount of target machine information that is
+needed. The estimation of the number of bytes saved does not
+take into account how an item is used. Rather, an average
+number is used. So these gains are computed as follows:</p>
+<pre>     #bytes_saved = #occurrences * gains_per_occurrence
+</pre>
+
+<p>The number of occurrences is derived from the EM code.
+Note that this is not exact either, as there is no
+one-to-one correspondence between occurrences in the EM code
+and in the assembler code.</p>
+
+<p>The gains of one occurrence depend on:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p>the type of the item</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p>the size of the item</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="48%">
+
+<p>the type of the register</p>
+</td>
+<td width="41%">
+</td>
+</table>
+
+<p>and for local variables and addresses of local
+variables:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p>the type of the local variable</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="88%">
+
+<p>the offset of the variable in the stackframe</p>
+</td>
+<td width="1%">
+</td>
+</table>
+
+<p>For every allocation we try two types of registers: the
+register type of the item and the general register type.
+Only the type with the highest profits will subsequently be
+used. This type is added to the allocation information.</p>
+
+<p>To compute the gains, RA uses a machine-dependent table
+that is read from a machine descriptor file. By means of
+this table the number of bytes saved can be computed as a
+function of the five properties.</p>
+
+<p>The costs of initializing a register with an item is
+determined in a similar way. The cost of one initialization
+is also obtained from the descriptor file. Note that there
+can be at most one initialization for any allocation.</p>
+
+<p>To summarize, the number of bytes a certain allocation
+would save is computed as follows:</p>
+
+<p align=center><img src="grohtml-1027239.png"></p>
+
+<p>It is inherently more difficult to estimate the
+execution time saved by putting an item in a register,
+because it is impossible to predict how many times an item
+will be used dynamically. If an occurrence is part of a
+loop, it may be executed many times. If it is part of a
+conditional statement, it may never be executed at all. In
+the latter case, the speed of the program may even get worse
+if an initialization is needed. As a clear example, consider
+the piece of &quot;C&quot; code in Fig. 13.1.</p>
+<pre>     switch(expr) {
+           case 1:  p(); break;
+           case 2:  p(); p(); break;
+           case 3:  p(); break;
+           default: break;
+     }
+
+
+     Fig. 13.1 A &quot;C&quot; switch statement
+</pre>
+
+<p>Lots of bytes may be saved by putting the address of
+procedure p in a register, as p is called four times
+(statically). Dynamically, p will be called zero, one or two
+times, depending on the value of the expression.</p>
+
+<p>The optimizer uses the following strategy for optimizing
+execution time:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>try to put items in registers during <i>loops</i>
+first</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>always keep the initializing code outside the loop</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>if an item is not used in a loop, do not put it in a
+register if the initialization costs may be higher than the
+gains</p>
+</td>
+</table>
+
+<p>The latter condition can be checked by determining the
+minimal number of usages (dynamically) of the item during
+the procedure, via a shortest path algorithm. In the example
+above, this minimal number is zero, so the address of p is
+not put in a register.</p>
+
+<p>The costs of one occurrence is estimated as described
+above for the code size. The number of dynamic occurrences
+is guessed by looking at the loop nesting level of every
+occurrence. If the item is never used in a loop, the minimal
+number of occurrences is used. From these facts, the
+execution time improvement is assessed for every
+allocation.</p>
+<a name="13.3.6. The packing subphase"></a>
+<h2>13.3.6. The packing subphase</h2>
+
+<p>The packing subphase takes as input the allocation list
+and outputs a description of which allocations should be put
+in which registers. So it is essentially the decision making
+part of RA.</p>
+
+<p>The packing system tries to assign a register to
+allocations one at a time, in some yet to be defined order.
+For every allocation A, it first checks if there is a
+register (of the right type) that is already assigned to one
+or more allocations, none of which are rivals of A. In this
+case A is assigned the same register. Else, A is assigned a
+new register, if one exists. A table containing the number
+of free registers for every type is maintained. It is
+initialized with the number of non-scratch registers of the
+target computer and updated whenever a new register is
+handed out. The packing algorithm stops when no more
+allocations can or need be assigned a register.</p>
+
+<p>After an allocation A has been packed, all allocations
+with non-disjunct timespans (including A itself) are removed
+from the allocation list.</p>
+
+<p>In case the number of items exceeds the number of
+registers, it is important to choose the most profitable
+allocations. Due to the possibility of having several
+allocations occupying the same register, this problem is
+quite complex. Our packing algorithm uses simple heuristic
+rules and avoids any combinatorial search. It has distinct
+rules for different costs measures.</p>
+
+<p>If object code size is the most important factor, the
+algorithm is greedy and chooses allocations in decreasing
+order of their profits attribute. It does not take into
+account the fact that other allocations may be passed over
+because of this decision.</p>
+
+<p>If execution time is at prime stake, the algorithm first
+considers allocations whose timespans consist of loops.
+After all these have been packed, it considers the remaining
+allocations. Within the two subclasses, it considers
+allocations with the highest profits first. When assigning a
+register to an allocation with a loop as timespan, the
+algorithm checks if the item has already been put in a
+register during another loop. If so, it tries to use the
+same register for the new allocation. After all packing has
+been done, it checks if the item has always been assigned
+the same register (although not necessarily during all
+loops). If so, it tries to put the item in that register
+during the entire procedure. This is possible if the
+allocation (item,whole_procedure) is not a rival of any
+allocation with a different item that has been assigned to
+the same register. Note that this approach is essentially
+&rsquo;bottom up&rsquo;, as registers are first assigned
+over small regions of text which are later collapsed into
+larger regions. The advantage of this approach is the fact
+that the decisions for one loop can be made independently of
+all other loops.</p>
+
+<p>After the entire packing process has been completed, we
+compute for each register how much is gained in using this
+register, by simply adding the net profits of all
+allocations assigned to it. This total yield should outweigh
+the costs of saving/restoring the register at procedure
+entry/exit. As most modern processors (e.g. 68000, Vax) have
+special instructions to save/restore several registers, the
+differential costs of saving one extra register are by no
+means constant. The costs are read from the machine
+descriptor file and compared to the total yields of the
+registers. As a consequence of this analysis, some
+allocations may have their registers taken away.</p>
+<a name="13.3.7. The transformation subphase"></a>
+<h2>13.3.7. The transformation subphase</h2>
+
+<p>The final subphase of RA transforms the EM text
+according to the decisions made by the packing system. It
+traverses the text of the currently optimized procedure and
+changes all occurrences of items at points where they are
+assigned a register. It also clears the score field of the
+register messages for normal local variables and emits
+register messages with a very high score for the pseudo
+locals. At points where registers have to be initialized
+with items, it generates EM code to do so. Finally it tries
+to decrease the size of the stackframe of the procedure by
+looking at which local variables need not be given memory
+locations.</p>
+<a name="13.4. Source files of RA"></a>
+<h2>13.4. Source files of RA</h2>
+
+<p>The sources of RA are in the following files and
+packages:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>ra.h:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>declarations of global variables and data structures</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>ra.c:</p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>the routine main; initialization of target
+machine-dependent tables</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>items:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>a routine to build the list of items of one procedure;
+routines to manipulate items</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>lifetime:</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>contains a subroutine that determines when items are
+live/dead</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>alloclist:</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>contains subroutines that build the initial allocations
+list and that compute the rivals sets.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>profits:</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>contains a subroutine that computes the profits of the
+allocations and a routine that determines the costs of
+saving/restoring registers</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>pack:</p>
+</td>
+<td width="18%"></td>
+<td width="58%">
+
+<p>contains the packing subphase</p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>xform:</p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>contains the transformation subphase</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>interval:</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>contains routines to manipulate intervals of time</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>aux:</p>
+</td>
+<td width="20%"></td>
+<td width="54%">
+
+<p>contains auxiliary routines</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<a name="14. Compact assembly generation"></a>
+<h2>14. Compact assembly generation</h2>
+<a name="14.1. Introduction"></a>
+<h2>14.1. Introduction</h2>
+
+<p>The &quot;Compact Assembly generation phase&quot; (CA)
+transforms the intermediate code of the optimizer into EM
+code in Compact Assembly Language (CAL) format. In the
+intermediate code, all program entities (such as procedures,
+labels, global variables) are denoted by a unique
+identifying number (see 3.5). In the CAL output of the
+optimizer these numbers have to be replaced by normal
+identifiers (strings). The original identifiers of the input
+program are used whenever possible. Recall that the IC phase
+generates two files that can be used to map unique
+identifying numbers to procedure names and global variable
+names. For instruction labels CA always generates new names.
+The reasons for doing so are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>instruction labels are only visible inside one
+procedure, so they can not be referenced in other
+modules</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the names are not very suggestive anyway, as they must
+be integer numbers</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the optimizer considerably changes the control structure
+of the program, so there is really no one to one mapping of
+instruction labels in the input and the output program.</p>
+</td>
+</table>
+
+<p>As the optimizer combines all input modules into one
+module, visibility problems may occur. Two modules M1 and M2
+can both define an identifier X (provided that X is not
+externally visible in any of these modules). If M1 and M2
+are combined into one module M, two distinct entities with
+the same name would exist in M, which is not allowed.
+[Tane83a, section 11.1.4.3] In these cases, CA invents a new
+unique name for one of the entities.</p>
+<a name="14.2. Implementation"></a>
+<h2>14.2. Implementation</h2>
+
+<p>CA first reads the files containing the procedure and
+global variable names and stores the names in two tables. It
+scans these tables to make sure that all names are
+different. Subsequently it reads the EM text, one procedure
+at a time, and outputs it in CAL format. The major part of
+the code that does the latter transformation is adapted from
+the EM Peephole Optimizer.</p>
+
+<p>The main problem of the implementation of CA is to
+assure that the visibility rules are obeyed. If an
+identifier must be externally visible (i.e. it was
+externally visible in the input program) and the identifier
+is defined (in the output program) before being referenced,
+an EXA or EXP pseudo must be generated for it. (Note that
+the optimizer may change the order of definitions and
+references, so some pseudos may be needed that were not
+present in the input program). On the other hand, an
+identifier may be only internally visible. If such an
+identifier is referenced before being defined, an INA or INP
+pseudo must be emitted prior to its first reference.</p>
+<a name="Acknowledgements"></a>
+<h2>Acknowledgements</h2>
+
+<p>The author would like to thank Andy Tanenbaum for his
+guidance, Duk Bekema for implementing the Common
+Subexpression Elimination phase and writing the initial
+documentation of that phase, Dick Grune for reading the
+manuscript of this report and Ceriel Jacobs, Ed Keizer,
+Martin Kersten, Hans van Staveren and the members of the
+S.T.W. user&rsquo;s group for their interest and
+assistance.</p>
+<a name="References"></a>
+<h2>References</h2>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>a.</p>
+</td>
+<td width="95%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>b.</p>
+</td>
+<td width="95%">
+</td>
+</table>
+
+<p>Aho74a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.V. Aho, J.E. Hopcroft, and J.D. Ullman, <i>The Design
+and Analysis of Computer Algorithms,</i> Addison-Wesley,
+Reading, Massachusetts (1974).</p>
+</td>
+</table>
+
+<p>Aho78a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.V. Aho and J.D. Ullman, <i>Principles of compiler
+design,</i> Addison-Wesley, Reading, Massachusetts
+(1978).</p>
+</td>
+</table>
+
+<p>Alle81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>F.E. Allen, J. Cocke, and K. Kennedy, &ldquo;Reduction of
+Operator Strength&rdquo; in <i>Program Flow Analysis,</i>
+ed. S.S. Muchnick and D. Jones, Prentice-Hall, Englewood
+Cliffs, N.J. (1981).</p>
+</td>
+</table>
+
+<p>Ankl82a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>P. Anklam, D. Cutler, R. Heinen, and M. MacLaren,
+<i>Engineering a compiler: Vax-11 code generation and
+optimization,</i> Digital Equipment Corporation (1982).</p>
+</td>
+</table>
+
+<p>Bal86a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>H.E. Bal and A.S. Tanenbaum, &ldquo;Language- and
+Machine-independent Global Optimization on Intermediate
+Code,&rdquo; <i>Computer Languages,</i> 11, 2, pp. 105-121
+(April 1986).</p>
+</td>
+</table>
+
+<p>Ball79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.E. Ball, &ldquo;Predicting the Effects of Optimization
+on a Procedure Body,&rdquo; <i>SIGPLAN Notices,</i> 14, 8,
+pp. 214-220 (August 1979).</p>
+</td>
+</table>
+
+<p>Cart77a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.L. Carter, &ldquo;A Case Study of a New Code Generation
+Technique for Compilers,&rdquo; <i>CACM,</i> 20, 12, pp.
+914-920 (December 1977).</p>
+</td>
+</table>
+
+<p>Cart82a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>L.R. Carter, <i>An analysis of Pascal Programs,</i> UMI
+Research Press, Ann Arbor, Michigan (1982).</p>
+</td>
+</table>
+
+<p>Chai81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>G.J. Chaitin, M.A. Auslander, A.K. Chandra, J. Cocke,
+M.E. Hopkins, and P.W. Markstein, &ldquo;Register Allocation
+via Coloring,&rdquo; <i>Computer Languages,</i> 6, 1, pp.
+47-57 (January 1981).</p>
+</td>
+</table>
+
+<p>Cock77a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J. Cocke and K. Kennedy, &ldquo;An algorithm for
+Reduction of Operator Strength,&rdquo; <i>CACM,</i> 20, 11,
+pp. 850-856 (November 1977).</p>
+</td>
+</table>
+
+<p>Davi81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.W. Davidson, &ldquo;Simplifying Code Generation Through
+Peephole Optimization,&rdquo; Ph.D. thesis, Dept. of
+Computer Science, Univ. of Arizona (December 1981).</p>
+</td>
+</table>
+
+<p>Faim80a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R.N. Faiman and A.A. Kortesoja, &ldquo;An Optimizing
+Pascal Compiler,&rdquo; <i>IEEE Trans. on Softw. Eng.,</i>
+6, 6, pp. 512-518 (November 1980).</p>
+</td>
+</table>
+
+<p>Frei74a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R.A. Freiburghouse, &ldquo;Register Allocation Via Usage
+Counts,&rdquo; <i>CACM,</i> 17, 11, pp. 638-642 (November
+1974).</p>
+</td>
+</table>
+
+<p>Freu83a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>S.M. Freudenberger and J.T. Schwartz, &ldquo;Experience
+with the SETL Optimizer,&rdquo; <i>TOPLAS,</i> 5, 1, pp.
+26-45 (Januari 1983).</p>
+</td>
+</table>
+
+<p>Harr79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>W.H. Harrison, &ldquo;A New Strategy for Code Generation
+- the General-Purpose Optimizing Compiler,&rdquo; <i>IEEE
+Trans. on Softw. Eng.,</i> 5, 4, pp. 367-373 (July
+1979).</p>
+</td>
+</table>
+
+<p>Ichb83a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.D. Ichbiah, &ldquo;Ada Programming Language - MILITARY
+STANDARD,&rdquo; ANSI/MIL-STD-1815A, U.S. Department of
+Defense (22 January 1983).</p>
+</td>
+</table>
+
+<p>Ichb79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.D. Ichbiah, &ldquo;Rationale for the Design of the Ada
+Programming Language,&rdquo; <i>SIGPLAN Notices,</i> 14, 6
+(June 1979).</p>
+</td>
+</table>
+
+<p>John81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>S.C. Johnson and D.M. Ritchie, <i>The C Language Calling
+Sequence,</i> Bell Laboratories, Murray Hill, New Jersey
+(September 1981).</p>
+</td>
+</table>
+
+<p>Katk73a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>G.R. Katkus, &ldquo;A study of selective optimization
+techniques,&rdquo; Ph.D. Thesis, University of Southern
+California (1973).</p>
+</td>
+</table>
+
+<p>Kenn81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>K. Kennedy, &ldquo;A Survey of Data Flow Analysis
+Techniques&rdquo; in <i>Program Flow Analysis,</i> ed. S.S.
+Muchnick and D. Jones, Prentice-Hall, Englewood Cliffs
+(1981).</p>
+</td>
+</table>
+
+<p>Kern79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B.W. Kernighan and M.D. McIlroy, <i>Unix
+programmer&rsquo;s manual, Seventh Edition,</i> 1, Bell
+Laboratories, Murray Hill, New Jersey (January 1979).</p>
+</td>
+</table>
+
+<p>Kirc83a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>W. Kirchgaesner, J. Uhl, G. Winterstein, G. Goos, M.
+Dausmann, and S. Drossopoulou, <i>An Optimizing Ada
+Compiler,</i> Institut fur Informatik II, Universitat
+Karlsruhe (February 1983).</p>
+</td>
+</table>
+
+<p>Leng79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>T. Lengauer and R.E. Tarjan, &ldquo;A Fast Algorithm for
+Finding Dominators in a Flowgraph,&rdquo; <i>TOPLAS,</i> 1,
+1, pp. 121-141 (July 1979).</p>
+</td>
+</table>
+
+<p>Leve81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B.W. Leverett, &ldquo;Register Allocation in Optimizing
+Compilers,&rdquo; Ph.D. Thesis, CMU-CS-81-103,
+Carnegie-Mellon University, Pittsburgh (February 1981).</p>
+</td>
+</table>
+
+<p>Leve79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B.W. Leverett, R.G.G Cattell, S.O. Hobbs, J.M. Newcomer,
+A.H. Reiner, B.R. Schatz, and W.A. Wulf, &ldquo;An Overview
+of the Production-Quality Compiler-Compiler Project,&rdquo;
+CMU-CS-79-105, Carnegie-Mellon University, Pittsburgh
+(1979).</p>
+</td>
+</table>
+
+<p>Leve80a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B.W. Leverett, R.G.G Cattell, S.O. Hobbs, J.M. Newcomer,
+A.H. Reiner, B.R. Schatz, and W.A. Wulf, &ldquo;An Overview
+of the Production-Quality Compiler-Compiler Project,&rdquo;
+<i>IEEE Computer,</i> 13, 8, pp. 38-49 (August 1980).</p>
+</td>
+</table>
+
+<p>Lowr69a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>E.S. Lowry and C.W. Medlock, &ldquo;Object Code
+Optimization,&rdquo; <i>CACM,</i> 12, 1, pp. 13-22 (Januari
+1969).</p>
+</td>
+</table>
+
+<p>Mint79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R.J. Mintz, G.A. Fisher, and M. Sharir, &ldquo;The design
+of a global optimizer,&rdquo; <i>SIGPLAN Notices,</i> 14, 9,
+pp. 226-234 (September 1979).</p>
+</td>
+</table>
+
+<p>More79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>E. Morel and C. Renvoise, &ldquo;Global Optimization by
+Suppression of Partial Redundancies,&rdquo; <i>CACM,</i> 22,
+2, pp. 96-103 (February 1979).</p>
+</td>
+</table>
+
+<p>Perk79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>D.R. Perkins and R.L. Sites, &ldquo;Machine-independent
+Pascal code optimization,&rdquo; <i>SIGPLAN Notices,</i> 14,
+8, pp. 201-207 (August 1979).</p>
+</td>
+</table>
+
+<p>Phot81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>D.S. Photopoulos, &ldquo;Optimal mixed code generation
+for microcomputers,&rdquo; Ph.D. Thesis, Northeastern
+University (1981).</p>
+</td>
+</table>
+
+<p>Poel72a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>W.L. van der Poel, <i>The Programming Languages LISP and
+TRAC,</i> Technische Hogeschool Delft, Delft (1972).</p>
+</td>
+</table>
+
+<p>Prab80a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B. Prabhala and R. Sethi, &ldquo;Efficient Computation of
+Expressions with Common Subexpressions,&rdquo; <i>JACM,</i>
+27, 1, pp. 146-163 (Januari 1980).</p>
+</td>
+</table>
+
+<p>Purd72a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>P.W. Purdom and E.F. Moore, &ldquo;Immediate
+Predominators in a Directed Graph,&rdquo; <i>CACM,</i> 15,
+8, pp. 777-778 (August 1972).</p>
+</td>
+</table>
+
+<p>Ritc78a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>D.M. Ritchie, <i>The C Programming Language - Reference
+Manual,</i> Bell Laboratories, Murray Hill, New Jersey
+(1978).</p>
+</td>
+</table>
+
+<p>Sche77a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R.W. Scheifler, &ldquo;An Analysis of Inline Substitution
+for a Structured Programming Language,&rdquo; <i>CACM,</i>
+20, 9, pp. 647-654 (September 1977).</p>
+</td>
+</table>
+
+<p>Seth70a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R. Sethi and J.D. Ullman, &ldquo;The Generation of
+Optimal Code for Arithmetic Expressions,&rdquo; <i>JACM,</i>
+17, 4, pp. 715-728 (October 1970).</p>
+</td>
+</table>
+
+<p>Shaf78a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>J.B. Shaffer, &ldquo;Automatic subroutine generation in
+an optimizing compiler,&rdquo; Ph.D. Thesis, University of
+Maryland (1978).</p>
+</td>
+</table>
+
+<p>Site79a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>R.L. Sites, &ldquo;Machine-independent register
+allocation,&rdquo; <i>SIGPLAN Notices,</i> 14, 8, pp.
+221-225 (August 1979).</p>
+</td>
+</table>
+
+<p>Spil71a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>T.C. Spillman, &ldquo;Exposing side-effects in a PL/I
+optimizing compiler&rdquo; in <i>Information Processing
+1971,</i> pp. 376-381, North-Holland Publishing Company,
+Amsterdam (1971).</p>
+</td>
+</table>
+
+<p>Tane83a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, H. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;Description of a machine architecture for
+use with block structured languages,&rdquo; Rapport nr
+IR-81, Vrije Universiteit, Amsterdam (August 1983).</p>
+</td>
+</table>
+
+<p>Tane81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, H. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;A Practical Toolkit for Making Portable
+Compilers,&rdquo; Rapport nr IR-74, Vrije Universiteit,
+Amsterdam (October 1981).</p>
+</td>
+</table>
+
+<p>Tane83b.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, H. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;A Practical Toolkit for Making Portable
+Compilers,&rdquo; <i>CACM,</i> 26, 9, pp. 654-660 (September
+1983).</p>
+</td>
+</table>
+
+<p>Wulf75a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>W.A. Wulf, R.K. Johnsson, C.B. Weinstock, S.O. Hobbs, and
+C.M. Geschke, <i>The Design of an Optimizing Compiler,</i>
+American Elsevier Publishing Company, New York (1975).</p>
+</td>
+</table>
+
+<p>Wulf80a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>W.M. Wulf, &ldquo;PQCC: A Machine-Relative Compiler
+Technology,&rdquo; CMU-CS-80-144, Carnegie-Mellon
+University, Pittsburgh (25 september 1980).</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/ego.pdf b/doc/tack/ego.pdf
new file mode 100644 (file)
index 0000000..e69f36d
Binary files /dev/null and b/doc/tack/ego.pdf differ
diff --git a/doc/tack/em.html b/doc/tack/em.html
new file mode 100644 (file)
index 0000000..826c002
--- /dev/null
@@ -0,0 +1,12846 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:05 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title></title>
+</head>
+<body>
+
+<hr>
+
+<p align=center>DESCRIPTION OF A MACHINE<br>
+ARCHITECTURE FOR USE WITH<br>
+BLOCK STRUCTURED LANGUAGES</p>
+
+<p align=center>Andrew S. Tanenbaum<br>
+Hans van Staveren<br>
+Ed G. Keizer<br>
+Johan W. Stevenson*</p>
+
+<p align=center>August 1983</p>
+
+<p align=center>Informatica Rapport IR-81</p>
+
+<p align=center>Abstract</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>EM is a family of intermediate languages designed for
+producing portable compilers. A program called <b>front
+end</b> translates source programs to EM. Another program,
+<b>back end</b>, translates EM to the assembly language of
+the target machine. Alternatively, the EM program can be
+assembled to a highly efficient binary format for
+interpretation. This document describes the EM languages in
+detail.</p>
+<!-- INDENTATION -->
+<p>* Present affiliation: NV Philips, Eindhoven</p></td>
+</table>
+
+<p>1</p>
+
+<p><b>1. INTRODUCTION</b></p>
+
+<p>EM is a family of intermediate languages designed for
+producing portable compilers. The general strategy is for a
+program called <b>front end</b> to translate the source
+program to EM. Another program, <b>back end</b>, translates
+EM to target assembly language. Alternatively, the EM code
+can be assembled to a binary form and interpreted. These
+considerations led to the following goals:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>1</p>
+</td>
+<td width="8%"></td>
+<td width="28%">
+
+<p>The design should allow translation to, or
+interpretation on, a wide range of existing machines. Design
+decisions should be delayed as far as possible and the
+implications of these decisions should be localized as much
+as possible.</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The current microcomputer technology offers 8, 16 and 32
+bit machines with various sizes of address space. EM should
+be flexible enough to be useful on most of these machines.
+The differences between the members of the EM family should
+only concern the wordsize and address space size.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>2</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>The architecture should ease the task of code generation
+for high level languages such as Pascal, C, Ada, Algol 68,
+BCPL.</p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>3</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>The instruction set used by the interpreter should be
+compact, to reduce the amount of memory needed for program
+storage, and to reduce the time needed to transmit programs
+over communication lines.</p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>3</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>It should be designed with microprogrammed
+implementations in mind; in particular, the use of many
+short fields within instruction opcodes should be avoided,
+because their extraction by the microprogram or conversion
+to other instruction formats is inefficient.</p>
+</td>
+<td width="59%">
+</td>
+</table>
+
+<p>The basic architecture is based on the concept of a
+stack. The stack is used for procedure return addresses,
+actual parameters, local variables, and arithmetic
+operations. There are several built-in object types, for
+example, signed and unsigned integers, floating point
+numbers, pointers and sets of bits. There are instructions
+to push and pop objects to and from the stack. The push and
+pop instructions are not typed. They only care about the
+size of the objects. For each built-in type there are
+reverse Polish type instructions that pop one or more
+objects from the top of the stack, perform an operation, and
+push the result back onto the stack. For all types except
+pointers, these instructions have the object size as
+argument.</p>
+
+<p>There are no visible general registers used for
+arithmetic operands etc. This is in contrast to most third
+generation computers, which usually have 8 or 16 general
+registers. The decision not to have a group of general
+registers was fully intentional, and follows W.L. Van der
+Poel&rsquo;s dictum that a machine should have 0, 1, or an
+infinite number of any feature. General registers have two
+primary uses: to hold intermediate results of complicated
+expressions, e.g.</p>
+<pre>     ((a*b + c*d)/e + f*g/h) * i
+</pre>
+
+<p>and to hold local variables.</p>
+
+<p>Various studies have shown that the average expression
+has fewer than two operands, making the former use of
+registers of doubtful value. The present trend toward
+structured programs consisting of many small procedures
+greatly reduces the value of registers to hold local
+variables because the large number of procedure calls
+implies a large overhead in saving and restoring the
+registers at every call.</p>
+
+<p>Although there are no general purpose registers, there
+are a few internal registers with specific functions as
+follows:</p>
+
+<p align=center><img src="grohtml-97441.png"></p>
+
+<p>Furthermore, reverse Polish code is much easier to
+generate than multi-register machine code, especially if
+highly efficient code is desired. When translating to
+assembly language the back end can make good use of the
+target machine&rsquo;s registers. An EM machine can achieve
+high performance by keeping part of the stack in high speed
+storage (a cache or microprogram scratchpad memory) rather
+than in primary memory.</p>
+
+<p>Again according to van der Poel&rsquo;s dictum, all EM
+instructions have zero or one argument. We believe that
+instructions needing two arguments can be split into two
+simpler ones. The simpler ones can probably be used in other
+circumstances as well. Moreover, these two instructions
+together often have a shorter encoding than the single
+instruction before.</p>
+
+<p>This document describes EM at three different levels:
+the abstract level, the assembly language level and the
+machine language level.<br>
+The most important level is that of the abstract EM
+architecture. This level deals with the basic design issues.
+Only the functional capabilities of instructions are
+relevant, not their format or encoding. Most chapters of
+this document refer to the abstract level and it is
+explicitly stated whenever another level is described.<br>
+The assembly language is intended for the compiler writer.
+It presents a more or less orthogonal instruction set and
+provides symbolic names for data. Moreover, it facilitates
+the linking of separately compiled &rsquo;modules&rsquo;
+into a single program by providing several
+pseudoinstructions.<br>
+The machine language is designed for interpretation with a
+compact program text and easy decoding. The binary
+representation of the machine language instruction set is
+far from orthogonal. Frequent instructions have a short
+opcode. The encoding is fully byte oriented. These bytes do
+not contain small bit fields, because bit fields would slow
+down decoding considerably.</p>
+
+<p>A common use for EM is for producing portable (cross)
+compilers. When used this way, the compilers produce EM
+assembly language as their output. To run the compiled
+program on the target machine, the back end, translates the
+EM assembly language to the target machine&rsquo;s assembly
+language. When this approach is used, the format of the EM
+machine language instructions is irrelevant. On the other
+hand, when writing an interpreter for EM machine language
+programs, the interpreter must deal with the machine
+language and not with the symbolic assembly language.</p>
+
+<p>As mentioned above, the current microcomputer technology
+offers 8, 16 and 32 bit machines with address spaces ranging
+from 2 <small>16</small> to 2 <small>32</small> bytes.
+Having one size of pointers and integers restricts the
+usefulness of the language. We decided to have a different
+language for each combination of word and pointer size. All
+languages offer the same instruction set and differ only in
+memory alignment restrictions and the implicit size assumed
+in several instructions. The languages differ slightly for
+the different size combinations. For example: the size of
+any object on the stack and alignment restrictions. The
+wordsize is restricted to powers of 2 and the pointer size
+must be a multiple of the wordsize. Almost all programs
+handling EM will be parametrized with word and pointer
+size.</p>
+
+<p>2</p>
+
+<p><b>2. MEMORY</b></p>
+
+<p>The EM machine has two distinct address spaces, one for
+instructions and one for data. The data space is divided up
+into 8-bit bytes. The smallest addressable unit is a byte.
+Bytes are numbered consecutively from 0 to some maximum. All
+sizes in EM are expressed in bytes.</p>
+
+<p>Some EM instructions can transfer objects containing
+several bytes to and/or from memory. The size of all objects
+larger than a word must be a multiple of the wordsize. The
+size of all objects smaller than a word must be a divisor of
+the wordsize. For example: if the wordsize is 2 bytes,
+objects of the sizes 1, 2, 4, 6,... are allowed. The address
+of such an object is the lowest address of all bytes it
+contains. For objects smaller than the wordsize, the address
+must be a multiple of the object size. For all other objects
+the address must be a multiple of the wordsize. For example,
+if an instruction transfers a 4-byte object to memory at
+location <i>m</i> and the wordsize is 2, <i>m</i> must be a
+multiple of 2 and the bytes at locations <i>m</i>,
+<i>m</i>+1,<i>m</i>+2 and <i>m</i>+3 are overwritten.</p>
+
+<p>The size of almost all objects in EM is an integral
+number of words. Only two operations are allowed on objects
+whose size is a divisor of the wordsize: push it onto the
+stack and pop it from the stack. The addressing of these
+objects in memory is always indirect. If such a small object
+is pushed onto the stack it is assumed to be a small integer
+and stored in the least significant part of a word. The rest
+of the word is cleared to zero, although EM provides a way
+to sign-extend a small integer. Popping a small object from
+the stack removes a word from the stack, stores the least
+significant byte(s) of this word in memory and discards the
+rest of the word.</p>
+
+<p>The format of pointers into both address spaces is
+explicitly undefined. The size of a pointer, however, is
+fixed for a member of EM, so that the compiler writer knows
+how much storage to allocate for a pointer.</p>
+
+<p>A minor problem is raised by the undefined pointer
+format. Some languages, notably Pascal, require a special,
+otherwise illegal, pointer value to represent the nil
+pointer. The current Pascal-VU compiler uses the integer
+value 0 as nil pointer. This value is also used by many C
+programs as a normally impossible address. A better solution
+would be to have a special instruction loading an illegal
+pointer value, but it is hard to imagine an implementation
+for which the current solution is inadequate, especially
+because the first word in the EM data space is special and
+probably not the target of any pointer.</p>
+
+<p>The next two chapters describe the EM memory in more
+detail. One describes the instruction address space, the
+other the data address space.</p>
+
+<p>A design goal of EM has been to allow its implementation
+on a wide range of existing machines, as well as allowing a
+new one to be built in hardware. To this extent we have
+tried to minimize the demands of EM on the memory structure
+of the target machine. Therefore, apart from the logical
+partitioning, EM memory is divided into
+&rsquo;fragments&rsquo;. A fragment consists of consecutive
+machine words and has a base address and a size. Pointer
+arithmetic is only defined within a fragment. The only
+exception to this rule is comparison with the null pointer.
+All fragments must be word aligned.</p>
+
+<p>3</p>
+
+<p><b>3. INSTRUCTION ADDRESS SPACE</b></p>
+
+<p>The instruction space of the EM machine contains the
+code for procedures. Tables necessary for the execution of
+this code, for example, procedure descriptor tables, may
+also be present. The instruction space does not change
+during the execution of a program, so that it may be
+protected. No further restrictions to the instruction
+address space are necessary for the abstract and assembly
+language level.</p>
+
+<p>Each procedure has a single entry point: the first
+instruction. A special type of pointer identifies a
+procedure. Pointers into the instruction address space have
+the same size as pointers into data space and can, for
+example, contain the address of the first instruction or an
+index in a procedure descriptor table.</p>
+
+<p>There is a single EM program counter, PC, pointing to
+the next instruction to be executed. The procedure pointed
+to by PC is called the &rsquo;current&rsquo; procedure. A
+procedure may call another procedure using the CAL or CAI
+instruction. The calling procedure remains
+&rsquo;active&rsquo; and is resumed whenever the called
+procedure returns. Note that a procedure has several
+&rsquo;active&rsquo; invocations when called
+recursively.</p>
+
+<p>Each procedure must return properly. It is not allowed
+to fall through to the code of the next procedure. There are
+several ways to exit from a procedure:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="24%">
+
+<p>the RET instruction, which returns to the calling
+procedure.</p>
+</td>
+<td width="65%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="24%">
+
+<p>the RTT instruction, which exits a trap handling routine
+and resumes the trapping instruction (see next chapter).</p>
+</td>
+<td width="65%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="24%">
+
+<p>the GTO instruction, which is used for non-local
+goto&rsquo;s. It can remove several frames from the stack
+and transfer control to an active procedure. (see also MES
+11 in paragraph 11.1.4.4)</p>
+</td>
+<td width="65%">
+</td>
+</table>
+
+<p>All branch instructions can transfer control to any
+label within the same procedure. Branch instructions can
+never jump out of a procedure.</p>
+
+<p>Several language implementations use a so called
+procedure instance identifier, a combination of a procedure
+identifier and the LB of a stack frame, also called static
+link.</p>
+
+<p>The program text for each procedure, as well as any
+tables, are fragments and can be allocated anywhere in the
+instruction address space.</p>
+
+<p>4</p>
+
+<p><b>4. DATA ADDRESS SPACE</b></p>
+
+<p>The data address space is divided into three parts,
+called &rsquo;areas&rsquo;, each with its own addressing
+method: global data area, local data area (including the
+stack), and heap data area. These data areas must be part of
+the same address space because all data is accessed by the
+same type of pointers.</p>
+
+<p>Space for global data is reserved using several
+pseudoinstructions in the assembly language, as described in
+the next paragraph and chapter 11. The size of the global
+data area is fixed per program.</p>
+
+<p>Global data is addressed absolutely in the machine
+language. Many instructions are available to address global
+data. They all have an absolute address as argument.
+Examples are LOE, LAE and STE.</p>
+
+<p>Part of the global data area is initialized by the
+compiler, the rest is not initialized at all or is
+initialized with a value, typically &minus;32768 or 0. Part
+of the initialized global data may be made read-only if the
+implementation supports protection.</p>
+
+<p>The local data area is used as a stack, which grows from
+high to low addresses and contains some data for each active
+procedure invocation, called a &rsquo;frame&rsquo;. The size
+of the local data area varies dynamically during execution.
+Below the current procedure frame resides the operand stack.
+The stack pointer SP always points to the bottom of the
+local data area. Local data is addressed by offsetting from
+the local base pointer LB. LB always points to the frame of
+the current procedure. Only the words of the current frame
+and the parameters can be addressed directly. Variables in
+other active procedures are addressed by following the chain
+of statically enclosing procedures using the LXL or LXA
+instruction. The variables in dynamically enclosing
+procedures can be addressed with the use of the DCH
+instruction.</p>
+
+<p>Many instructions have offsets to LB as argument, for
+instance LOL, LAL and STL. The arguments of these
+instructions range from &minus;1 to some (negative) minimum
+for the access of local storage and from 0 to some
+(positive) maximum for parameter access.</p>
+
+<p>The procedure call instructions CAL and CAI each create
+a new frame on the stack. Each procedure has an
+assembly-time parameter specifying the number of bytes
+needed for local storage. This storage is allocated each
+time the procedure is called and must be a multiple of the
+wordsize. Each procedure, therefore, starts with a stack
+with the local variables already allocated. The return
+instructions RET and RTT remove a frame. The actual
+parameters must be removed by the calling procedure.</p>
+
+<p>RET may copy some words from the stack of the returning
+procedure to an unnamed &rsquo;function return area&rsquo;.
+This area is available for &rsquo;READ-ONCE&rsquo; access
+using the LFR instruction. The result of a LFR is only
+defined if the size used to fetch is identical to the size
+used in the last return. The instruction ASP, used to remove
+the parameters from the stack, the branch instruction BRA
+and the non-local goto instruction GTO are the only ones
+that leave the contents of the &rsquo;function return
+area&rsquo; intact. All other instructions are allowed to
+destroy the function return area. Thus parameters can be
+popped before fetching the function result. The maximum size
+of all function return areas is implementation dependent,
+but should allow procedure instance identifiers and all
+implemented objects of type integer, unsigned, float and
+pointer to be returned. In most implementations the maximum
+size of the function return area is twice the pointer size,
+because we want to be able to handle &rsquo;procedure
+instance identifiers&rsquo; which consist of a procedure
+identifier and the LB of a frame belonging to that
+procedure.</p>
+
+<p>The heap data area grows upwards, to higher numbered
+addresses. It is initially empty. The initial value of the
+heap pointer HP marks the low end. The heap pointer may be
+manipulated by the LOR and STR instructions. The heap can
+only be addressed indirectly, by pointers derived from
+previous values of HP.</p>
+
+<p><b>4.1 Global data area</b></p>
+
+<p>The initial size of the global data area is determined
+at assembly time. Global data is allocated by several
+pseudoinstructions in the EM assembly language. Each
+pseudoinstruction allocates one or more bytes. The bytes
+allocated for a single pseudo form a &rsquo;block&rsquo;. A
+block differs from a fragment, because, under certain
+conditions, several blocks are allocated in a single
+fragment. This guarantees that the bytes of these blocks are
+consecutive.</p>
+
+<p>Global data is addressed absolutely in binary machine
+language. Most compilers, however, cannot assign absolute
+addresses to their global variables, especially not if the
+language allows programs to be composed of several
+separately compiled modules. The assembly language therefore
+allows the compiler to name the first address of a global
+data block with an alphanumeric label. Moreover, the only
+way to address such a named global data block in the
+assembly language is by using its name. It is the task of
+the assembler/loader to translate these labels into absolute
+addresses. These labels may also be used in CON and ROM
+pseudoinstructions to initialize pointers.</p>
+
+<p>The pseudoinstruction CON allocates initialized data.
+ROM acts like CON but indicates that the initialized data
+will not change during execution of the program. The
+pseudoinstruction BSS allocates a block of uninitialized or
+identically initialized data. The pseudoinstruction HOL is
+similar to BSS, but it alters the meaning of subsequent
+absolute addressing in the assembly language.</p>
+
+<p>Another type of global data is a small block, called the
+ABS block, with an implementation defined size. Storage in
+this type of block can only be addressed absolutely in
+assembly language. The first word has address 0 and is used
+to maintain the source line number. Special instructions LIN
+and LNI are provided to update this counter. A pointer at
+location 4 points to a string containing the current source
+file name. The instruction FIL can be used to update the
+pointer.</p>
+
+<p>All numeric arguments of the instructions that address
+the global data area refer to locations in the ABS block
+unless they are preceded by at least one HOL pseudo in the
+same module, in which case they refer to the storage area
+allocated by the last HOL pseudoinstruction. Thus LOE 0
+loads the zeroth word of the most recent HOL, unless no HOL
+has appeared in the current file so far, in which case it
+loads the zeroth word of the ABS fragment.</p>
+
+<p>The global data area is highly fragmented. The ABS block
+and each HOL and BSS block are separate fragments. The way
+fragments are formed from CON and ROM blocks is more
+complex. The assemblers group several blocks into a single
+fragment. A fragment only contains blocks of the same type:
+CON or ROM. It is guaranteed that the bytes allocated for
+two consecutive CON pseudos are allocated consecutively in a
+single fragment, unless these CON pseudos are separated in
+the assembly language program by a data label definition or
+one or more of the following pseudos:</p>
+<pre>     ROM, BSS, HOL and END
+</pre>
+
+<p>An analogous rule holds for ROM pseudos.</p>
+
+<p><b>4.2 Local data area</b></p>
+
+<p>The local data area consists of a sequence of frames,
+one for each active procedure. Below the frame of the
+current procedure resides the expression stack. Frames are
+generated by procedure calls and are removed by procedure
+returns. A procedure frame consists of six
+&rsquo;zones&rsquo;:</p>
+<pre>     1.  The return status block
+     2.  The local variables and compiler temporaries
+     3.  The register save block
+     4.  The dynamic local generators
+     5.  The operand stack.
+     6.  The parameters of a procedure one level deeper
+</pre>
+
+<p>A sample frame is shown in Figure 1.</p>
+
+<p>Before a procedure call is performed the actual
+parameters are pushed onto the stack of the calling
+procedure. The exact details are compiler dependent. EM
+allows procedures to be called with a variable number of
+parameters. The implementation of the C-language almost
+forces its runtime system to push the parameters in reverse
+order, that is, the first positional parameter last. Most
+compilers use the C calling convention to be compatible. The
+parameters of a procedure belong to the frame of the calling
+procedure. Note that the evaluation of the actual parameters
+may imply the calling of procedures. The parameters can be
+accessed with certain instructions using offsets of 0 and
+greater. The first byte of the last parameter pushed has
+offset 0. Note that the parameter at offset 0 has a special
+use in the instructions following the static chain (LXL and
+LXA). These instructions assume that this parameter contains
+the LB of the statically enclosing procedure. Procedures
+that do not have a dynamically enclosing procedure do not
+need a static link at offset 0.</p>
+
+<p>Two instructions are available to perform procedure
+calls, CAL and CAI. Several tasks are performed by these
+call instructions.</p>
+
+<p>First, a part of the status of the calling procedure is
+saved on the stack in the return status block. This block
+should contain the return address of the calling procedure,
+its LB and other implementation dependent data. The size of
+this block is fixed for any given implementation because the
+lexical instructions LPB, LXL and LXA must be able to obtain
+the base addresses of the procedure parameters <b>and</b>
+local variables. An alternative solution can be used on
+machines with a highly segmented address space. The stack
+frames need not be contiguous then and the first status save
+area can contain the parameter base AB, which has the value
+of SP just after the last parameter has been pushed.</p>
+
+<p>Second, the LB is changed to point to the first word
+above the local variables. The new LB is a copy of the SP
+after the return status block has been pushed.</p>
+
+<p>Third, the amount of local storage needed by the
+procedure is reserved. The parameters and local storage are
+accessed by the same instructions. Negative offsets are used
+for access to local variables. The highest byte, that is the
+byte nearest to LB, has to be accessed with offset &minus;1.
+The pseudoinstruction specifying the entry point of a
+procedure, has an argument that specifies the amount of
+local storage needed. The local variables allocated by the
+CAI or CAL instructions are the only ones that can be
+accessed with a fixed negative offset. The initial value of
+the allocated words is not defined, but implementations that
+check for undefined values will probably initialize them
+with a special &rsquo;undefined&rsquo; pattern, typically
+&minus;32768.</p>
+
+<p>Fourth, any EM implementation is allowed to reserve a
+variable size block beneath the local variables. This block
+could, for example, be used to save a variable number of
+registers.</p>
+
+<p>Finally, the address of the entry point of the called
+procedure is loaded into the Program Counter.</p>
+
+<p>The ASP instruction can be used to allocate further
+(dynamic) local storage. The base address of such storage
+must be obtained with a LOR SP instruction. This same
+instruction ASP may also be used to remove some words from
+the stack.</p>
+
+<p>There is a version of ASP, called ASS, which fetches the
+number of bytes to allocate from the stack. It can be used
+to allocate space for local objects whose size is unknown at
+compile time, so called &rsquo;dynamic local
+generators&rsquo;.</p>
+
+<p>Control is returned to the calling procedure with a RET
+instruction. Any return value is then copied to the
+&rsquo;function return area&rsquo;. The frame created by the
+call is deallocated and the status of the calling procedure
+is restored. The value of SP just after the return value has
+been popped must be the same as the value of SP just before
+executing the first instruction of this invocation. This
+means that when a RET is executed the operand stack can only
+contain the return value and all dynamically generated
+locals must be deallocated. Violating this restriction might
+result in hard to detect errors. The calling procedure has
+to remove the parameters from the stack. This can be done
+with the aforementioned ASP instruction.</p>
+
+<p>Each procedure frame is a separate fragment. Because any
+fragment may be placed anywhere in memory, procedure frames
+need not be contiguous.</p>
+
+<p><tt>|===============================| | actual parameter
+n-1 | |-------------------------------| | . | | . | | . |
+|-------------------------------| | actual parameter 0 | (
+&lt;&minus; AB ) |===============================|</tt></p>
+
+<p><tt>|===============================|
+|///////////////////////////////| |///// return status block
+/////| |///////////////////////////////| &lt;&minus; LB
+|===============================| | | | local variables | |
+| |-------------------------------| | | | compiler
+temporaries | | | |===============================|
+|///////////////////////////////| |///// register save block
+/////| |///////////////////////////////|
+|===============================| | | | dynamic local
+generators | | | |===============================| | operand
+| |-------------------------------| | operand |
+|===============================| | parameter m-1 |
+|-------------------------------| | . | | . | | . |
+|-------------------------------| | parameter 0 |
+&lt;&minus; SP |===============================|</tt></p>
+
+<p align=center>Figure 1. A sample procedure frame and
+parameters.</p>
+
+<p><b>4.3 Heap data area</b></p>
+
+<p>The heap area starts empty, with HP pointing to the low
+end of it. HP always contains a word address. A copy of HP
+can always be obtained with the LOR instruction. A new value
+may be stored in the heap pointer using the STR instruction.
+If the new value is greater than the old one, then the heap
+grows. If it is smaller, then the heap shrinks. HP may never
+point below its original value. All words between the
+current HP and the original HP are allocated to the heap.
+The heap may not grow into a part of memory that is already
+allocated. When this is attempted, the STR instruction will
+cause a trap to occur. In this case, HP retains its old
+value.</p>
+
+<p>The only way to address the heap is indirectly. Whenever
+an object is allocated by increasing HP, then the old HP
+value must be saved and can be used later to address the
+allocated object. If, in the meantime, HP is decreased so
+that the object is no longer part of the heap, then an
+attempt to access the object is not allowed. Furthermore, if
+the heap pointer is increased again to above the object
+address, then access to the old object gives undefined
+results.</p>
+
+<p>The heap is a single fragment. All bytes have
+consecutive addresses. No limits are imposed on the size of
+the heap as long as it fits in the available data address
+space.</p>
+
+<p>5</p>
+
+<p><b>5. MAPPING OF EM DATA MEMORY ONTO TARGET MACHINE
+MEMORY</b></p>
+
+<p>The EM architecture is designed to be implemented on
+many existing and future machines. EM memory is highly
+fragmented to make adaptation to various memory
+architectures possible. Format and encoding of pointers is
+explicitly undefined.</p>
+
+<p>This chapter gives solutions to some of the anticipated
+problems. First, we describe a possible memory layout for
+machines with 64K bytes of address space. Here we use a
+member of the EM family with 2-byte word and pointer size.
+The most straightforward layout is shown in figure 2.</p>
+
+<p><tt>65534 &minus;&gt; |-------------------------------|
+|///////////////////////////////| |//// unimplemented memory
+/////| |///////////////////////////////| ML &minus;&gt;
+|-------------------------------| | | | | &lt;&minus; LB |
+stack and local area | | | |-------------------------------|
+&lt;&minus; SP |///////////////////////////////| |////////
+inaccessible /////////| |///////////////////////////////|
+|-------------------------------| &lt;&minus; HP | | | heap
+area | | | | | HB &minus;&gt;
+|-------------------------------| | | | global data area | |
+| EB &minus;&gt; |-------------------------------| | | |
+program text | &lt;&minus; PC | | | ( and tables ) | | | | |
+PB &minus;&gt; |-------------------------------|
+|///////////////////////////////| |////////// undefined
+//////////| |///////////////////////////////| 0 &minus;&gt;
+|-------------------------------|</tt></p>
+
+<p align=center>Figure 2. Memory layout showing typical
+register<br>
+positions during execution of an EM program.</p>
+
+<p>The base registers for the various memory pieces can be
+stored in target machine registers or memory.</p>
+
+<p align=center><img src="grohtml-97442.png"></p>
+
+<p>The stack grows from high EM addresses to low EM
+addresses, and the heap the other way. The memory between SP
+and HP is not accessible, but may be allocated later to the
+stack or the heap if needed. The local data area is
+allocated starting at the high end of memory.</p>
+
+<p>Because EM address 0 is not mapped onto target address
+0, a problem arises when pointers are used. If a program
+pushed a constant, say 6, onto the stack, and then tried to
+indirect through it, the wrong word would be fetched,
+because EM address 6 is mapped onto target address EB+6 and
+not target address 6 itself. This particular problem is
+solved by explicitly declaring the format of a pointer to be
+undefined, so that using a constant as a pointer is
+completely illegal. However, the general problem of mapping
+pointers still exists.</p>
+
+<p>There are two possible solutions. In the first solution,
+EM pointers are represented in the target machine as true EM
+addresses, for example, a pointer to EM address 6 really is
+stored as a 6 in the target machine. This solution implies
+that every time a pointer is fetched EB must be added before
+referencing the target machine&rsquo;s memory. If the target
+machine has powerful indexing facilities, EB can be kept in
+a target machine register, and the relocation can indeed be
+done on every reference to the data address space at a
+modest cost in speed.</p>
+
+<p>The other solution consists of having EM pointers refer
+to the true target machine address. Thus the instruction LAE
+6 (Load Address of External 6) would push the value of EB+6
+onto the stack. When this approach is chosen, back ends must
+know how to offset from EB, to translate all instructions
+that manipulate EM addresses. However, the problem is not
+completely solved, because a front end may have to
+initialize a pointer in CON or ROM data to point to a global
+address. This pointer must also be relocated by the back end
+or the interpreter.</p>
+
+<p>Although the EM stack grows from high to low EM
+addresses, some machines have hardware PUSH and POP
+instructions that require the stack to grow upwards. If
+reasons of efficiency demand the use of these instructions,
+then EM can be implemented with the memory layout upside
+down, as shown in figure 3. This is possible because the
+pointer format is explicitly undefined. The first element of
+a word array will have a lower physical address than the
+second element.</p>
+
+<p><tt>| | | | | EB=60 | | ^ | | | | | |
+|-----------------| |-----------------| 105 | 45 | 44 | 104
+214 | 41 | 40 | 215 |-----------------| |-----------------|
+103 | 43 | 42 | 102 212 | 43 | 42 | 213 |-----------------|
+|-----------------| 101 | 41 | 40 | 100 210 | 45 | 44 | 211
+|-----------------| |-----------------| | | | | | | v | |
+EB=255 | | | | |</tt></p>
+
+<p><tt>Type A Type B</tt></p>
+
+<p align=center>Figure 3. Two possible memory
+implementations.<br>
+Numbers within the boxes are EM addresses.<br>
+The other numbers are physical addresses.</p>
+
+<p>So, we have two different EM memory implementations:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>A &minus;</p>
+</td>
+<td width="4%"></td>
+<td width="18%">
+
+<p>stack downwards</p>
+</td>
+<td width="71%">
+</td>
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>B &minus;</p>
+</td>
+<td width="4%"></td>
+<td width="18%">
+
+<p>stack upwards</p>
+</td>
+<td width="71%">
+</td>
+</table>
+
+<p>For each of these two possibilities we give the
+translation of the EM instructions to push the third byte of
+a global data block starting at EM address 40 onto the stack
+and to load the word at address 40. All translations assume
+a word and pointer size of two bytes. The target machine
+used is a PDP-11 augmented with push and pop instructions.
+Registers &rsquo;r0&rsquo; and &rsquo;r1&rsquo; are used and
+suffer from sign extension for byte transfers. Push $40
+means push the constant 40, not word 40.</p>
+
+<p>The translation of the EM instructions depends on the
+pointer representation used. For each of the two solutions
+explained above the translation is given.</p>
+
+<p>First, the translation for the two implementations using
+EM addresses as pointer representation:</p>
+
+<p align=center><img src="grohtml-97443.png"></p>
+
+<p>The translation for the two implementations, if the
+target machine address is used as pointer representation,
+is:</p>
+
+<p align=center><img src="grohtml-97444.png"></p>
+
+<p>The translation presented above is not intended to be
+optimal. Most machines can handle these simple cases in one
+or two instructions. It demonstrates, however, the
+flexibility of the EM design.</p>
+
+<p>There are several possibilities to implement EM on
+machines with address spaces larger than 64k bytes. For EM
+with two byte pointers one could allocate instruction and
+data space each in a separate 64k piece of memory. EM
+pointers still have to fit in two bytes, but the base
+registers PB and EB may be loaded in hardware registers
+wider than 16 bits, if available. EM implementations can
+also make efficient use of a machine with separate
+instruction and data space.</p>
+
+<p>EM with 32 bit pointers allows one to make use of
+machines with large address spaces. In a virtual, segmented
+memory system one could use a separate segment for each
+fragment.</p>
+
+<p>6</p>
+
+<p><b>6. TYPE REPRESENTATIONS</b></p>
+
+<p>The representations used for typed objects are not
+precisely specified by EM. Sometimes we only specify that a
+typed object occupies a certain amount of space and state no
+further restrictions. If one wants to have a different
+representation of the value of an object on the stack one
+has to use a convert instruction in most cases. We do
+specify some relations between the representations of types.
+This allows some intermixed use of operators for different
+types on the same object(s). For example, the instruction
+ZER pushes signed and unsigned integers with the value zero
+and empty sets. ZER has as only argument the size of the
+object.</p>
+
+<p>The representation of floating point numbers is a good
+example, it allows widely varying implementations. The only
+ways to create floating point numbers are via initialization
+and via conversions from integer numbers. Only by using
+conversions to integers and comparing two floating point
+numbers with each other, can these numbers be converted to
+human readable output. Implementations may use base 10, base
+2 or any other base for exponents, and have freedom in
+choosing the range of exponent and mantissa.</p>
+
+<p>Other types are more precisely described. In the
+following paragraphs a description will be given of the
+restrictions imposed on the representation of the types
+used. A number <b>n</b> used in these paragraphs indicates
+the size of the object in <i>bits</i>.</p>
+
+<p><b>6.1 Unsigned integers</b></p>
+
+<p>The range of unsigned integers is 0.. 2
+<b><small>n</small></b> -1. A binary representation is
+assumed. The order of the bits within an object is knowingly
+left unspecified. Discussing bit order within each 8-bit
+byte is academic, so the only real freedom of this
+specification lies in the byte order. We really do not care
+whether an implementation of a 4-byte integer has its bytes
+in a particular order of significance. This of course means
+that some sequences of instructions have unpredictable
+effects. For example:</p>
+<pre>     LOC 258 ; STL 0 ; LAL 0 ; LOI 1      ( wordsize &gt;=2 )
+</pre>
+
+<p>The value on the stack after executing this sequence can
+be anything, but will most likely be 1 or 2.</p>
+
+<p>Conversion between unsigned integers of different sizes
+have to be done with explicit convert instructions. One
+cannot simply pad an unsigned integer with zero&rsquo;s at
+either end and expect a correct result.</p>
+
+<p>We assume existence of at least single word unsigned
+arithmetic in any implementation.</p>
+
+<p><b>6.2 Signed Integers</b></p>
+
+<p>The range of signed integers is &minus;2
+<b><small>n</small></b><small>&minus;1</small> .. 2
+<b><small>n</small></b><small>&minus;1</small> &minus;1, in
+other words the range of signed integers of <b>n</b> bits
+using two&rsquo;s complement arithmetic. The representation
+is the same as for unsigned integers except the range 2
+<b><small>n</small></b><small>&minus;1</small> .. 2
+<b><small>n</small></b> &minus;1 is mapped on the range
+&minus;2 <b><small>n</small></b><small>&minus;1</small> ..
+&minus;1. In other words, the most significant bit is used
+as sign bit. The convert instructions between signed and
+unsigned integers of the same size can be used to catch
+errors.</p>
+
+<p>The value &minus;2
+<b><small>n</small></b><small>&minus;1</small> is used for
+undefined signed integers. EM implementations should trap
+when this value is used in an operation on signed integers.
+The instruction mask, accessed with SIM and LIM &minus; see
+chapter 9 &minus;, can be used to disable such traps.</p>
+
+<p>We assume existence of at least single word signed
+arithmetic in any implementation.</p>
+
+<p><b>6.3 Floating point values</b></p>
+
+<p>Floating point values must have a signed mantissa and a
+signed exponent. Although no base is specified, base 2 is
+the normal choice, because the FEF instruction pushes the
+exponent in base 2.</p>
+
+<p>The implementation of floating point arithmetic is
+optional. The compilers currently in use have runtime
+parameters for the size of the floating point values they
+should use. Common choices are 4 and/or 8 bytes.</p>
+
+<p><b>6.4 Pointers</b></p>
+
+<p>EM has two kinds of pointers: for instruction and for
+data space. Each kind can only be used for its own space,
+conversion between these two subtypes is impossible. We
+assume that pointers have a range from 0 upwards. Any
+implementation may have holes in the pointer range between
+fragments. One can of course not expect to be able to
+address two megabyte of memory using a 2-byte pointer.
+Normally, a 2-byte pointer allows up to 65536 bytes of
+addressable memory.</p>
+
+<p>Pointer representation has one restriction. The pointer
+with the same representation as the integer zero of the same
+size should be invalid. Some languages and/or runtime
+systems represent the nil pointer as zero.</p>
+
+<p><b>6.5 Bit sets</b></p>
+
+<p>All bit sets of size <b>n</b> are subsets of the set { i
+| i&gt;=0, i&lt;<b>n</b> }. A bit set contains a bit for
+each element showing its presence or absence. Bit sets are
+subdivided into words. The word with the lowest EM address
+governs the subset { i | i&gt;=0, i&lt;<b>m</b> }, where
+<b>m</b> is the number of bits in a word. The next higher
+words each govern the next higher <b>m</b> set elements. The
+relation between a set with size of a word and an unsigned
+integer word is that the value of the unsigned integer is
+the summation of the 2i where i is in the set.</p>
+
+<p>Example: a 2-word bit set (wordsize 2) containing the
+elements 1, 6, 8, 15, 18, 21, 27 and 28 is composed of two
+integers, e.g. at addresses 40 and 42. The word at 40
+contains the value 33090 (or &minus;32446), the word at 42
+contains the value 6180.</p>
+
+<p>7</p>
+
+<p><b>7. DESCRIPTORS</b></p>
+
+<p>Several instructions use descriptors, notably the range
+check instruction, the array instructions, the goto
+instruction and the case jump instructions. Descriptors
+reside in data space. They may be constructed at run time,
+but more often they are fixed and allocated in ROM data.</p>
+
+<p>All instructions using descriptors, except GTO, have as
+argument the size of the integers in the descriptor. All
+implementations have to allow integers of the size of a word
+in descriptors. All integers popped from the stack and used
+for indexing or comparing must have the same size as the
+integers in the descriptor.</p>
+
+<p><b>7.1 Range check descriptors</b></p>
+
+<p>Range check descriptors consist of two integers:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>1.</p>
+</td>
+<td width="10%">
+
+<p>lower bound</p>
+</td>
+<td width="79%">
+
+<p>signed</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>2.</p>
+</td>
+<td width="10%">
+
+<p>upper bound</p>
+</td>
+<td width="79%">
+
+<p>signed</p>
+</td>
+</table>
+
+<p>The range check instruction checks an integer on the
+stack against these bounds and causes a trap if the value is
+outside the interval. The value itself is neither changed
+nor removed from the stack.</p>
+
+<p><b>7.2 Array descriptors</b></p>
+
+<p>Each array descriptor describes a single dimension. For
+multi-dimensional arrays, several array instructions are
+needed to access a single element. Array descriptors contain
+the following three integers:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>1.</p>
+</td>
+<td width="10%">
+
+<p>lower bound</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="79%">
+
+<p>signed</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>2.</p>
+</td>
+<td width="10%">
+
+<p>upper bound &minus; lower bound</p>
+</td>
+<td width="79%">
+
+<p>unsigned</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>3.</p>
+</td>
+<td width="14%">
+
+<p>number of bytes per element</p>
+</td>
+<td width="75%">
+
+<p>unsigned</p>
+</td>
+</table>
+
+<p>The array instructions LAR, SAR and AAR have the pointer
+to the start of the descriptor as operand on the stack.</p>
+
+<p>The element A[I] is fetched as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>Stack the address of A (e.g., using LAE or LAL)</p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>Stack the value of I (n-byte integer)</p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>Stack the pointer to the descriptor (e.g., using
+LAE)</p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>LAR n (n is the size of the integers in the descriptor
+and I)</p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p>All array instructions first pop the address of the
+descriptor and the index. If the index is not within the
+bounds specified, a trap occurs. If ok, (I &minus; lower
+bound) is multiplied by the number of bytes per element (the
+third word). The result is added to the address of A and
+replaces A on the stack.</p>
+
+<p>At this point LAR, SAR and AAR diverge. AAR is finished.
+LAR pops the address and fetches the data item, the size
+being specified by the descriptor. The usual restrictions
+for memory access must be obeyed. SAR pops the address and
+stores the data item now exposed.</p>
+
+<p><b>7.3 Non-local goto descriptors</b></p>
+
+<p>The GTO instruction provides a way of returning directly
+to any active procedure invocation. The argument of the
+instruction is the address of a descriptor containing three
+pointers:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="10%">
+
+<p>value of PC after the jump</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="10%">
+
+<p>value of SP after the jump</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="10%">
+
+<p>value of LB after the jump</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>GTO replaces the loads PC, SP and LB from the
+descriptor, thereby jumping to a procedure and removing zero
+or more frames from the stack. The LB, SP and PC in the
+descriptor must belong to a dynamically enclosing procedure,
+because some EM implementations will need to backtrack
+through the dynamic chain and use the implementation
+dependent data in frames to restore registers etc.</p>
+
+<p><b>7.4 Case descriptors</b></p>
+
+<p>The case jump instructions CSA and CSB both provide
+multiway branches selected by a case index. Both fetch two
+operands from the stack: first a pointer to the low address
+of the case descriptor and then the case index. CSA uses the
+case index as index in the descriptor table, but CSB
+searches the table for an occurrence of the case index.
+Therefore, the descriptors for CSA and CSB, as shown in
+figure 4, are different. All pointers in the table must be
+addresses of instructions in the procedure executing the
+case instruction.</p>
+
+<p>CSA selects the new PC by indexing. If the index, a
+signed integer, is greater than or equal to the lower bound
+and less than or equal to the upper bound, then fetch the
+new PC from the list of instruction pointers by indexing
+with index-lower. The table does not contain the value of
+the upper bound, but the value of upper-lower as an unsigned
+integer. The default instruction pointer is used when the
+index is out of bounds. If the resulting PC is 0, then
+trap.</p>
+
+<p>CSB selects the new PC by searching. The table is
+searched for an entry with index value equal to the case
+index. That entry or, if none is found, the default entry
+contains the new PC. When the resulting PC is 0, a trap is
+performed.</p>
+
+<p>The choice of which case instruction to use for each
+source language case statement is up to the front end. If
+the range of the index value is dense, i.e</p>
+<pre>     (highest value &minus; lowest value) / number of cases
+</pre>
+
+<p>is less than some threshold, then CSA is the obvious
+choice. If the range is sparse, CSB is better.</p>
+
+<p><tt>|--------------------| |--------------------| high
+address | pointer for upb | | pointer n-1 |
+|--------------------| |- - - - - - - | | . | | index n-1 |
+| . | |--------------------| | . | | . | | . | | . | | . | |
+. | | . | |--------------------| | . | | pointer 1 |
+|--------------------| |- - - - - - - | | pointer for lwb+1
+| | index 1 | |--------------------| |--------------------|
+| pointer for lwb | | pointer 0 | |--------------------| |-
+- - - - - - | | upper - lower | | index 0 |
+|--------------------| |--------------------| | lower bound
+| | number of entries | |--------------------|
+|--------------------| | default pointer | | default pointer
+| low address |--------------------|
+|--------------------|</tt></p>
+
+<p><tt>CSA descriptor CSB descriptor</tt></p>
+
+<p align=center>Figure 4. Descriptor layout for CSA and
+CSB</p>
+
+<p>8</p>
+
+<p><b>8. ENVIRONMENT INTERACTIONS</b></p>
+
+<p>EM programs can interact with their environment in three
+ways. Two, starting/stopping and monitor calls, are dealt
+with in this chapter. The remaining way to interact,
+interrupts, will be treated together with traps in chapter
+9.</p>
+
+<p><b>8.1 Program starting and stopping</b></p>
+
+<p>EM user programs start with a call to a procedure called
+_m_a_i_n. The assembler and backends look for the definition
+of a procedure with this name in their input. The call
+passes three parameters to the procedure. The parameters are
+similar to the parameters supplied by the
+<small>UNIX</small> &reg; operating system to C programs.
+These parameters are often called <b>argc</b>, <b>argv</b>
+and <b>envp</b>. Argc is the parameter nearest to LB and is
+a wordsized integer. The other two are pointers to the first
+element of an array of string pointers. The <b>argv</b>
+array contains <b>argc</b> strings, the first of which
+contains the program call name. The other strings in the
+<b>argv</b> array are the program parameters.</p>
+
+<p>The <b>envp</b> array contains strings in the form
+&quot;name=string&quot;, where &rsquo;name&rsquo; is the
+name of an environment variable and string its value. The
+<b>envp</b> is terminated by a zero pointer.</p>
+
+<p>An EM user program stops if the program returns from the
+first invocation of _m_a_i_n. The contents of the function
+return area are used to procure a wordsized program return
+code. EM programs also stop when traps and interrupts occur
+that are not caught and when the exit monitor call is
+executed.</p>
+
+<p><b>8.2 Input/Output and other monitor calls</b></p>
+
+<p>EM differs from most conventional machines in that it
+has high level i/o instructions. Typical instructions are
+OPEN FILE and READ FROM FILE instead of low level
+instructions such as setting and clearing bits in device
+registers. By providing such high level i/o primitives, the
+task of implementing EM on various non EM machines is made
+considerably easier.</p>
+
+<p>I/O is initiated by the MON instruction, which expects
+an iocode on top of the stack. Often there are also
+parameters which are pushed on the stack in reverse order,
+that is: last parameter first. Some i/o functions also
+provide results, which are returned on the stack. In the
+list of monitor calls we use several types of parameters and
+results, these types consist of integers and unsigneds of
+varying sizes, but never smaller than the wordsize, and the
+two pointer types.</p>
+
+<p>The names of the types used are:</p>
+
+<p align=center><img src="grohtml-97445.png"></p>
+
+<p>The table below lists the i/o codes with their results
+and parameters. This list is similar to the system calls of
+the UNIX Version 7 operating system.</p>
+
+<p>To execute a monitor call, proceed as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>a)</p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p>Stack the parameters, in reverse order, last parameter
+first.</p>
+</td>
+<td width="65%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>b)</p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p>Push the monitor call number (iocode) onto the
+stack.</p>
+</td>
+<td width="65%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>c)</p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p>Execute the MON instruction.</p>
+</td>
+<td width="65%">
+</td>
+</table>
+
+<p>An error code is present on the top of the stack after
+execution of most monitor calls. If this error code is zero,
+the call performed the action requested and the results are
+available on top of the stack. Non-zero error codes indicate
+a failure, in this case no results are available and the
+error code has been pushed twice. This construction enables
+programs to test for failure with a single instruction ( TEQ
+or TNE ) and still find out the cause of the failure. The
+result name &rsquo;e&rsquo; is reserved for the error
+code.</p>
+
+<p>List of monitor calls.</p>
+<pre>nr  name     parameters      results                function
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>1</p>
+</td>
+<td width="92%">
+
+<p>Exit</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>status:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Terminate this process</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>2</p>
+</td>
+<td width="92%">
+
+<p>Fork</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,flag,pid:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Spawn new process</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>3</p>
+</td>
+<td width="92%">
+
+<p>Read</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes:int;buf:ptr;nbytes:unsp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int;rbytes:unsp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Read from file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>4</p>
+</td>
+<td width="92%">
+
+<p>Write</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes:int;buf:ptr;nbytes:unsp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int;wbytes:unsp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Write on a file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>5</p>
+</td>
+<td width="92%">
+
+<p>Open</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;flag:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,fildes:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Open file for read and/or write</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>6</p>
+</td>
+<td width="92%">
+
+<p>Close</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Close a file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>7</p>
+</td>
+<td width="92%">
+
+<p>Wait</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int;status,pid:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Wait for child</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>8</p>
+</td>
+<td width="92%">
+
+<p>Creat</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;mode:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,fildes:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Create a new file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>9</p>
+</td>
+<td width="92%">
+
+<p>Link</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string1,string2:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Link to a file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>10</p>
+</td>
+<td width="92%">
+
+<p>Unlink</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Remove directory entry</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>12</p>
+</td>
+<td width="92%">
+
+<p>Chdir</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Change default directory</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>14</p>
+</td>
+<td width="92%">
+
+<p>Mknod</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;mode,addr:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Make a special file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>15</p>
+</td>
+<td width="92%">
+
+<p>Chmod</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;mode:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Change mode of file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>16</p>
+</td>
+<td width="92%">
+
+<p>Chown</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;owner,group:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Change owner/group of a file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>18</p>
+</td>
+<td width="92%">
+
+<p>Stat</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string,statbuf:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get file status</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>19</p>
+</td>
+<td width="92%">
+
+<p>Lseek</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes:int;off:int4;whence:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int;oldoff:int4</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Move read/write pointer</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>20</p>
+</td>
+<td width="92%">
+
+<p>Getpid</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>pid:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get process identification</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>21</p>
+</td>
+<td width="92%">
+
+<p>Mount</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>special,string:ptr;rwflag:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Mount file system</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>22</p>
+</td>
+<td width="92%">
+
+<p>Umount</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>special:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Unmount file system</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>23</p>
+</td>
+<td width="92%">
+
+<p>Setuid</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>userid:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set user ID</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>24</p>
+</td>
+<td width="92%">
+
+<p>Getuid</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e_uid,r_uid:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get user ID</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>25</p>
+</td>
+<td width="92%">
+
+<p>Stime</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>time:int4</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set time and date</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>26</p>
+</td>
+<td width="92%">
+
+<p>Ptrace</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>request:int;pid:int2;addr:ptr;data:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,value:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Process trace</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>27</p>
+</td>
+<td width="92%">
+
+<p>Alarm</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>seconds:uns2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>previous:uns2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Schedule signal</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>28</p>
+</td>
+<td width="92%">
+
+<p>Fstat</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes:int;statbuf:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get file status</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>29</p>
+</td>
+<td width="92%">
+
+<p>Pause</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Stop until signal</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>30</p>
+</td>
+<td width="92%">
+
+<p>Utime</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string,timep:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set file times</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>33</p>
+</td>
+<td width="92%">
+
+<p>Access</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr;mode:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Determine file accessibility</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>34</p>
+</td>
+<td width="92%">
+
+<p>Nice</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>incr:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set program priority</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>35</p>
+</td>
+<td width="92%">
+
+<p>Ftime</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>bufp:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get date and time</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>36</p>
+</td>
+<td width="92%">
+
+<p>Sync</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Update filesystem</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>37</p>
+</td>
+<td width="92%">
+
+<p>Kill</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>pid:int2;sig:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Send signal to a process</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>41</p>
+</td>
+<td width="92%">
+
+<p>Dup</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes,newfildes:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,fildes:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Duplicate a file descriptor</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>42</p>
+</td>
+<td width="92%">
+
+<p>Pipe</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,w_des,r_des:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Create a pipe</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>43</p>
+</td>
+<td width="92%">
+
+<p>Times</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>buffer:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get process times</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>44</p>
+</td>
+<td width="92%">
+
+<p>Profil</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>buff:ptr;bufsiz,offset,scale:intp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Execution time profile</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>46</p>
+</td>
+<td width="92%">
+
+<p>Setgid</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>gid:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set group ID</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>47</p>
+</td>
+<td width="92%">
+
+<p>Getgid</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e_gid,r_gid:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Get group ID</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>48</p>
+</td>
+<td width="92%">
+
+<p>Sigtrp</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>trapno,signo:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e,prevtrap:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>See below</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>51</p>
+</td>
+<td width="92%">
+
+<p>Acct</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>file:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Turn accounting on or off</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>53</p>
+</td>
+<td width="92%">
+
+<p>Lock</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>flag:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Lock a process</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>54</p>
+</td>
+<td width="92%">
+
+<p>Ioctl</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>fildes,request:int;argp:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Control device</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>56</p>
+</td>
+<td width="92%">
+
+<p>Mpxcall</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>cmd:int;vec:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Multiplexed file handling</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>59</p>
+</td>
+<td width="92%">
+
+<p>Exece</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>name,argv,envp:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Execute a file</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>60</p>
+</td>
+<td width="92%">
+
+<p>Umask</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>mask:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>oldmask:int2</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Set file creation mode mask</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>61</p>
+</td>
+<td width="92%">
+
+<p>Chroot</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>string:ptr</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>e:int</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>Change root directory</p>
+</td>
+</table>
+
+<p>Codes 0, 11, 13, 17, 31, 32, 38, 39, 40, 45, 49, 50, 52,
+55, 57, 58, 62, and 63 are not used.</p>
+
+<p>All monitor calls, except fork and sigtrp are the same
+as the UNIX version 7 system calls.</p>
+
+<p>The sigtrp entry maps UNIX signals onto EM interrupts.
+Normally, trapno is in the range 0 to 252. In that case it
+requests that signal signo will cause trap trapno to occur.
+When given trap number &minus;2, default signal handling is
+reset, and when given trap number &minus;3, the signal is
+ignored.</p>
+
+<p>The flag returned by fork is 1 in the child process and
+0 in the parent. The pid returned is the process-id of the
+other process.</p>
+
+<p>9</p>
+
+<p><b>9. TRAPS AND INTERRUPTS</b></p>
+
+<p>EM provides a means for the user program to catch all
+traps generated by the program itself, the hardware, or
+external conditions. This mechanism uses five instructions:
+LIM, SIM, SIG, TRP and RTT. This section of the manual may
+be omitted on the first reading since it presupposes
+knowledge of the EM instruction set.</p>
+
+<p>The action taken when a trap occurs is determined by the
+value of an internal EM trap register. This register
+contains a pointer to a procedure. Initially the pointer
+used is zero and all traps halt the program with, hopefully,
+a useful message to the outside world. The SIG instruction
+can be used to alter the trap register, it pops a procedure
+pointer from the stack into the trap register. When a trap
+occurs after storing a nonzero value in the trap register,
+the procedure pointed to by the trap register is called with
+the trap number as the only parameter (see below). SIG
+returns the previous value of the trap register on the
+stack. Two consecutive SIGs are a no-op. When a trap occurs,
+the trap register is reset to its initial condition, to
+prevent recursive traps from hanging the machine up, e.g.
+stack overflow in the stack overflow handling procedure.</p>
+
+<p>The runtime systems for some languages need to ignore
+some EM traps. EM offers a feature called the ignore mask.
+It contains one bit for each of the lowest 16 trap numbers.
+The bits are numbered 0 to 15, with the least significant
+bit having number 0. If a certain bit is 1 the corresponding
+trap never occurs and processing simply continues. The
+actions performed by the offending instruction are described
+by the Pascal program in appendix A.<br>
+If the bit is 0, traps are not ignored. The instructions LIM
+and SIM allow copying and replacement of the ignore
+mask.</p>
+
+<p>The TRP instruction generates a trap, the trap number
+being found on the stack. This is, among other things,
+useful for library procedures and runtime systems. It can
+also be used by a low level trap procedure to pass the trap
+to a higher level one (see example below).</p>
+
+<p>The RTT instruction returns from the trap procedure and
+continues after the trap. In the list below all traps marked
+with an asterisk (&rsquo;*&rsquo;) are considered to be
+fatal and it is explicitly undefined what happens when
+restarting after the trap.</p>
+
+<p>The way a trap procedure is called is completely
+compatible with normal calling conventions. The only way a
+trap procedure differs from normal procedures is the return.
+It has to use RTT instead of RET. This is necessary because
+the complete runtime status is saved on the stack before
+calling the procedure and all this status has to be
+reloaded. Error numbers are in the range 0 to 252. The trap
+numbers are divided into three categories:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="10%">
+
+<p>0&minus; 63</p>
+</td>
+<td width="10%"></td>
+<td width="24%">
+
+<p>EM machine errors, e.g. illegal instruction.</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>0&minus;15</p>
+<td width="39%"></td>
+<td width="16%">
+
+<p>maskable</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="32%">
+
+<p>16&minus;63</p>
+</td>
+<td width="6%"></td>
+<td width="16%">
+
+<p>not maskable</p>
+</td>
+<td width="43%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="32%">
+
+<p>64&minus;127</p>
+</td>
+<td width="6%"></td>
+<td width="16%"></td>
+<td width="43%">
+</td>
+</table>
+
+<p>Reserved for use by compilers, run time systems,
+etc.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>128&minus;252</p>
+</td>
+<td width="10%"></td>
+<td width="18%">
+
+<p>Available for user programs.</p>
+</td>
+<td width="57%">
+</td>
+</table>
+
+<p>EM machine errors are numbered as follows:</p>
+
+<p align=center><img src="grohtml-97446.png"></p>
+
+<p>As an example, suppose a subprocedure has to be written
+to do a numeric calculation. When an overflow occurs the
+computation has to be stopped and the higher level procedure
+must be resumed. This can be programmed as follows using the
+mechanism described above:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>mes 2,2,2</p>
+</td>
+<td width="52%">
+
+<p>; set sizes</p>
+</td>
+</table>
+
+<p>ersave</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>bss 2,0,0</p>
+</td>
+<td width="52%">
+
+<p>; Room to save previous value of trap procedure</p>
+</td>
+</table>
+
+<p>msave</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>bss 2,0,0</p>
+</td>
+<td width="52%">
+
+<p>; Room to save previous value of trap mask</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>pro $calcule,0</p>
+</td>
+<td width="52%">
+
+<p>; entry point</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lxl 0</p>
+</td>
+<td width="52%">
+
+<p>; fill in non-local goto descriptor with LB</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>ste jmpbuf+4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lor 1</p>
+</td>
+<td width="52%">
+
+<p>; and SP</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>ste jmpbuf+2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lim</p>
+</td>
+<td width="52%">
+
+<p>; get current ignore mask</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>ste msave</p>
+</td>
+<td width="52%">
+
+<p>; save it</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lim</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>loc 16</p>
+</td>
+<td width="52%">
+
+<p>; bit for EFOVFL</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>ior 2</p>
+</td>
+<td width="52%">
+
+<p>; set in mask</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sim</p>
+</td>
+<td width="52%">
+
+<p>; ignore EFOVFL from now on</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lpi $catch</p>
+</td>
+<td width="52%">
+
+<p>; load procedure identifier</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sig</p>
+</td>
+<td width="52%">
+
+<p>; catch wil get all traps now</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>ste ersave</p>
+</td>
+<td width="52%">
+
+<p>; save previous trap procedure identifier</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+</td>
+<td width="52%">
+
+<p>; perform calculation now, possibly generating
+overflow</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>1</p>
+</td>
+<td width="46%"></td>
+<td width="52%">
+
+<p>; label jumped to by catch procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>loe ersave</p>
+</td>
+<td width="52%">
+
+<p>; get old trap procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sig</p>
+</td>
+<td width="52%">
+
+<p>; refer all following trap to old procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>asp 2</p>
+</td>
+<td width="52%">
+
+<p>; remove result of sig</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>loe msave</p>
+</td>
+<td width="52%">
+
+<p>; restore previous mask</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sim</p>
+</td>
+<td width="52%">
+
+<p>; done now</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+</td>
+<td width="52%">
+
+<p>; load result of calculation</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>ret 2</p>
+</td>
+<td width="52%">
+
+<p>; return result</p>
+</td>
+</table>
+
+<p>jmpbuf</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="98%">
+
+<p>con *1,0,0</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="98%">
+
+<p>end</p>
+</td>
+</table>
+
+<p>Example of catch procedure</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>pro $catch,0</p>
+</td>
+<td width="52%">
+
+<p>; Local procedure that must catch the overflow trap</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lol 2</p>
+</td>
+<td width="52%">
+
+<p>; Load trap number</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>loc 4</p>
+</td>
+<td width="52%">
+
+<p>; check for overflow</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>bne *1</p>
+</td>
+<td width="52%">
+
+<p>; if other trap, call higher trap procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>gto jmpbuf</p>
+</td>
+<td width="52%">
+
+<p>; return to procedure calcule</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>1</p>
+</td>
+<td width="46%"></td>
+<td width="52%">
+
+<p>; other trap has occurred</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>loe ersave</p>
+</td>
+<td width="52%">
+
+<p>; previous trap procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sig</p>
+</td>
+<td width="52%">
+
+<p>; other procedure will get the traps now</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>asp 2</p>
+</td>
+<td width="52%">
+
+<p>; remove the result of sig</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lol 2</p>
+</td>
+<td width="52%">
+
+<p>; stack trap number</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>trp</p>
+</td>
+<td width="52%">
+
+<p>; call other trap procedure</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>rtt</p>
+</td>
+<td width="52%">
+
+<p>; if other procedure returns, do the same</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>end</p>
+</td>
+<td width="52%">
+</td>
+</table>
+
+<p>10</p>
+
+<p><b>10. EM MACHINE LANGUAGE</b></p>
+
+<p>The EM machine language is designed to make program text
+compact and to make decoding easy. Compact program text has
+many advantages: programs execute faster, programs occupy
+less primary and secondary storage and loading programs into
+satellite processors is faster. The decoding of EM machine
+language is so simple, that it is feasible to use
+interpreters as long as EM hardware machines are not
+available. This chapter is irrelevant when back ends are
+used to produce executable target machine code.</p>
+
+<p><b>10.1 Instruction encoding</b></p>
+
+<p>A design goal of EM is to make the program text as
+compact as possible. Decoding must be easy, however. The
+encoding is fully byte oriented, without any small bit
+fields. There are 256 primary opcodes, two of which are an
+escape to two groups of 256 secondary opcodes each.</p>
+
+<p>EM instructions without arguments have a single opcode
+assigned, possibly escaped:</p>
+
+<p><tt>|--------------| | opcode |
+|--------------|</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="47%"></td>
+<td width="-24%"></td>
+<td width="76%">
+
+<p>or</p>
+</td>
+</table>
+
+<p><tt>|--------------|--------------| | escape | opcode |
+|--------------|--------------|</tt></p>
+
+<p>The encoding for instructions with an argument is more
+complex. Several instructions have an address from the
+global data area as argument. Other instructions have
+different opcodes for positive and negative arguments.</p>
+
+<p>There is always an opcode that takes the next two bytes
+as argument, high byte first:</p>
+
+<p><tt>|--------------|--------------|--------------| |
+opcode | hibyte | lobyte |
+|--------------|--------------|--------------|</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="-10%"></td>
+<td width="90%">
+
+<p>or</p>
+</td>
+</table>
+
+
+<p><tt>|--------------|--------------|--------------|--------------|
+| escape | opcode | hibyte | lobyte |
+|--------------|--------------|--------------|--------------|</tt></p>
+
+<p>An extra escape is provided for instructions with four
+or eight byte arguments.</p>
+
+<p><tt>|--------------|--------------|--------------|
+|--------------| | ESCAPE | opcode | hibyte |...| lobyte |
+|--------------|--------------|--------------|
+|--------------|</tt></p>
+
+<p>For most instructions some argument values predominate.
+The most frequent combinations of instruction and argument
+will be encoded in a single byte, called a mini:</p>
+
+<p><tt>|---------------| |opcode+argument| (mini)
+|---------------|</tt></p>
+
+<p>The number of minis is restricted, because only 254
+primary opcodes are available. Many instructions have the
+bulk of their arguments fall in the range 0 to 255.
+Instructions that address global data have their arguments
+distributed over a wider range, but small values of the high
+byte are common. For all these cases there is another
+encoding that combines the instruction and the high byte of
+the argument into a single opcode. These opcodes are called
+shorties. Shorties may be escaped.</p>
+
+<p><tt>|--------------|--------------| | opcode+high |
+lobyte | (shortie) |--------------|--------------|</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="-10%"></td>
+<td width="90%">
+
+<p>or</p>
+</td>
+</table>
+
+<p><tt>|--------------|--------------|--------------| |
+escape | opcode+high | lobyte |
+|--------------|--------------|--------------|</tt></p>
+
+<p>Escaped shorties are useless if the normal encoding has
+a primary opcode. Note that for some instruction-argument
+combinations several different encodings are available. It
+is the task of the assembler to select the shortest of
+these. The savings by these mini and shortie opcodes are
+considerable, about 55%.</p>
+
+<p>Further improvements are possible: the arguments of many
+instructions are a multiple of the wordsize. Some do also
+not allow zero as an argument. If these arguments are
+divided by the wordsize and, when zero is not allowed, then
+decremented by 1, more of them can be encoded as shortie or
+mini. The arguments of some other instructions rarely or
+never assume the value 0, but start at 1. The value 1 is
+then encoded as 0, 2 as 1 and so on.</p>
+
+<p>Assigning opcodes to instructions by the assembler is
+completely table driven. For details see appendix B.</p>
+
+<p><b>10.2 Procedure descriptors</b></p>
+
+<p>The procedure identifiers used in the interpreter are
+indices into a table of procedure descriptors. Each
+descriptor contains:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>the number of bytes to be reserved for locals at each
+invocation.</p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This is a pointer-sized integer.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="18%">
+
+<p>the start address of the procedure</p>
+</td>
+<td width="71%">
+</td>
+</table>
+
+<p><b>10.3 Load format</b></p>
+
+<p>The EM machine language load format defines the
+interface between the EM assembler/loader and the EM machine
+itself. A load file consists of a header, the program text
+to be executed, a description of the global data area and
+the procedure descriptor table, in this order. All integers
+in the load file are presented with the least significant
+byte first.</p>
+
+<p>The header has two parts: the first half (eight 16-bit
+integers) aids in selecting the correct EM machine or
+interpreter. Some EM machines, for instance, may have
+hardware floating point instructions. The header entries are
+as follows (bit 0 is rightmost):</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="6%"></td>
+<td width="18%">
+
+<p>magic number (07255)</p>
+</td>
+<td width="71%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="6%"></td>
+<td width="18%">
+
+<p>flag bits with the following meaning:</p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 0</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>TEST; test for integer overflow etc.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 1</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>PROFILE; for each source line: count the number of memory
+cycles executed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 2</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>FLOW; for each source line: set a bit in a bit map table
+if instructions on that line are executed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 3</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>COUNT; for each source line: increment a counter if that
+line is entered.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 4</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>REALS; set if a program uses floating point
+instructions.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>bit 5</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>EXTRA; more tests during compiler debugging.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>number of unresolved references.</p>
+</td>
+<td width="67%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>version number; used to detect obsolete EM load
+files.</p>
+</td>
+<td width="67%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>wordsize ; the number of bytes in each machine word.</p>
+</td>
+<td width="67%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>pointer size ; the number of bytes available for
+addressing.</p>
+</td>
+<td width="67%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>unused</p>
+</td>
+<td width="67%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8:</p>
+</td>
+<td width="6%"></td>
+<td width="22%">
+
+<p>unused</p>
+</td>
+<td width="67%">
+</td>
+</table>
+
+<p>The second part of the header (eight entries, of pointer
+size bytes each) describes the load file itself:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>NTEXT; the program text size in bytes.</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>NDATA; the number of load-file descriptors (see
+below).</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>NPROC; the number of entries in the procedure descriptor
+table.</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>ENTRY; procedure number of the procedure to start
+with.</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>NLINE; the maximum source line number.</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>SZDATA; the address of the lowest uninitialized data
+byte.</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>unused</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8:</p>
+</td>
+<td width="6%"></td>
+<td width="26%">
+
+<p>unused</p>
+</td>
+<td width="63%">
+</td>
+</table>
+
+<p>The program text consists of NTEXT bytes. NTEXT is
+always a multiple of the wordsize. The first byte of the
+program text is the first byte of the instruction address
+space, i.e. it has address 0. Pointers into the program text
+are found in the procedure descriptor table where relocation
+is simple and in the global data area. The initialization of
+the global data area allows easy relocation of pointers into
+both address spaces.</p>
+
+<p>The global data area is described by the NDATA
+descriptors. Each descriptor describes a number of
+consecutive words (of wordsize) and consists of a sequence
+of bytes. While reading the descriptors from the load file,
+one can initialize the global data area from low to high
+addresses. The size of the initialized data area is given by
+SZDATA, this number can be used to check the
+initialization.<br>
+The header of each descriptor consists of a byte, describing
+the type, and a count. The number of bytes used for this
+(unsigned) count depends on the type of the descriptor and
+is either a pointer-sized integer or one byte. The meaning
+of the count depends on the descriptor type. At load time an
+interpreter can perform any conversion deemed necessary,
+such as reordering bytes in integers and pointers and adding
+base addresses to pointers.</p>
+
+<p>In the following pictures we show a graphical notation
+of the initializers. The leftmost rectangle represents the
+leading byte.</p>
+
+<p>Fields marked with</p>
+
+<p align=center><img src="grohtml-97447.png"></p>
+
+<p><tt>------------------- | 0 | n | repeat last
+initialization n times -------------------</tt></p>
+
+<p><tt>--------- | 1 | m | m uninitialized words
+---------</tt></p>
+
+<p><tt>____________ / bytes \ ----------------- ----- | 2 |
+m | b | b |...| b | m initialized bytes -----------------
+-----</tt></p>
+
+<p><tt>_________ / word \ ----------------------- | 3 | m |
+w |... m initialized wordsized integers
+-----------------------</tt></p>
+
+<p><tt>_________ / pointer \ ----------------------- | 4 |
+m | p |... m initialized data pointers
+-----------------------</tt></p>
+
+<p><tt>_________ / pointer \ ----------------------- | 5 |
+m | p |... m initialized instruction pointers
+-----------------------</tt></p>
+
+<p><tt>____________ / bytes \ ------------------------- | 6
+| m | b | b |...| b | initialized integer of size m
+-------------------------</tt></p>
+
+<p><tt>____________ / bytes \ ------------------------- | 7
+| m | b | b |...| b | initialized unsigned of size m
+-------------------------</tt></p>
+
+<p><tt>____________ / string \ ------------------------- |
+8 | m | s | initialized float of size m
+-------------------------</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 0:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>If the last initialization initialized k bytes starting
+at address <i>a</i>, do the same initialization again n
+times, starting at <i>a</i>+k, <i>a</i>+2*k, ....
+<i>a</i>+n*k. This is the only descriptor whose starting
+byte is followed by an integer with the size of a pointer,
+in all other descriptors the first byte is followed by a
+one-byte count. This descriptor must be preceded by a
+descriptor of another type.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 1:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>Reserve m words, not explicitly initialized (BSS and
+HOL).</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 2:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m bytes following the descriptor header are
+initializers for the next m bytes of the global data area. m
+is divisible by the wordsize.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 3:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m words following the header are initializers for
+the next m words of the global data area.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 4:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m data address space pointers following the header
+are initializers for the next m data pointers in the global
+data area. Interpreters that represent EM pointers by target
+machine addresses must relocate all data pointers.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 5:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m instruction address space pointers following the
+header are initializers for the next m instruction pointers
+in the global data area. Interpreters that represent EM
+instruction pointers by target machine addresses must
+relocate these pointers.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 6:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m bytes following the header form a signed integer
+number with a size of m bytes, which is an initializer for
+the next m bytes of the global data area. m is governed by
+the same restrictions as for transfer of objects to/from
+memory.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 7:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The m bytes following the header form an unsigned
+integer number with a size of m bytes, which is an
+initializer for the next m bytes of the global data area. m
+is governed by the same restrictions as for transfer of
+objects to/from memory.</p>
+</td>
+<td width="51%">
+</td>
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>type 8:</p>
+</td>
+<td width="6%"></td>
+<td width="28%">
+
+<p>The header is followed by an ASCII string, null
+terminated, to initialize, in global data, a floating point
+number with a size of m bytes. m is governed by the same
+restrictions as for transfer of objects to/from memory. The
+ASCII string contains the notation of a real as used in the
+Pascal language.</p>
+</td>
+<td width="51%">
+</td>
+</table>
+
+<p>The NPROC procedure descriptors on the load file consist
+of an instruction space address (of pointer size) and an
+integer (of pointer size) specifying the number of bytes for
+locals.</p>
+
+<p>11</p>
+
+<p><b>11. EM ASSEMBLY LANGUAGE</b></p>
+
+<p>We use two representations for assembly language
+programs, one is in ASCII and the other is the compact
+assembly language. The latter needs less space than the
+first for the same program and therefore allows faster
+processing. Our only program accepting ASCII assembly
+language converts it to the compact form. All other programs
+expect compact assembly input. The first part of the chapter
+describes the ASCII assembly language and its semantics. The
+second part describes the syntax of the compact assembly
+language. The last part lists the EM instructions with the
+type of arguments allowed and an indication of the function.
+Appendix A gives a detailed description of the effect of all
+instructions in the form of a Pascal program.</p>
+
+<p><b>11.1 ASCII assembly language</b></p>
+
+<p>An assembly language program consists of a series of
+lines, each line may be blank, contain one
+(pseudo)instruction or contain one label. Input to the
+assembler is in lower case. Upper case is used in this
+document merely to distinguish keywords from the surrounding
+prose. Comment is allowed at the end of each line and starts
+with a semicolon &quot;;&quot;. This kind of comment does
+not exist in the compact form.</p>
+
+<p>Labels must be placed all by themselves on a line and
+start in column 1. There are two kinds of labels,
+instruction and data labels. Instruction labels are unsigned
+positive integers. The scope of an instruction label is its
+procedure.</p>
+
+<p>The pseudoinstructions CON, ROM and BSS may be preceded
+by a line containing a 1&minus;8 character data label, the
+first character of which is a letter, period or underscore.
+The period may only be followed by digits, the others may be
+followed by letters, digits and underscores. The use of the
+character &quot;.&quot; followed by a constant, which must
+be in the range 1 to 32767 (e.g. &quot;.40&quot;) is
+recommended for compiler generated programs. These labels
+are considered as a special case and handled more
+efficiently in compact assembly language (see below). Note
+that a data label on its own or two consecutive labels are
+not allowed.</p>
+
+<p>Each statement may contain an instruction mnemonic or
+pseudoinstruction. These must begin in column 2 or later
+(not column 1) and must be followed by a space, tab,
+semicolon or LF. Everything on the line following a
+semicolon is taken as a comment.</p>
+
+<p>Each input file contains one module. A module may
+contain many procedures, which may be nested. A procedure
+consists of a PRO statement, a (possibly empty) collection
+of instructions and pseudoinstructions and finally an END
+statement. Pseudoinstructions are also allowed between
+procedures. They do not belong to a specific procedure.</p>
+
+<p>All constants in EM are interpreted in the decimal base.
+The ASCII assembly language accepts constant expressions
+wherever constants are allowed. The operators recognized
+are: +, &minus;, *, % and / with the usual precedence order.
+Use of the parentheses ( and ) to alter the precedence order
+is allowed.</p>
+
+<p><i>11.1.1 Instruction arguments</i></p>
+
+<p>Unlike many other assembly languages, the EM assembly
+language requires all arguments of normal and
+pseudoinstructions to be either a constant or an identifier,
+but not a combination of these two. There is one exception
+to this rule: when a data label is used for initialization
+or as an instruction argument, expressions of the form
+&rsquo;label+constant&rsquo; and
+&rsquo;label-constant&rsquo; are allowed. This makes it
+possible to address, for example, the third word of a ten
+word BSS block directly. Thus LOE LABEL+4 is permitted and
+so is CON LABEL+3. The resulting address is must be in the
+same fragment as the label. It is not allowed to add or
+subtract from instruction labels or procedure identifiers,
+which certainly is not a severe restriction and greatly aids
+optimization.</p>
+
+<p>Instruction arguments can be constants, data labels,
+data labels offsetted by a constant, instruction labels and
+procedure identifiers. The range of integers allowed depends
+on the instruction. Most instructions allow only integers
+(signed or unsigned) that fit in a word. Arguments used as
+offsets to pointers should fit in a pointer-sized integer.
+Finally, arguments to LDC should fit in a double-word
+integer.</p>
+
+<p>Several instructions have two possible forms: with an
+explicit argument and with an implicit argument on top of
+the stack. The size of the implicit argument is the
+wordsize. The implicit argument is always popped before all
+other operands. For example: &rsquo;CMI 4&rsquo; specifies
+that two four-byte signed integers on top of the stack are
+to be compared. &rsquo;CMI&rsquo; without an argument
+expects a wordsized integer on top of the stack that
+specifies the size of the integers to be compared. Thus the
+following two sequences are equivalent:</p>
+
+<p align=center><img src="grohtml-97448.png"></p>
+
+<p>Section 11.1.6 shows the arguments allowed for each
+instruction.</p>
+
+<p><i>11.1.2 Pseudoinstruction arguments</i></p>
+
+<p>Pseudoinstruction arguments can be divided in two
+classes: Initializers and others. The following initializers
+are allowed: signed integer constants, unsigned integer
+constants, floating-point constants, strings, data labels,
+data labels offsetted by a constant, instruction labels and
+procedure identifiers.</p>
+
+<p>Constant initializers in BSS, HOL, CON and ROM
+pseudoinstructions can be followed by a letter I, U or F.
+This indicator specifies the type of the initializer:
+Integer, Unsigned or Float. If no indicator is present I is
+assumed. The size of the initializer is the wordsize unless
+the indicator is followed by an integer specifying the
+initializer&rsquo;s size. This integer is governed by the
+same restrictions as for transfer of objects to/from memory.
+As in instruction arguments, initializers include
+expressions of the form: &quot;LABEL+offset&quot; and
+&quot;LABEL&minus;offset&quot;. The offset must be an
+unsigned decimal constant. The &rsquo;IUF&rsquo; indicators
+cannot be used in the offsets.</p>
+
+<p>Data labels are referred to by their name.</p>
+
+<p>Strings are surrounded by double quotes (&quot;).
+Semicolon&rsquo;s in string do not indicate the start of
+comment. In the ASCII representation the escape character \
+(backslash) alters the meaning of subsequent character(s).
+This feature allows inclusion of zeroes, graphic characters
+and the double quote in the string. The following escape
+sequences exist:</p>
+
+<p align=center><img src="grohtml-97449.png"></p>
+
+<p>The escape <b>\ddd</b> consists of the backslash
+followed by 1, 2, or 3 octal digits specifying the value of
+the desired character. If the character following a
+backslash is not one of those specified, the backslash is
+ignored. Example: CON &quot;hello\012\0&quot;. Each string
+element initializes a single byte. The ASCII character set
+is used to map characters onto values.</p>
+
+<p>Instruction labels are referred to as *1, *2, etc. in
+both branch instructions and as initializers.</p>
+
+<p>The notation $procname means the identifier for the
+procedure with the specified name. This identifier has the
+size of a pointer.</p>
+
+<p><i>11.1.3 Notation</i></p>
+
+<p>First, the notation used for the arguments, classes of
+instructions and pseudoinstructions.</p>
+
+<p align=center><img src="grohtml-974410.png"></p>
+
+<p><i>11.1.4 Pseudoinstructions</i></p>
+
+<p><i>11.1.4.1 Storage declaration</i></p>
+
+<p>Initialized global data is allocated by the
+pseudoinstruction CON, which needs at least one argument.
+Each argument is used to allocate and initialize a number of
+consecutive bytes in data memory. The number of bytes to be
+allocated and the alignment depend on the type of the
+argument. For each argument, an integral number of words,
+determined by the argument type, is allocated and
+initialized.</p>
+
+<p>The pseudoinstruction ROM is the same as CON, except
+that it guarantees that the initialized words will not
+change during the execution of the program. This information
+allows optimizers to do certain calculations such as array
+indexing and subrange checking at compile time instead of at
+run time.</p>
+
+<p>The pseudoinstruction BSS allocates uninitialized global
+data or large blocks of data initialized by the same value.
+The first argument to this pseudo is the number of bytes
+required, which must be a multiple of the wordsize. The
+other arguments specify the value used for initialization
+and whether the initialization is only for convenience or a
+strict necessity. The pseudoinstruction HOL is similar to
+BSS in that it requests an (un)initialized global data
+block. Addressing of a HOL block, however, is quasi
+absolute. The first byte is addressed by 0, the second byte
+by 1 etc. in assembly language. The assembler/loader adds
+the base address of the HOL block to these numbers to obtain
+the absolute address in the machine language.</p>
+
+<p>The scope of a HOL block starts at the HOL pseudo and
+ends at the next HOL pseudo or at the end of a module
+whatever comes first. Each instruction falls in the scope of
+at most one HOL block, the current HOL block. It is not
+allowed to have more than one HOL block per procedure.</p>
+
+<p>The alignment restrictions are enforced by the
+pseudoinstructions. All initializers are aligned on a
+multiple of their size or the wordsize whichever is smaller.
+Strings form an exception, they are to be seen as a sequence
+of initializers each for one byte, i.e. strings are not
+padded with zero bytes. Switching to another type of
+fragment or placing a label forces word-alignment. There are
+three types of fragments in global data space: CON, ROM and
+BSS/HOL.</p>
+
+<p>BSS &lt;cst1&gt;,&lt;val&gt;,&lt;cst2&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Reserve &lt;cst1&gt; bytes. &lt;val&gt; is the value used
+to initialize the area. &lt;cst1&gt; must be a multiple of
+the size of &lt;val&gt;. &lt;cst2&gt; is 0 if the
+initialization is not strictly necessary, 1 if it is.</p>
+</td>
+</table>
+
+<p>HOL &lt;cst1&gt;,&lt;val&gt;,&lt;cst2&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Idem, but all following absolute global data references
+will refer to this block. Only one HOL is allowed per
+procedure, it has to be placed before the first
+instruction.</p>
+</td>
+</table>
+
+<p>CON &lt;val&gt;+</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Assemble global data words initialized with the
+&lt;val&gt; constants.</p>
+</td>
+</table>
+
+<p>ROM &lt;val&gt;+</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Idem, but the initialized data will never be changed by
+the program.</p>
+</td>
+</table>
+
+<p><i>11.1.4.2 Partitioning</i></p>
+
+<p>Two pseudoinstructions partition the input into
+procedures:</p>
+
+<p>PRO &lt;pro&gt;[,&lt;cst&gt;]</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Start of procedure. &lt;pro&gt; is the procedure name.
+&lt;cst&gt; is the number of bytes for locals. The number of
+bytes for locals must be specified in the PRO or END
+pseudoinstruction. When specified in both, they must be
+identical.</p>
+</td>
+</table>
+
+<p>END [&lt;cst&gt;]</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>End of Procedure. &lt;cst&gt; is the number of bytes for
+locals. The number of bytes for locals must be specified in
+either the PRO or END pseudoinstruction or both.</p>
+</td>
+</table>
+
+<p><i>11.1.4.3 Visibility</i></p>
+
+<p>Names of data and procedures in an EM module can either
+be internal or external. External names are known outside
+the module and are used to link several pieces of a program.
+Internal names are not known outside the modules they are
+used in. Other modules will not &rsquo;see&rsquo; an
+internal name.</p>
+
+<p>To reduce the number of passes needed, it must be known
+at the first occurrence whether a name is internal or
+external. If the first occurrence of a name is in a
+definition, the name is considered to be internal. If the
+first occurrence of a name is a reference, the name is
+considered to be external. If the first occurrence is in one
+of the following pseudoinstructions, the effect of the
+pseudo has precedence.</p>
+
+<p>EXA &lt;dlb&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>External name. &lt;dlb&gt; is known, possibly defined,
+outside this module. Note that &lt;dlb&gt; may be defined in
+the same module.</p>
+</td>
+</table>
+
+<p>EXP &lt;pro&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>External procedure identifier. Note that &lt;pro&gt; may
+be defined in the same module.</p>
+</td>
+</table>
+
+<p>INA &lt;dlb&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Internal name. &lt;dlb&gt; is internal to this module and
+must be defined in this module.</p>
+</td>
+</table>
+
+<p>INP &lt;pro&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Internal procedure. &lt;pro&gt; is internal to this
+module and must be defined in this module.</p>
+</td>
+</table>
+
+<p><i>11.1.4.4 Miscellaneous</i></p>
+
+<p>Two other pseudoinstructions provide miscellaneous
+features:</p>
+
+<p>EXC &lt;cst1&gt;,&lt;cst2&gt;</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Two blocks of instructions preceding this one are
+interchanged before being processed. &lt;cst1&gt; gives the
+number of lines of the first block. &lt;cst2&gt; gives the
+number of lines of the second one. Blank and pure comment
+lines do not count. This instruction is obsolete. Its use is
+strongly discouraged.</p>
+</td>
+</table>
+
+<p>MES &lt;cst&gt;[,&lt;par&gt;]*</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A special type of comment. Used by compilers to
+communicate with the optimizer, assembler, etc. as
+follows:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 0</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>An error has occurred, stop further processing.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 1</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Suppress optimization.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 2,&lt;cst1&gt;,&lt;cst2&gt;</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Use wordsize &lt;cst1&gt; and pointer size
+&lt;cst2&gt;.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES
+3,&lt;cst1&gt;,&lt;cst2&gt;,&lt;cst3&gt;,&lt;cst4&gt;</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Indicates that a local variable is never referenced
+indirectly. Used to indicate that a register may be used for
+a specific variable. &lt;cst1&gt; is offset in bytes from AB
+if positive and offset from LB if negative. &lt;cst2&gt;
+gives the size of the variable. &lt;cst3&gt; indicates the
+class of the variable. The following values are currently
+recognized:<br>
+0 The variable can be used for anything.<br>
+1 The variable is used as a loopindex.<br>
+2 The variable is used as a pointer.<br>
+3 The variable is used as a floating point number.<br>
+&lt;cst4&gt; gives the priority of the variable, higher
+numbers indicate better candidates.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 4,&lt;cst&gt;,&lt;str&gt;</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Number of source lines in file &lt;str&gt; (for
+profiler).</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 5</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Floating point used.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 6,&lt;val&gt;*</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Comment. Used to provide comments in compact assembly
+language.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 7,.....</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Reserved.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 8,&lt;pro&gt;[,&lt;dlb&gt;]...</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Library module. Indicates that the module may only be
+loaded if it is useful, that is, if it can satisfy any
+unresolved references during the loading process. May not be
+preceded by any other pseudo, except MES&rsquo;s.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 9,&lt;cst&gt;</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Guarantees that no more than &lt;cst&gt; bytes of
+parameters are accessed, either directly or indirectly.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 10,&lt;cst&gt;[,&lt;par&gt;]*</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>This message number is reserved for the global optimizer.
+It inserts these messages in its output as hints to
+backends. &lt;cst&gt; indicates the type of hint.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>MES 11</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Procedures containing this message are possible
+destinations of non-local goto&rsquo;s with the GTO
+instruction. Some backends keep locals in registers, the
+locals in this procedure should not be kept in registers and
+all registers containing locals of other procedures should
+be saved upon entry to this procedure.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Each backend is free to skip irrelevant MES pseudos.</p>
+</td>
+</table>
+
+<p><b>11.2 The Compact Assembly Language</b></p>
+
+<p>The assembler accepts input in a highly encoded form.
+This form is intended to reduce the amount of file transport
+between the front ends, optimizers and back ends, and also
+reduces the amount of storage required for storing
+libraries. Libraries are stored as archived compact assembly
+language, not machine language.</p>
+
+<p>When beginning to read the input, the assembler is in
+neutral state, and expects either a label or an instruction
+(including the pseudoinstructions). The meaning of the next
+byte(s) when in neutral state is as follows, where b1, b2
+etc. represent the succeeding bytes.</p>
+
+<p align=center><img src="grohtml-974411.png"></p>
+
+<p>After a label, the assembler is back in neutral state;
+it can immediately accept another label or an instruction in
+the next byte. No linefeeds are used to separate lines.</p>
+
+<p>If an opcode expects no arguments, the assembler is back
+in neutral state after reading the one byte containing the
+instruction number. If it has one or more arguments (only
+pseudos have more than 1), the arguments follow directly,
+encoded as follows:</p>
+
+<p align=center><img src="grohtml-974412.png"></p>
+
+<p>Absence of an optional argument is indicated by a
+special byte.</p>
+
+<p align=center><img src="grohtml-974413.png"></p>
+
+<p>The bytes specifying the value of a 16, 32 or 64 bit
+constant are presented in two&rsquo;s complement notation,
+with the least significant byte first. For example: the
+value of a 32 bit constant is ((s4*256+b3)*256+b2)*256+b1,
+where s4 is b4&minus;256 if b4 is greater than 128 else s4
+takes the value of b4. A &lt;string&gt; consists of a
+&lt;cst&gt; immediately followed by a sequence of bytes with
+length &lt;cst&gt;.</p>
+
+<p>The pseudoinstructions fall into several categories,
+depending on their arguments:</p>
+<pre>     Group 1 &minus; EXC, BSS, HOL have a known number of arguments
+     Group 2 &minus; EXA, EXP, INA, INP have a string as argument
+     Group 3 &minus; CON, MES, ROM have a variable number of various things
+     Group 4 &minus; END, PRO have a trailing optional argument.
+</pre>
+
+<p>Groups 1 and 2 use the encoding described above. Group 3
+also uses the encoding listed above, with an &lt;end&gt;
+byte after the last argument to indicate the end of the
+list. Group 4 uses an &lt;end&gt; byte if the trailing
+argument is not present.</p>
+
+<p align=center><img src="grohtml-974414.png"></p>
+
+<p><b>11.3 Assembly language instruction list</b></p>
+
+<p>For each instruction in the list the range of argument
+values in the assembly language is given. The column headed
+<i>assem</i> contains the mnemonics defined in 11.1.3. The
+following column specifies restrictions of the argument
+value. Addresses have to obey the restrictions mentioned in
+chapter 2. The classes of arguments are indicated by
+letters:</p>
+
+<p align=center><img src="grohtml-974415.png"></p>
+
+<p>The * at the rationale for <b>w</b> indicates that the
+argument can either be given as argument or on top of the
+stack. If the argument is omitted, the argument is fetched
+from the stack; it is assumed to be a wordsized unsigned
+integer. Instructions that check for undefined integer or
+floating-point values and underflow or overflow are
+indicated below by (*).</p>
+<pre>     GROUP 1 &minus; LOAD
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>LOC <b>c</b> :</p>
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load constant (i.e. push one word onto the stack)<br>
+LDC <b>d</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load double constant ( push two words )<br>
+LOL <b>l</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load word at <b>l</b>-th local (<b>l</b>&lt;0) or
+parameter (<b>l</b>&gt;=0)<br>
+LOE <b>g</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load external word <b>g</b><br>
+LIL <b>l</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load word pointed to by <b>l</b>-th local or
+parameter<br>
+LOF <b>f</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load offsetted (top of stack + <b>f</b> yield
+address)<br>
+LAL <b>l</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load address of local or parameter<br>
+LAE <b>g</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load address of external<br>
+LXL <b>n</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load lexical (address of LB <b>n</b> static levels
+back)<br>
+LXA <b>n</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load lexical (address of AB <b>n</b> static levels
+back)<br>
+LOI <b>o</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load indirect <b>o</b> bytes (address is popped from the
+stack)<br>
+LOS <b>w</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load indirect, <b>w</b>-byte integer on top of stack
+gives object size<br>
+LDL <b>l</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load double local or parameter (two consecutive words
+are stacked)<br>
+LDE <b>g</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load double external (two consecutive externals are
+stacked)<br>
+LDF <b>f</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load double offsetted (top of stack + <b>f</b> yield
+address)<br>
+LPI <b>p</b> :</p>
+</td>
+<td width="66%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="20%">
+
+<p>Load procedure identifier</p>
+</td>
+<td width="66%">
+</td>
+</table>
+<pre>     GROUP 2 &minus; STORE
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>STL <b>l</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store local or parameter<br>
+STE <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store external<br>
+SIL <b>l</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store into word pointed to by <b>l</b>-th local or
+parameter<br>
+STF <b>f</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store offsetted<br>
+STI <b>o</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store indirect <b>o</b> bytes (pop address, then
+data)<br>
+STS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store indirect, <b>w</b>-byte integer on top of stack
+gives object size<br>
+SDL <b>l</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store double local or parameter<br>
+SDE <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store double external<br>
+SDF <b>f</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store double offsetted</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 3 &minus; INTEGER ARITHMETIC
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ADI <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Addition (*)<br>
+SBI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Subtraction (*)<br>
+MLI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Multiplication (*)<br>
+DVI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Division (*)<br>
+RMI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Remainder (*)<br>
+NGI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Negate (two&rsquo;s complement) (*)<br>
+SLI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Shift left (*)<br>
+SRI <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Shift right (*)</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 4 &minus; UNSIGNED ARITHMETIC
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ADU <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Addition<br>
+SBU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Subtraction<br>
+MLU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Multiplication<br>
+DVU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Division<br>
+RMU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Remainder<br>
+SLU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Shift left<br>
+SRU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Shift right</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 5 &minus; FLOATING POINT ARITHMETIC
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ADF <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating add (*)<br>
+SBF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating subtract (*)<br>
+MLF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating multiply (*)<br>
+DVF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating divide (*)<br>
+NGF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating negate (*)<br>
+FIF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Floating multiply and split integer and fraction part
+(*)<br>
+FEF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Split floating number in exponent and fraction part
+(*)</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 6 &minus; POINTER ARITHMETIC
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ADP <b>f</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Add <b>f</b> to pointer on top of stack<br>
+ADS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Add <b>w</b>-byte value and pointer<br>
+SBS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Subtract pointers in same fragment and push diff as size
+<b>w</b> integer</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 7 &minus; INCREMENT/DECREMENT/ZERO
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>INC <b>&minus;</b> :</p>
+<td width="9%"></td>
+<td width="10%">
+
+<p>Increment word on top of stack by 1 (*)<br>
+INL <b>l</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Increment local or parameter (*)<br>
+INE <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Increment external (*)<br>
+DEC <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Decrement word on top of stack by 1 (*)<br>
+DEL <b>l</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Decrement local or parameter (*)<br>
+DEE <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Decrement external (*)<br>
+ZRL <b>l</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Zero local or parameter<br>
+ZRE <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Zero external<br>
+ZRF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Load a floating zero of size <b>w</b><br>
+ZER <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>Load <b>w</b> zero bytes</p>
+<pre>     GROUP 8 &minus; CONVERT    (stack:</td>
+<td width="79%">
+  source, source size, dest. size (top))
+
+
+       CII <b>&minus;</b> :</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert integer to integer (*)
+       CUI <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert unsigned to integer (*)
+       CFI <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert floating to integer (*)
+       CIF <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert integer to floating (*)
+       CUF <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert unsigned to floating (*)
+       CFF <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert floating to floating (*)
+       CIU <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert integer to unsigned
+       CUU <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert unsigned to unsigned
+       CFU <b>&minus;</b> :</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+ Convert floating to unsigned</td>
+<td width="79%">
+</td>
+</table>
+
+</pre>
+<pre>     GROUP 9 &minus; LOGICAL
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>AND <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Boolean and on two groups of <b>w</b> bytes<br>
+IOR <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Boolean inclusive or on two groups of <b>w</b> bytes<br>
+XOR <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Boolean exclusive or on two groups of <b>w</b> bytes<br>
+COM <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Complement (one&rsquo;s complement of top <b>w</b>
+bytes)<br>
+ROL <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Rotate left a group of <b>w</b> bytes<br>
+ROR <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Rotate right a group of <b>w</b> bytes</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 10 &minus; SETS
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>INN <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Bit test on <b>w</b> byte set (bit number on top of
+stack)<br>
+SET <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Create singleton <b>w</b> byte set with bit n on (n is
+top of stack)</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 11 &minus; ARRAY
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>LAR <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Load array element, descriptor contains integers of size
+<b>w</b><br>
+SAR <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store array element<br>
+AAR <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Load address of array element</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 12 &minus; COMPARE
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>CMI <b>w</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Compare <b>w</b> byte integers, Push negative, zero,
+positive for &lt;, = or &gt;<br>
+CMF <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Compare <b>w</b> byte reals<br>
+CMU <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Compare <b>w</b> byte unsigneds<br>
+CMS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Compare <b>w</b> byte values, can only be used for bit
+for bit equality test<br>
+CMP <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Compare pointers</p>
+
+<p>TLT <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if less, i.e. iff top of stack &lt; 0<br>
+TLE <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if less or equal, i.e. iff top of stack &lt;= 0<br>
+TEQ <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if equal, i.e. iff top of stack = 0<br>
+TNE <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if not equal, i.e. iff top of stack non zero<br>
+TGE <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if greater or equal, i.e. iff top of stack &gt;=
+0<br>
+TGT <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>True if greater, i.e. iff top of stack &gt; 0</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 13 &minus; BRANCH
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>BRA <b>b</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch unconditionally to label <b>b</b></p>
+
+<p>BLT <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch less (pop 2 words, branch if top &gt; second)<br>
+BLE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch less or equal<br>
+BEQ <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch equal<br>
+BNE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch not equal<br>
+BGE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch greater or equal<br>
+BGT <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch greater</p>
+
+<p>ZLT <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch less than zero (pop 1 word, branch negative)<br>
+ZLE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch less or equal to zero<br>
+ZEQ <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch equal zero<br>
+ZNE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch not zero<br>
+ZGE <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch greater or equal zero<br>
+ZGT <b>b</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Branch greater than zero</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 14 &minus; PROCEDURE CALL
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>CAI <b>&minus;</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Call procedure (procedure identifier on stack)<br>
+CAL <b>p</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Call procedure (with identifier <b>p</b>)<br>
+LFR <b>s</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Load function result<br>
+RET <b>z</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Return (function result consists of top <b>z</b>
+bytes)</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<pre>     GROUP 15 &minus; MISCELLANEOUS
+
+
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>ASP <b>f</b> :</p>
+<td width="13%"></td>
+<td width="6%">
+
+<p>Adjust the stack pointer by <b>f</b><br>
+ASS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Adjust the stack pointer by <b>w</b>-byte integer<br>
+BLM <b>z</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Block move <b>z</b> bytes; first pop destination addr,
+then source addr<br>
+BLS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Block move, size is in <b>w</b>-byte integer on top of
+stack<br>
+CSA <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Case jump; address of jump table at top of stack<br>
+CSB <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Table lookup jump; address of jump table at top of
+stack<br>
+DCH <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Follow dynamic chain, convert LB to LB of caller<br>
+DUP <b>s</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Duplicate top <b>s</b> bytes<br>
+DUS <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Duplicate top <b>w</b> bytes<br>
+EXG <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Exchange top <b>w</b> bytes<br>
+FIL <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>File name (external 4 := <b>g</b>)<br>
+GTO <b>g</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Non-local goto, descriptor at <b>g</b><br>
+LIM <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Load 16 bit ignore mask<br>
+LIN <b>n</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Line number (external 0 := <b>n</b>)<br>
+LNI <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Line number increment<br>
+LOR <b>r</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Load register (0=LB, 1=SP, 2=HP)<br>
+LPB <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Convert local base to argument base<br>
+MON <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Monitor call<br>
+NOP <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>No operation<br>
+RCK <b>w</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Range check; trap on error<br>
+RTT <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Return from trap<br>
+SIG <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Trap errors to proc identifier on top of stack, &minus;2
+resets default<br>
+SIM <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store 16 bit ignore mask<br>
+STR <b>r</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Store register (0=LB, 1=SP, 2=HP)<br>
+TRP <b>&minus;</b> :</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="6%">
+
+<p>Cause trap to occur (Error number on stack)</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>12</p>
+
+<p><b>A. EM INTERPRETER</b></p>
+<pre>{ This  is an interpreter for EM.  It serves as  the official machine
+  definition.  This interpreter must run on a machine which supports
+  arithmetic with words and memory offsets.
+
+ Certain aspects of the definition are over specified.  In particular:
+
+   1. The representation of  an  address on the stack  need not be the
+       numerical value of the memory location.
+
+   2. The state of  the stack is not defined  after a trap has aborted
+       an instruction in the middle.  For example, it is officially un-
+       defined  whether the second  operand of an  ADD  instruction has
+       been popped  or  not  if the  first one is undefined ( -32768 or
+       unsigned 32768).
+
+   3. The memory layout is implementation dependent. Only the most
+       basic checks are performed whenever memory is accessed.
+
+   4. The representation of an integer or set on the stack is not fixed
+       in bit order.
+
+   5. The format and existence of the procedure descriptors depends on
+       the implementation.
+
+   6. The result of the compare operators  CMI etc.  are -1, 0  and  1
+       here, but other negative  and  positive values will do  and they
+       need not be the same each time.
+
+   7. The shift count for SHL, SHR, ROL and ROR must be in the range 0
+       to object size in bits - 1.  The effect of a  count  not in this
+       range is undefined.
+}
+</pre>
+
+<p>13</p>
+
+<p><tt>{$i256} {$d+} program
+em(tables,prog,input,output);</tt></p>
+
+<p><tt>label 8888,9999;</tt></p>
+
+<p><tt>const t15 = 32768; { 2**15 } t15m1 = 32767; { 2**15
+-1 } t16 = 65536; { 2**16 } t16m1 = 65535; { 2**16 -1 }
+t31m1 = 2147483647; { 2**31 -1 }</tt></p>
+
+<p><tt>wsize = 2; { number of bytes in a word } asize = 2;
+{ number of bytes in an address } fsize = 4; { number of
+bytes in a floating point number } maxret =4; { number of
+words in the return value area }</tt></p>
+
+<p><tt>signbit = t15; { the power of two indicating the
+sign bit } negoff = t16; { the next power of two } maxsint =
+t15m1; { the maximum signed integer } maxuint = t16m1; { the
+maximum unsigned integer } maxdbl = t31m1; { the maximum
+double signed integer } maxadr = t16m1; { the maximum
+address } maxoffs = t15m1; { the maximum offset from an
+address } maxbitnr= 15; { the number of the highest bit
+}</tt></p>
+
+<p><tt>lineadr = 0; { address of the line number } fileadr
+= 4; { address of the file name } maxcode = 8191; { highest
+byte in code address space } maxdata = 8191; { highest byte
+in data address space }</tt></p>
+
+<p><tt>{ format of status save area } statd = 4; { how far
+is static link from lb } dynd = 2; { how far is dynamic link
+from lb } reta = 0; { how far is the return address from lb
+} savsize = 4; { size of save area in bytes }</tt></p>
+
+<p><tt>{ procedure descriptor format } pdlocs = 0; { offset
+for size of local variables in bytes } pdbase = asize; {
+offset for the procedure base } pdsize = 4; { size of
+procedure descriptor in bytes = 2*asize }</tt></p>
+
+<p><tt>{ header words } NTEXT = 1; NDATA = 2; NPROC = 3;
+ENTRY = 4; NLINE = 5; SZDATA = 6;</tt></p>
+
+<p><tt>escape1 = 254; { escape to secondary opcodes }
+escape2 = 255; { escape to tertiary opcodes } undef =
+signbit; { the range of integers is -32767 to +32767
+}</tt></p>
+
+<p><tt>{ error codes } EARRAY = 0; ERANGE = 1; ESET = 2;
+EIOVFL = 3; EFOVFL = 4; EFUNFL = 5; EIDIVZ = 6; EFDIVZ = 7;
+EIUND = 8; EFUND = 9; ECONV = 10; ESTACK = 16; EHEAP = 17;
+EILLINS = 18; EODDZ = 19; ECASE = 20; EMEMFLT = 21; EBADPTR
+= 22; EBADPC = 23; EBADLAE = 24; EBADMON = 25; EBADLIN = 26;
+EBADGTO = 27;</tt></p>
+
+<p>14</p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Declarations }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>type bitval= 0..1; { one bit } bitnr= 0..maxbitnr; {
+bits in machine words are numbered 0 to 15 } byte= 0..255; {
+memory is an array of bytes } adr= {0..maxadr} long; { the
+range of addresses } word= {0..maxuint} long;{ the range of
+unsigned integers } offs= -maxoffs..maxoffs; { the range of
+signed offsets from addresses } size= 0..maxoffs; { the
+range of sizes is the positive offsets } sword=
+{-signbit..maxsint} long; { the range of signed integers }
+full= {-maxuint..maxuint} long; { intermediate results need
+this range } double={-maxdbl..maxdbl} long; { double
+precision range } bftype= (andf,iorf,xorf); { tells which
+boolean operator needed } insclass=(prim,second,tert); {
+tells which opcode table is in use }
+instype=(implic,explic); { does opcode have implicit or
+explicit operand } iflags= (mini,short,sbit,wbit,zbit,ibit);
+ifset= set of iflags;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>mnem = ( NON,</tt></p>
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>AAR, ADF, ADI, ADP, ADS, ADU,XAND, ASP, ASS,
+BEQ,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>BGE, BGT, BLE, BLM, BLS, BLT, BNE, BRA, CAI,
+CAL,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>CFF, CFI, CFU, CIF, CII, CIU, CMF, CMI, CMP,
+CMS,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>CMU, COM, CSA, CSB, CUF, CUI, CUU, DCH, DEC,
+DEE,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>DEL, DUP, DUS, DVF, DVI, DVU, EXG, FEF, FIF,
+FIL,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>GTO, INC, INE, INL, INN, IOR, LAE, LAL, LAR,
+LDC,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>LDE, LDF, LDL, LFR, LIL, LIM, LIN, LNI, LOC,
+LOE,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>LOF, LOI, LOL, LOR, LOS, LPB, LPI, LXA, LXL,
+MLF,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>MLI, MLU, MON, NGF, NGI, NOP, RCK, RET, RMI,
+RMU,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>ROL, ROR, RTT, SAR, SBF, SBI, SBS, SBU, SDE,
+SDF,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>SDL,XSET, SIG, SIL, SIM, SLI, SLU, SRI, SRU,
+STE,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>STF, STI, STL, STR, STS, TEQ, TGE, TGT, TLE,
+TLT,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>TNE, TRP, XOR, ZEQ, ZER, ZGE, ZGT, ZLE, ZLT,
+ZNE,</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>ZRE, ZRF, ZRL);</tt></p>
+
+<p><tt>dispatch = record</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>iflag: ifset;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>instr: mnem;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>case instype of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>implic: (implicit:sword);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>explic: (ilength:byte);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+</table>
+
+<p><tt>var code: packed array[0..maxcode] of byte; { code
+space } data: packed array[0..maxdata] of byte; { data space
+} retarea: array[1..maxret ] of word; { return area }
+pc,lb,sp,hp,pd: adr; { internal machine registers } i:
+integer; { integer scratch variable } s,t :word; { scratch
+variables } sz:size; { scratch variables } ss,st: sword; {
+scratch variables } k :double; { scratch variables } j:size;
+{ scratch variable used as index } a,b:adr; { scratch
+variable used for addresses } dt,ds:double; { scratch
+variables for double precision } rt,rs,x,y:real; { scratch
+variables for real } found:boolean; { scratch } opcode:
+byte; { holds the opcode during execution } iclass:
+insclass; { true for escaped opcodes } dispat:
+array[insclass,byte] of dispatch; retsize:size; { holds size
+of last LFR } insr: mnem; { holds the instruction number }
+halted: boolean; { normally false } exitstatus:word; {
+parameter of MON 1 } ignmask:word; { ignore mask for traps }
+uerrorproc:adr; { number of user defined error procedure }
+intrap:boolean; { Set when executing trap(), to catch
+recursive calls} trapval:byte; { Set to number of last trap
+} header: array[1..8] of adr;</tt></p>
+
+<p><tt>tables: text; { description of EM instructions }
+prog: file of byte; { program and initialized data
+}</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Various check routines }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>{ Only the most basic checks are performed. These
+routines are inherently implementation dependent. }</tt></p>
+
+<p><tt>procedure trap(n:byte); forward;</tt></p>
+
+<p><tt>procedure memadr(a:adr); begin if (a&gt;maxdata) or
+((a&lt;sp) and (a&gt;=hp)) then trap(EMEMFLT) end;</tt></p>
+
+<p><tt>procedure wordadr(a:adr); begin memadr(a); if (a mod
+wsize&lt;&gt;0) then trap(EBADPTR) end;</tt></p>
+
+<p><tt>procedure chkadr(a:adr; s:size); begin memadr(a);
+memadr(a+s-1); { assumption: size is ok } if s&lt;wsize then
+begin if a mod s&lt;&gt;0 then trap(EBADPTR) end else if a
+mod wsize&lt;&gt;0 then trap(EBADPTR) end;</tt></p>
+
+<p><tt>procedure newpc(a:double); begin if (a&lt;0) or
+(a&gt;maxcode) then trap(EBADPC); pc:=a end;</tt></p>
+
+<p><tt>procedure newsp(a:adr); begin if (a&gt;lb) or
+(a&lt;hp) or (a mod wsize&lt;&gt;0) then trap(ESTACK); sp:=a
+end;</tt></p>
+
+<p><tt>procedure newlb(a:adr); begin if (a&lt;sp) or (a mod
+wsize&lt;&gt;0) then trap(ESTACK); lb:=a end;</tt></p>
+
+<p><tt>procedure newhp(a:adr); begin if (a&gt;sp) or
+(a&gt;maxdata+1) or (a mod wsize&lt;&gt;0) then trap(EHEAP)
+else hp:=a end;</tt></p>
+
+<p><tt>function argc(a:double):sword; begin if
+(a&lt;-signbit) or (a&gt;maxsint) then trap(EILLINS);
+argc:=a end;</tt></p>
+
+<p><tt>function argd(a:double):double; begin if
+(a&lt;-maxdbl) or (a&gt;maxdbl) then trap(EILLINS); argd:=a
+end;</tt></p>
+
+<p><tt>function argl(a:double):offs; begin if
+(a&lt;-maxoffs) or (a&gt;maxoffs) then trap(EILLINS);
+argl:=a end;</tt></p>
+
+<p><tt>function argg(k:double):adr; begin if (k&lt;0) or
+(k&gt;maxadr) then trap(EILLINS); argg:=k end;</tt></p>
+
+<p><tt>function argf(a:double):offs; begin if
+(a&lt;-maxoffs) or (a&gt;maxoffs) then trap(EILLINS);
+argf:=a end;</tt></p>
+
+<p><tt>function argn(a:double):word; begin if (a&lt;0) or
+(a&gt;maxuint) then trap(EILLINS); argn:=a end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function args(a:double):size; begin if (a&lt;=0) or
+(a&gt;maxoffs)</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then trap(EODDZ)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else if (a mod wsize)&lt;&gt;0 then trap(EODDZ);
+args:=a ; end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function argz(a:double):size; begin if (a&lt;0) or
+(a&gt;maxoffs)</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then trap(EODDZ)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else if (a mod wsize)&lt;&gt;0 then trap(EODDZ);
+argz:=a ; end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function argo(a:double):size; begin if (a&lt;=0) or
+(a&gt;maxoffs)</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then trap(EODDZ)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else if (a mod wsize&lt;&gt;0) and (wsize mod
+a&lt;&gt;0) then trap(EODDZ); argo:=a ; end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function argw(a:double):size; begin if (a&lt;=0) or
+(a&gt;maxoffs) or (a&gt;maxuint)</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then trap(EODDZ)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else if (a mod wsize)&lt;&gt;0 then trap(EODDZ);
+argw:=a ; end;</tt></p>
+</td>
+</table>
+
+<p><tt>function argp(a:double):size; begin if (a&lt;0) or
+(a&gt;=header[NPROC]) then trap(EILLINS); argp:=a
+end;</tt></p>
+
+<p><tt>function argr(a:double):word; begin if (a&lt;0) or
+(a&gt;2) then trap(EILLINS); argr:=a end;</tt></p>
+
+<p><tt>procedure argwf(s:double); begin if
+argw(s)&lt;&gt;fsize then trap(EILLINS) end;</tt></p>
+
+<p><tt>function szindex(s:double):integer; begin
+s:=argw(s); if (s mod wsize &lt;&gt; 0) or (s&gt;2*wsize)
+then trap(EILLINS); szindex:=s div wsize end;</tt></p>
+
+<p><tt>function locadr(l:double):adr; begin l:=argl(l); if
+l&lt;0 then locadr:=lb+l else locadr:=lb+l+savsize
+end;</tt></p>
+
+<p><tt>function signwd(w:word):sword; begin if w = undef
+then trap(EIUND); if w &gt;= signbit then signwd:=w-negoff
+else signwd:=w end;</tt></p>
+
+<p><tt>function dosign(w:word):sword; begin if w &gt;=
+signbit then dosign:=w-negoff else dosign:=w end;</tt></p>
+
+<p><tt>function unsign(w:sword):word; begin if w&lt;0 then
+unsign:=w+negoff else unsign:=w end;</tt></p>
+
+<p><tt>function chopw(dw:double):word; begin chopw:=dw mod
+negoff end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function fitsw(w:full;trapno:byte):word; { checks
+whether value fits in signed word, returns unsigned
+representation} begin if (w&gt;maxsint) or (w&lt;-signbit)
+then begin trap(trapno); if w&lt;0 then fitsw:=negoff-
+(-w)mod negoff</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>else fitsw:=w mod negoff; end else fitsw:=unsign(w)
+end;</tt></p>
+</td>
+</table>
+
+<p><tt>function fitd(w:full):double; begin if abs(w) &gt;
+maxdbl then trap(ECONV); fitd:=w end;</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Memory access routines }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>{ memw returns a machine word as an unsigned integer
+memb returns a single byte as a positive integer: 0 &lt;=
+memb &lt;= 255 mems(a,s) fetches an object smaller than a
+word and returns a word store(a,v) stores the word v at
+machine address a storea(a,v) stores the address v at
+machine address a storeb(a,b) stores the byte b at machine
+address a stores(a,s,v) stores the s least significant bytes
+of a word at address a memi returns an offset from the
+instruction space Note that the procedure descriptors are
+part of instruction space. nextpc returns the next byte
+addressed by pc, incrementing pc</tt></p>
+
+<p><tt>lino changes the line number word. filna changes the
+pointer to the file name.</tt></p>
+
+<p><tt>All routines check to make sure the address is
+within range and valid for the size of the object. If an
+addressing error is found, a trap occurs. }</tt></p>
+
+<p><tt>function memw(a:adr):word; var b:word; i:integer;
+begin wordadr(a); b:=0; for i:=wsize-1 downto 0 do b:=256*b
++ data[a+i] ; memw:=b end;</tt></p>
+
+<p><tt>function memd(a:adr):double; { Always signed } var
+b:double; i:integer; begin wordadr(a); b:=data[a+2*wsize-1];
+if b&gt;=128 then b:=b-256; for i:=2*wsize-2 downto 0 do
+b:=256*b + data[a+i] ; memd:=b end;</tt></p>
+
+<p><tt>function mema(a:adr):adr; var b:adr; i:integer;
+begin wordadr(a); b:=0; for i:=asize-1 downto 0 do b:=256*b
++ data[a+i] ; mema:=b end;</tt></p>
+
+<p><tt>function mems(a:adr;s:size):word; var i:integer;
+b:word; begin chkadr(a,s); b:=0; for i:=1 to s do
+b:=b*256+data[a+s-i]; mems:=b end;</tt></p>
+
+<p><tt>function memb(a:adr):byte; begin memadr(a);
+memb:=data[a] end;</tt></p>
+
+<p><tt>procedure store(a:adr; x:word); var i:integer; begin
+wordadr(a); for i:=0 to wsize-1 do begin data[a+i]:=x mod
+256; x:=x div 256 end end;</tt></p>
+
+<p><tt>procedure storea(a:adr; x:adr); var i:integer; begin
+wordadr(a); for i:=0 to asize-1 do begin data[a+i]:=x mod
+256; x:=x div 256 end end;</tt></p>
+
+<p><tt>procedure stores(a:adr;s:size;v:word); var
+i:integer; begin chkadr(a,s); for i:=0 to s-1 do begin
+data[a+i]:=v mod 256; v:=v div 256 end; end;</tt></p>
+
+<p><tt>procedure storeb(a:adr; b:byte); begin memadr(a);
+data[a]:=b end;</tt></p>
+
+<p><tt>function memi(a:adr):adr; var b:adr; i:integer;
+begin if (a mod wsize&lt;&gt;0) or (a+asize-1&gt;maxcode)
+then trap(EBADPTR); b:=0; for i:=asize-1 downto 0 do
+b:=256*b + code[a+i] ; memi:=b end;</tt></p>
+
+<p><tt>function nextpc:byte; begin if pc&gt;=pd then
+trap(EBADPC); nextpc:=code[pc]; newpc(pc+1) end;</tt></p>
+
+<p><tt>procedure lino(w:word); begin store(lineadr,w)
+end;</tt></p>
+
+<p><tt>procedure filna(a:adr); begin storea(fileadr,a)
+end;</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Stack Manipulation Routines }
+{---------------------------------------------------------------------------}</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>{ push puts a word on the stack pushsw takes a
+signed one word integer and pushes it on the stack pop
+removes a machine word from the stack and delivers it as a
+word popsw removes a machine word from the stack and
+delivers a signed integer pusha pushes an address on the
+stack popa removes a machine word from the stack and
+delivers it as an address pushd pushes a double precision
+number on the stack popd removes two machine words and
+returns a double precision integer pushr pushes a float
+(floating point) number on the stack popr removes several
+machine words and returns a float number pushx puts an
+object of arbitrary size on the stack popx removes an object
+of arbitrary size</tt></p>
+</td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>}</tt></p>
+</td>
+</table>
+
+<p><tt>procedure push(x:word); begin newsp(sp-wsize);
+store(sp,x) end;</tt></p>
+
+<p><tt>procedure pushsw(x:sword); begin newsp(sp-wsize);
+store(sp,unsign(x)) end;</tt></p>
+
+<p><tt>function pop:word; begin pop:=memw(sp);
+newsp(sp+wsize) end;</tt></p>
+
+<p><tt>function popsw:sword; begin popsw:=signwd(pop)
+end;</tt></p>
+
+<p><tt>procedure pusha(x:adr); begin newsp(sp-asize);
+storea(sp,x) end;</tt></p>
+
+<p><tt>function popa:adr; begin popa:=mema(sp);
+newsp(sp+asize) end;</tt></p>
+
+<p><tt>procedure pushd(y:double); begin { push double
+integer onto the stack } newsp(sp-2*wsize) end;</tt></p>
+
+<p><tt>function popd:double; begin { pop double integer
+from the stack } newsp(sp+2*wsize); popd:=0 end;</tt></p>
+
+<p><tt>procedure pushr(z:real); begin { Push a float onto
+the stack } newsp(sp-fsize) end;</tt></p>
+
+<p><tt>function popr:real; begin { pop float from the stack
+} newsp(sp+fsize); popr:=0.0 end;</tt></p>
+
+<p><tt>procedure pushx(objsize:size; a:adr); var i:integer;
+begin if objsize&lt;wsize then push(mems(a,objsize)) else
+for i:=1 to objsize div wsize do
+push(memw(a+objsize-wsize*i)) end;</tt></p>
+
+<p><tt>procedure popx(objsize:size; a:adr); var i:integer;
+begin if objsize&lt;wsize then stores(a,objsize,pop) else
+for i:=1 to objsize div wsize do store(a-wsize+wsize*i,pop)
+end;</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Bit manipulation routines (extract, shift, rotate) }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>procedure sleft(var w:sword); { 1 bit left shift }
+begin w:= dosign(fitsw(2*w,EIOVFL)) end;</tt></p>
+
+<p><tt>procedure suleft(var w:word); { 1 bit left shift }
+begin w := chopw(2*w) end;</tt></p>
+
+<p><tt>procedure sdleft(var d:double); { 1 bit left shift }
+begin { shift two word signed integer } end;</tt></p>
+
+<p><tt>procedure sright(var w:sword); { 1 bit right shift
+with sign extension } begin if w &gt;= 0 then w := w div 2
+else w := (w-1) div 2 end;</tt></p>
+
+<p><tt>procedure suright(var w:word); { 1 bit right shift
+without sign extension } begin w := w div 2 end;</tt></p>
+
+<p><tt>procedure sdright(var d:double); { 1 bit right shift
+} begin { shift two word signed integer } end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure rleft(var w:word); { 1 bit left rotate }
+begin if w &gt;= t15</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then w:=(w-t15)*2 + 1</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else w:=w*2 end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure rright(var w:word); { 1 bit right rotate }
+begin if w mod 2 = 1</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>then w:=w div 2 + t15</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else w:=w div 2 end;</tt></p>
+</td>
+</table>
+
+<p><tt>function sextend(w:word;s:size):word; var i:size;
+begin for i:=1 to (wsize-s)*8 do rleft(w); for i:=1 to
+(wsize-s)*8 do sright(w); sextend:=w; end;</tt></p>
+
+<p><tt>function bit(b:bitnr; w:word):bitval; { return bit b
+of the word w } var i:bitnr; begin for i:= 1 to b do
+rright(w); bit:= w mod 2 end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>function bf(ty:bftype; w1,w2:word):word; { return
+boolean fcn of 2 words } var i:bitnr; j:word; begin j:=0;
+for i:= maxbitnr downto 0 do</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin j := 2*j;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case ty of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>andf: if bit(i,w1)+bit(i,w2) = 2 then
+j:=j+1;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>iorf: if bit(i,w1)+bit(i,w2) &gt; 0 then
+j:=j+1;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>xorf: if bit(i,w1)+bit(i,w2) = 1 then
+j:=j+1</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; bf:=j end;</tt></p>
+</td>
+</table>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Array indexing }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>function arraycalc(c:adr):adr; { subscript
+calculation } var j:full; objsize:size; a:adr; begin j:=
+popsw - signwd(memw(c)); if (j&lt;0) or (j&gt;memw(c+wsize))
+then trap(EARRAY); objsize := argo(memw(c+wsize+wsize)); a
+:= j*objsize+popa; chkadr(a,objsize); arraycalc:=a
+end;</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Double and Real Arithmetic }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>{ All routines for doubles and floats are dummy
+routines, since the format of doubles and floats is not
+defined in EM. }</tt></p>
+
+<p><tt>function doadi(ds,dt:double):double; begin { add two
+doubles } doadi:=0 end;</tt></p>
+
+<p><tt>function dosbi(ds,dt:double):double; begin {
+subtract two doubles } dosbi:=0 end;</tt></p>
+
+<p><tt>function domli(ds,dt:double):double; begin {
+multiply two doubles } domli:=0 end;</tt></p>
+
+<p><tt>function dodvi(ds,dt:double):double; begin { divide
+two doubles } dodvi:=0 end;</tt></p>
+
+<p><tt>function dormi(ds,dt:double):double; begin { modulo
+of two doubles } dormi:=0 end;</tt></p>
+
+<p><tt>function dongi(ds:double):double; begin { negative
+of a double } dongi:=0 end;</tt></p>
+
+<p><tt>function doadf(x,y:real):real; begin { add two
+floats } doadf:=0.0 end;</tt></p>
+
+<p><tt>function dosbf(x,y:real):real; begin { subtract two
+floats } dosbf:=0.0 end;</tt></p>
+
+<p><tt>function domlf(x,y:real):real; begin { multiply two
+floats } domlf:=0.0 end;</tt></p>
+
+<p><tt>function dodvf(x,y:real):real; begin { divide two
+floats } dodvf:=0.0 end;</tt></p>
+
+<p><tt>function dongf(x:real):real; begin { negate a float
+} dongf:=0.0 end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure dofif(x,y:real;var intpart,fraction:real);
+begin { dismember x*y into integer and fractional parts }
+intpart:=0.0; { integer part of x*y, same sign as x*y }
+fraction:=0.0;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>{ fractional part of x*y, 0&lt;=abs(fraction)&lt;1
+and same sign as x*y } end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure dofef(x:real;var mantissa:real;var
+exponent:sword); begin { dismember x into mantissa and
+exponent parts } mantissa:=0.0; { mantissa of x , &gt;= 1/2
+and &lt;1 } exponent:=0; { base 2 exponent of x }
+end;</tt></p>
+
+<p>15</p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Trap and Call }
+{---------------------------------------------------------------------------}</tt></p>
+
+<p><tt>procedure call(p:adr); { Perform the call } begin
+pusha(lb);pusha(pc); newlb(sp);newsp(sp - memi(pd + pdsize*p
++ pdlocs)); newpc(memi(pd + pdsize*p+ pdbase)) end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure dotrap(n:byte); var i:size; begin if
+(uerrorproc=0) or intrap then begin if intrap then</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>writeln(&rsquo;Recursive trap, first trap number was
+&rsquo;, trapval:1); writeln(&rsquo;Error &rsquo;, n:1);
+writeln(&rsquo;With&rsquo;,ord(insr):4,&rsquo; arg
+&rsquo;,k:1); goto 9999 end; { Deposit all interpreter
+variables that need to be saved on the stack. This includes
+all scratch variables that can be in use at the moment and (
+not possible in this interpreter ) the internal address of
+the interpreter where the error occurred. This would make it
+possible to execute an RTT instruction totally transparent
+to the user program. It can, for example, occur within an
+ADD instruction that both operands are undefined and that
+the result overflows. Although this will generate 3 error
+traps it must be possible to ignore them all. }
+intrap:=true; trapval:=n; for i:=retsize div wsize downto 1
+do push(retarea[i]); push(retsize); { saved return area }
+pusha(mema(fileadr)); { saved current file name pointer }
+push(memw(lineadr)); { saved line number } push(n); { push
+error number } a:=argp(uerrorproc); uerrorproc:=0; { reset
+signal } call(a); { call the routine } intrap:=false; {
+Don&rsquo;t catch recursive traps anymore } goto 8888; {
+reenter main loop } end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure trap; { This routine is invoked for
+overflow, and other run time errors. For non-fatal errors,
+trap returns to the calling routine } begin if n&gt;=16 then
+dotrap(n) else if bit(n,ignmask)=0 then dotrap(n);
+end;</tt></p>
+
+<p><tt>procedure dortt; { The restoration of file address
+and line number is not essential. The restoration of the
+return save area is. } var i:size; n:word; begin newsp(lb);
+lb:=maxdata+1 ; { to circumvent ESTACK for the popa + pop }
+newpc(popa); newlb(popa); { So far a plain RET 0 } n:=pop;
+if (n&gt;=16) and (n&lt;64) then goto 9999 ; lino(pop);
+filna(popa); retsize:=pop; for i:=1 to retsize div wsize do
+retarea[i]:=pop ; end;</tt></p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ monitor calls }
+{---------------------------------------------------------------------------}</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure domon(entry:word); var index:
+1..63;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>dummy: double;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>count,rwptr: adr;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>token: byte;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>i: integer; begin if (entry&lt;=0) or (entry&gt;63)
+then entry:=63 ; index:=entry; case index of 1: begin { exit
+} exitstatus:=pop; halted:=true end; 3: begin { read }
+dummy:=pop; { All input is from stdin }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>rwptr:=popa; count:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>i:=0 ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>while (not eof(input)) and (i&lt;count) do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if eoln(input) then begin storeb(rwptr,10) ;
+count:=i end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else storeb(rwptr,ord(input^)) ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>get(input); rwptr:=rwptr+1 ; i:=i+1 ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>pusha(i); push(0) end; 4: begin { write }
+dummy:=pop; { All output is to stdout }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>rwptr:=popa; count:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=1 to count do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin token:=memb(rwptr); rwptr:=rwptr+1 ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if token=10 then writeln else
+write(chr(token))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>pusha(count);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>push(0) end; 54: begin { ioctl, faked }
+dummy:=popa;dummy:=popa;dummy:=pop;push(0) end ; 2, 5, 6, 7,
+8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+53, 55, 56, 57, 58, 59, 60, 61, 62: begin push(22); push(22)
+end; 63: { exists only for the trap } trap(EBADMON) end
+end;</tt></p>
+</td>
+</table>
+
+<p>16</p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Initialization and debugging }
+{---------------------------------------------------------------------------}</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure doident; { print line number and file name
+} var a:adr; i,c:integer; found:boolean; begin
+write(&rsquo;at line &rsquo;,memw(lineadr):1,&rsquo;
+&rsquo;); a:=mema(fileadr); if a&lt;&gt;0 then begin i:=20;
+found:=false; while (i&lt;&gt;0) and not found do begin
+c:=memb(a); a:=a+1; found:=true; i:=i-1; if (c&gt;=48) and
+(c&lt;=57) then</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin found:=false;
+write(chr(ord(&rsquo;0&rsquo;)+c-48)) end; if (c&gt;=65) and
+(c&lt;=90) then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin found:=false;
+write(chr(ord(&rsquo;A&rsquo;)+c-65)) end; if (c&gt;=97) and
+(c&lt;=122) then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin found:=false;
+write(chr(ord(&rsquo;a&rsquo;)+c-97)) end; end; end;
+writeln; end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure initialize; { start the ball rolling } {
+This is not part of the machine definition } var cset:set of
+char; f:ifset; iclass:insclass; insno:byte; nops:integer;
+opcode:byte; i,j,n:integer; wtemp:sword; count:integer;
+repc:adr; nexta,firsta:adr; elem:byte; amount,ofst:size;
+c:char;</tt></p>
+
+<p><tt>function readb(n:integer):double; var b:byte; begin
+read(prog,b); if n&gt;1 then readb:=readb(n-1)*256+b else
+readb:=b end;</tt></p>
+
+<p><tt>function readbyte:byte; begin readbyte:=readb(1)
+end;</tt></p>
+
+<p><tt>function readword:word; begin readword:=readb(wsize)
+end;</tt></p>
+
+<p><tt>function readadr:adr; begin readadr:=readb(asize)
+end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>function ifind(ordinal:byte):mnem; var
+loopvar:mnem;</tt></p>
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>found:boolean; begin ifind:=NON; loopvar:=insr;
+found:=false; repeat</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>if ordinal=ord(loopvar) then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin found:=true; ifind:=loopvar end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>if loopvar&lt;&gt;ZRL then loopvar:=succ(loopvar)
+else loopvar:=NON; until found or (loopvar=insr) ;
+end;</tt></p>
+
+<p><tt>procedure readhdr; type hdrw=0..32767 ; { 16 bit
+header words } var hdr: hdrw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>i: integer; begin for i:=0 to 7 do begin
+hdr:=readb(2);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>case i of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>0: if hdr&lt;&gt;3757 then { 07255 }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin writeln(&rsquo;Not an em load file&rsquo;);
+halt end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>2: if hdr&lt;&gt;0 then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin writeln(&rsquo;Unsolved references&rsquo;);
+halt end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>3: if hdr&lt;&gt;3 then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin writeln(&rsquo;Incorrect load file
+version&rsquo;); halt end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>4: if hdr&lt;&gt;wsize then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin writeln(&rsquo;Incorrect word size&rsquo;);
+halt end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>5: if hdr&lt;&gt;asize then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin writeln(&rsquo;Incorrect pointer size&rsquo;);
+halt end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>1,6,7:;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure noinit; begin writeln(&rsquo;Illegal
+initialization&rsquo;); halt end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>procedure readint(a:adr;s:size); var i:size; begin {
+construct integer out of byte sequence } for i:=1 to s do {
+construct the value and initialize at a }</tt></p>
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>begin storeb(a,readbyte); a:=a+1 end end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure readuns(a:adr;s:size); begin { construct
+unsigned out of byte sequence } readint(a,s) { identical to
+readint } end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>procedure readfloat(a:adr;s:size); var i:size;
+b:byte; begin { construct float out of string} if
+(s&lt;&gt;4) and (s&lt;&gt;8) then noinit; i:=0; repeat {
+eat the bytes, construct the value and intialize at a
+}</tt></p>
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>b:=readbyte; i:=i+1; until b=0 ; end;</tt></p>
+</td>
+</table>
+
+<p><tt>begin halted:=false; exitstatus:=undef;
+uerrorproc:=0; intrap:=false;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>{ initialize tables } for i:=0 to maxcode do
+code[i]:=0; for i:=0 to maxdata do data[i]:=0; for
+iclass:=prim to tert do for i:=0 to 255 do with
+dispat[iclass][i] do</tt></p>
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin instr:=NON; iflag:=[zbit] end;</tt></p>
+
+<p><tt>{ read instruction table file. see appendix B } {
+The table read here is a simple transformation of the table
+on page xx } { - instruction names were transformed to
+numbers } { - the &rsquo;-&rsquo; flag was transformed to an
+&rsquo;i&rsquo; flag for &rsquo;w&rsquo; type instructions }
+{ - the &rsquo;S&rsquo; flag was added for instructions
+having signed operands } reset(tables); insr:=NON; repeat
+read(tables,insno) ; cset:=[]; f:=[]; insr:=ifind(insno); if
+insr=NON then begin writeln(&rsquo;Incorrect table&rsquo;);
+halt end; repeat read(tables,c) until c&lt;&gt;&rsquo;
+&rsquo; ; repeat cset:=cset+[c]; read(tables,c) until
+c=&rsquo; &rsquo; ; if &rsquo;m&rsquo; in cset then
+f:=f+[mini]; if &rsquo;s&rsquo; in cset then f:=f+[short];
+if &rsquo;-&rsquo; in cset then f:=f+[zbit]; if
+&rsquo;i&rsquo; in cset then f:=f+[ibit]; if &rsquo;S&rsquo;
+in cset then f:=f+[sbit]; if &rsquo;w&rsquo; in cset then
+f:=f+[wbit]; if (mini in f) or (short in f) then
+read(tables,nops) else nops:=1 ; readln(tables,opcode); if
+(&rsquo;4&rsquo; in cset) or (&rsquo;8&rsquo; in cset) then
+begin iclass:=tert end else if &rsquo;e&rsquo; in cset then
+begin iclass:=second end else iclass:=prim; for i:=0 to
+nops-1 do begin with dispat[iclass,opcode+i] do
+begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>iflag:=f; instr:=insr;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>if &rsquo;2&rsquo; in cset then ilength:=2</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>else if &rsquo;u&rsquo; in cset then
+ilength:=2</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>else if &rsquo;4&rsquo; in cset then
+ilength:=4</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>else if &rsquo;8&rsquo; in cset then
+ilength:=8</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>else if (mini in f) or (short in f) then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>if &rsquo;N&rsquo; in cset then wtemp:=-1-i else
+wtemp:=i ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>if &rsquo;o&rsquo; in cset then wtemp:=wtemp+1
+;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>if short in f then wtemp:=wtemp*256 ;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>implicit:=wtemp</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end end end until eof(tables);</tt></p>
+
+<p><tt>{ read in program text, data and procedure
+descriptors } reset(prog); readhdr; { verify first header }
+for i:=1 to 8 do header[i]:=readadr; { read second header }
+hp:=maxdata+1; sp:=maxdata+1; lino(0); { read program text }
+if header[NTEXT]+header[NPROC]*pdsize&gt;maxcode then begin
+writeln(&rsquo;Text size too large&rsquo;); halt end; if
+header[SZDATA]&gt;maxdata then begin writeln(&rsquo;Data
+size too large&rsquo;); halt end; for i:=0 to
+header[NTEXT]-1 do code[i]:=readbyte; { read data blocks }
+nexta:=0; for i:=1 to header[NDATA] do begin n:=readbyte; if
+n&lt;&gt;0 then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>elem:=readbyte; firsta:=nexta;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>case n of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>1: { uninitialized words }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for j:=1 to elem do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin store(nexta,undef); nexta:=nexta+wsize
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>2: { initialized bytes }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for j:=1 to elem do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin storeb(nexta,readbyte); nexta:=nexta+1
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>3: { initialized words }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for j:=1 to elem do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin store(nexta,readword); nexta:=nexta+wsize
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>4,5: { instruction and data pointers }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for j:=1 to elem do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin storea(nexta,readadr); nexta:=nexta+asize
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>6: { signed integers }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin readint(nexta,elem); nexta:=nexta+elem
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>7: { unsigned integers }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin readuns(nexta,elem); nexta:=nexta+elem
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>8: { floating point numbers }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin readfloat(nexta,elem); nexta:=nexta+elem
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>repc:=readadr; amount:=nexta-firsta;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for count:=1 to repc do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>for ofst:=0 to amount-1 do
+data[nexta+ofst]:=data[firsta+ofst];</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>nexta:=nexta+amount;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>end end; if header[SZDATA]&lt;&gt;nexta then
+writeln(&rsquo;Data initialization error&rsquo;); hp:=nexta;
+{ read descriptor table } pd:=header[NTEXT]; for i:=1 to
+header[NPROC]*pdsize do code[pd+i-1]:=readbyte; { call the
+entry point routine } ignmask:=0;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>{ catch all traps, higher numbered traps cannot be
+ignored} retsize:=0; lb:=maxdata; { illegal dynamic link }
+pc:=maxcode; { illegal return address } push(0); a:=sp; { No
+environment } push(0); b:=sp; { No args } pusha(a); { envp }
+pusha(b); { argv } push(0); { argc }
+call(argp(header[ENTRY])); end;</tt></p>
+</td>
+</table>
+
+<p>17</p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ MAIN LOOP OF THE INTERPRETER }
+{---------------------------------------------------------------------------}
+{ It should be noted that the interpreter (microprogram) for
+an EM machine can be written in two fundamentally different
+ways: (1) the instruction operands are fetched in the main
+loop, or (2) the in- struction operands are fetched after
+the 256 way branch, by the exe- cution routines themselves.
+In this interpreter, method (1) is used to simplify the
+description of execution routines. The dispatch table dispat
+is used to determine how the operand is encoded. There are 4
+possibilities:</tt></p>
+
+<p><tt>0. There is no operand 1. The operand and
+instruction are together in 1 byte (mini) 2. The operand is
+one byte long and follows the opcode byte(s) 3. The operand
+is two bytes long and follows the opcode byte(s) 4. The
+operand is four bytes long and follows the opcode
+byte(s)</tt></p>
+
+<p><tt>In this interpreter, the main loop determines the
+operand type, fetches it, and leaves it in the global
+variable k for the execution routines to use. Consequently,
+instructions such as LOL, which use three different formats,
+need only be described once in the body of the interpreter.
+However, for a production interpreter, or a hardware EM
+machine, it is probably better to use method (2), i.e. to
+let the execution routines themselves fetch their own
+operands. The reason for this is that each opcode uniquely
+determines the operand format, so no table lookup in the
+dispatch table is needed. The whole table is not needed.
+Method (2) therefore executes much faster. However, separate
+execution routines will be needed for LOL with a one byte
+offset, and LOL with a two byte offset. It is to avoid this
+additional clutter that method (1) is used here. In a
+produc- tion interpreter, it is envisioned that the main
+loop will fetch the next instruction byte, and use it as an
+index into a 256 word table to find the address of the
+interpreter routine to jump to. The routine jumped to will
+begin by fetching its operand, if any, without any table
+lookup, since it knows which format to expect. After doing
+the work, it returns to the main loop by jumping in-
+directly to a register that contains the address of the main
+loop. A slight variation on this idea is to have the
+register contain the address of the branch table, rather
+than the address of the main loop. Another issue is whether
+the execution routines for LOL 0, LOL 2, LOL 4, etc. should
+all be have distinct execution routines. Doing so provides
+for the maximum speed, since the operand is implicit in the
+routine itself. The disadvantage is that many nearly
+identical execution routines will then be needed. Another
+way of doing it is to keep the instruction byte fetched from
+memory (LOL 0, LOL 2, LOL 4, etc.) in some register, and
+have all the LOL mini format instruc- tions branch to a
+common routine. This routine can then determine the operand
+by subtracting the code for LOL 0 from the register, leaving
+the true operand in the register (as a word quantity of
+course). This method makes the interpreter smaller, but is a
+bit slower.</tt></p>
+
+<p>18</p>
+
+<p><tt>To make this important point a little clearer,
+consider how a production interpreter for the PDP-11 might
+appear. Let us assume the following opcodes have been
+assigned:</tt></p>
+
+<p><tt>31: LOL -2 (2 bytes, i.e. next word) 32: LOL -4 33:
+LOL -6 34: LOL b (format with a one byte offset) 35: LOL w
+(format with a one word, i.e. two byte offset)</tt></p>
+
+<p><tt>Further assume that each of the 5 opcodes will have
+its own execution routine, i.e. we are making a tradeoff in
+favor of fast execution and a slightly larger interpreter.
+Register r5 is the em program counter. Register r4 is the em
+LB register Register r3 is the em SP register (the stack
+grows toward low core) Register r2 contains the interpreter
+address of the main loop</tt></p>
+
+<p><tt>The main loop looks like this:</tt></p>
+
+<p><tt>movb (r5)+,r0 /fetch the opcode into r0 and
+increment r5 asl r0 /shift r0 left 1 bit. Now:
+-256&lt;=r0&lt;=+254 jmp *table(r0) /jump to execution
+routine</tt></p>
+
+<p><tt>Notice that no operand fetching has been done. The
+execution routines for the 5 sample instructions given above
+might be as follows:</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>lol2: mov -2(r4),-(sp) /push local -2 onto
+stack</tt></p>
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>jmp (r2) /go back to main loop lol4: mov
+-4(r4),-(sp) /push local -4 onto stack</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>jmp (r2) /go back to main loop lol6: mov
+-6(r4),-(sp) /push local -6 onto stack</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>jmp (r2) /go back to main loop lolb: mov $177400,r0
+/prepare to fetch the 1 byte operand</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>bisb (r5)+,r0 /operand is now in r0</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>asl r0 /r0 is now offset from LB in bytes, not
+words</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>add r4,r0 /r0 is now address of the needed
+local</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>mov (r0),-(sp) /push the local onto the
+stack</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>jmp (r2) lolw: clr r0 /prepare to fetch the 2 byte
+operand</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>bisb (r5)+,r0 /fetch high order byte first
+!!!</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>swab r0 /insert high order byte in place</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>bisb (r5)+,r0 /insert low order byte in
+place</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>asl r0 /convert offset to bytes, from words</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>add r4,r0 /r0 is now address of needed
+local</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>mov (r0),-(sp) /stack the local</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="6%"></td>
+<td width="89%">
+
+<p><tt>jmp (r2) /done</tt></p>
+</td>
+</table>
+
+<p><tt>The important thing to notice is where and how the
+operand fetch occurred: lol2, lol4, and lol6, (the
+mini&rsquo;s) have implicit operands lolb knew it had to
+fetch one byte, and did so without any table lookup lolw
+knew it had to fetch a word, and did so, high order byte
+first }</tt></p>
+
+<p>19</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Routines for the individual instructions }
+{---------------------------------------------------------------------------}
+procedure loadops; var j:integer; begin case insr of { LOAD
+GROUP } LDC: pushd(argd(k)); LOC: pushsw(argc(k)); LOL:
+push(memw(locadr(k))); LOE: push(memw(argg(k))); LIL:
+push(memw(mema(locadr(k)))); LOF: push(memw(popa+argf(k)));
+LAL: pusha(locadr(k)); LAE: pusha(argg(k)); LXL: begin
+a:=lb; for j:=1 to argn(k) do a:=mema(a+savsize); pusha(a)
+end; LXA: begin a:=lb;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>for j:=1 to argn(k) do a:= mema(a+savsize);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>pusha(a+savsize)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LOI: pushx(argo(k),popa); LOS: begin
+k:=argw(k); if k&lt;&gt;wsize then trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>k:=pop; pushx(argo(k),popa)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LDL: begin a:=locadr(k); push(memw(a+wsize));
+push(memw(a)) end; LDE: begin k:=argg(k);
+push(memw(k+wsize)); push(memw(k)) end; LDF: begin
+k:=argf(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>a:=popa; push(memw(a+k+wsize));
+push(memw(a+k))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LPI: push(argp(k)) end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure storeops; begin case insr of { STORE GROUP
+} STL: store(locadr(k),pop); STE: store(argg(k),pop); SIL:
+store(mema(locadr(k)),pop); STF: begin a:=popa;
+store(a+argf(k),pop) end; STI: popx(argo(k),popa); STS:
+begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS);</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>k:=popa; popx(argo(k),popa)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SDL: begin a:=locadr(k); store(a,pop);
+store(a+wsize,pop) end; SDE: begin k:=argg(k); store(k,pop);
+store(k+wsize,pop) end; SDF: begin k:=argf(k); a:=popa;
+store(a+k,pop); store(a+k+wsize,pop) end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure intarith; var i:integer; begin case insr
+of { SIGNED INTEGER ARITHMETIC } ADI: case szindex(argw(k))
+of</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; ss:=popsw;
+push(fitsw(ss+st,EIOVFL)) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd; pushd(doadi(ds,dt))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; SBI: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; ss:= popsw;
+push(fitsw(ss-st,EIOVFL)) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd; pushd(dosbi(ds,dt))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; MLI: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; ss:= popsw;
+push(fitsw(ss*st,EIOVFL)) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd; pushd(domli(ds,dt))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; DVI: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin st:= popsw; ss:= popsw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if st=0 then trap(EIDIVZ) else pushsw(ss div
+st)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd; pushd(dodvi(ds,dt))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; RMI: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin st:= popsw; ss:=popsw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if st=0 then trap(EIDIVZ) else pushsw(ss - (ss div
+st)*st)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd; pushd(dormi(ds,dt))
+end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; NGI: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; pushsw(-st) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin ds:=popd; pushd(dongi(ds)) end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SLI: begin t:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin ss:=popsw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:= 1 to t do sleft(ss); pushsw(ss)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SRI: begin t:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin ss:=popsw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:= 1 to t do sright(ss); pushsw(ss)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin ds:=popd;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:= 1 to t do sdright(ss); pushd(ss)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure unsarith; var i:integer; begin case insr
+of { UNSIGNED INTEGER ARITHMETIC } ADU: case
+szindex(argw(k)) of</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:= pop; push(chopw(s+t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; SBU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:= pop; push(chopw(s-t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; MLU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:= pop; push(chopw(s*t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end ; DVU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:= pop; s:= pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if t=0 then trap(EIDIVZ) else push(s div t)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; RMU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:= pop; s:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if t=0 then trap(EIDIVZ) else push(s - (s div
+t)*t)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SLU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:= 1 to t do suleft(s); push(s)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SRU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:= 1 to t do suright(s); push(s)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure fltarith; begin case insr of { FLOATING
+POINT ARITHMETIC } ADF: begin argwf(k); rt:=popr; rs:=popr;
+pushr(doadf(rs,rt)) end; SBF: begin argwf(k); rt:=popr;
+rs:=popr; pushr(dosbf(rs,rt)) end; MLF: begin argwf(k);
+rt:=popr; rs:=popr; pushr(domlf(rs,rt)) end; DVF: begin
+argwf(k); rt:=popr; rs:=popr; pushr(dodvf(rs,rt)) end; NGF:
+begin argwf(k); rt:=popr; pushr(dongf(rt)) end; FIF: begin
+argwf(k); rt:=popr; rs:=popr;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>dofif(rt,rs,x,y); pushr(y); pushr(x)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; FEF: begin argwf(k); rt:=popr; dofef(rt,x,ss);
+pushr(x); pushsw(ss) end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure ptrarith; begin case insr of { POINTER
+ARITHMETIC } ADP: pusha(popa+argf(k)); ADS: case
+szindex(argw(k)) of</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; pusha(popa+st) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; pusha(popa+dt) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SBS: begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>a:=popa; b:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: push(fitsw(b-a,EIOVFL));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: pushd(b-a)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+</table>
+
+<p><tt>procedure incops; var j:integer; begin case insr of
+{ INCREMENT/DECREMENT/ZERO } INC:
+push(fitsw(popsw+1,EIOVFL)); INL: begin a:=locadr(k);
+store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end; INE: begin
+a:=argg(k); store(a,fitsw(signwd(memw(a))+1,EIOVFL)) end;
+DEC: push(fitsw(popsw-1,EIOVFL)); DEL: begin a:=locadr(k);
+store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end; DEE: begin
+a:=argg(k); store(a,fitsw(signwd(memw(a))-1,EIOVFL)) end;
+ZRL: store(locadr(k),0); ZRE: store(argg(k),0); ZER: for
+j:=1 to argw(k) div wsize do push(0); ZRF: pushr(0); end
+end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure convops; begin case insr of { CONVERT
+GROUP } CII: begin s:=pop; t:=pop;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>if t&lt;wsize then begin push(sextend(pop,t));
+t:=wsize end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(t)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: if szindex(argw(s))=2 then pushd(popsw);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: if szindex(argw(s))=1 then
+push(fitsw(popd,ECONV))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CIU: case szindex(argw(pop)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: if szindex(argw(pop))=2 then push(unsign(popd mod
+negoff));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CIF: begin argwf(pop);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(pop)) of 1:pushr(popsw);
+2:pushr(popd) end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CUI: case szindex(argw(pop)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: case szindex(argw(pop)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin s:=pop; if s&gt;maxsint then trap(ECONV);
+push(s) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: case szindex(argw(pop)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: pushd(pop);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CUU: case szindex(argw(pop)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: if szindex(argw(pop))=2 then
+trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CUF: begin argwf(pop);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if szindex(argw(pop))=1 then pushr(pop) else
+trap(EILLINS)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CFI: begin sz:=argw(pop); argwf(pop);
+rt:=popr;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(sz) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: push(fitsw(trunc(rt),ECONV));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: pushd(fitd(trunc(rt)));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CFU: begin sz:=argw(pop); argwf(pop);
+rt:=popr;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(sz) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: push( chopw(trunc(abs(rt)-0.5)) );</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CFF: begin argwf(pop); argwf(pop) end end
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure logops; var i,j:integer; begin case insr
+of { LOGICAL GROUP } XAND:</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin a:=sp+k; t:=pop; store(a,bf(andf,memw(a),t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; IOR:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin a:=sp+k; t:=pop; store(a,bf(iorf,memw(a),t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; XOR:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin a:=sp+k; t:=pop; store(a,bf(xorf,memw(a),t))
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; COM:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>store(sp+k-wsize*j, bf(xorf,memw(sp+k-wsize*j),
+negoff-1))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; ROL: begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:=pop; s:=pop; for i:= 1 to t do rleft(s);
+push(s)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; ROR: begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:=pop; s:=pop; for i:= 1 to t do rright(s);
+push(s)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure setops; var i,j:integer; begin case insr
+of { SET GROUP } INN:</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>i:= t mod 8; t:= t div 8;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if t&gt;=k then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin trap(ESET); s:=0 end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin s:=memb(sp+t) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newsp(sp+k); push(bit(i,s));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; XSET:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>i:= t mod 8; t:= t div 8;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do push(0);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if t&gt;=k then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>trap(ESET)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin s:=1; for j:= 1 to i do rleft(s);
+storeb(sp+t,s) end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure arrops; begin case insr of { ARRAY GROUP }
+LAR:</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>pushx(argo(memw(a+2*k)),arraycalc(a))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; SAR:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>popx(argo(memw(a+2*k)),arraycalc(a))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; AAR:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>push(arraycalc(a))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure cmpops; begin case insr of { COMPARE GROUP
+} CMI: case szindex(argw(k)) of</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>1: begin st:=popsw; ss:=popsw;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if ss&lt;st then pushsw(-1) else if ss=st then
+push(0) else push(1)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: begin dt:=popd; ds:=popd;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if ds&lt;dt then pushsw(-1) else if ds=dt then
+push(0) else push(1)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CMU: case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: begin t:=pop; s:=pop;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if s&lt;t then pushsw(-1) else if s=t then push(0)
+else push(1)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CMP: begin a:=popa; b:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if b&lt;a then pushsw(-1) else if b=a then push(0)
+else push(1)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CMF: begin argwf(k); rt:=popr;
+rs:=popr;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if rs&lt;rt then pushsw(-1) else if rs=rt then
+push(0) else push(1)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CMS: begin k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:= 0; j:= 0;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>while (j &lt; k) and (t=0) do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin if memw(sp+j) &lt;&gt; memw(sp+k+j) then
+t:=1;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>j:=j+wsize</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newsp(sp+wsize*k); push(t);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+</table>
+
+<p><tt>TLT: if popsw &lt; 0 then push(1) else push(0); TLE:
+if popsw &lt;= 0 then push(1) else push(0); TEQ: if pop = 0
+then push(1) else push(0); TNE: if pop &lt;&gt; 0 then
+push(1) else push(0); TGE: if popsw &gt;= 0 then push(1)
+else push(0); TGT: if popsw &gt; 0 then push(1) else
+push(0); end end;</tt></p>
+
+<p><tt>procedure branchops; begin case insr of { BRANCH
+GROUP } BRA: newpc(pc+k);</tt></p>
+
+<p><tt>BLT: begin st:=popsw; if popsw &lt; st then
+newpc(pc+k) end; BLE: begin st:=popsw; if popsw &lt;= st
+then newpc(pc+k) end; BEQ: begin t :=pop ; if pop = t then
+newpc(pc+k) end; BNE: begin t :=pop ; if pop &lt;&gt; t then
+newpc(pc+k) end; BGE: begin st:=popsw; if popsw &gt;= st
+then newpc(pc+k) end; BGT: begin st:=popsw; if popsw &gt; st
+then newpc(pc+k) end;</tt></p>
+
+<p><tt>ZLT: if popsw &lt; 0 then newpc(pc+k); ZLE: if popsw
+&lt;= 0 then newpc(pc+k); ZEQ: if pop = 0 then newpc(pc+k);
+ZNE: if pop &lt;&gt; 0 then newpc(pc+k); ZGE: if popsw &gt;=
+0 then newpc(pc+k); ZGT: if popsw &gt; 0 then newpc(pc+k)
+end end;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure callops; var j:integer; begin case insr of
+{ PROCEDURE CALL GROUP } CAL: call(argp(k)); CAI: begin
+call(argp(popa)) end; RET: begin k:=argz(k); if k div
+wsize&gt;maxret then trap(EILLINS);</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>for j:= 1 to k div wsize do retarea[j]:=pop;
+retsize:=k;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newsp(lb); lb:=maxdata+1; { To circumvent stack
+overflow error }</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newpc(popa);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if pc=maxcode then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>halted:=true;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if retsize=wsize then
+exitstatus:=retarea[1]</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else exitstatus:=undef</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newlb(popa);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LFR: begin k:=args(k); if k&lt;&gt;retsize then
+trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j:=k div wsize downto 1 do
+push(retarea[j]);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>procedure miscops; var i,j:integer; begin case insr
+of { MISCELLANEOUS GROUP } ASP,ASS:</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>begin if insr=ASS then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); k:=popsw end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>k:=argf(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if k&lt;0</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>then for j:= 1 to -k div wsize do
+push(undef)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>else newsp(sp+k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; BLM,BLS:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin if insr=BLS then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); k:=pop end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>k:=argz(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>b:=popa; a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for j := 1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+
+<p><tt>store(b-wsize+wsize*j,memw(a-wsize+wsize*j))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CSA: begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>st:= popsw - signwd(memw(a+asize));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if (st&gt;=0) and (st&lt;=memw(a+wsize+asize))
+then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>b:=mema(a+2*wsize+asize+asize*st) else
+b:=mema(a);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if b=0 then trap(ECASE) else newpc(b)</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; CSB: begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>t:=pop; i:=1; found:=false;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>while (i&lt;=memw(a+asize)) and not found
+do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if t=memw(a+(asize+wsize)*i) then found:=true else
+i:=i+1;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if found then b:=memw(a+(asize+wsize)*i+wsize) else
+b:=memw(a);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if b=0 then trap(ECASE) else newpc(b);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; DCH: begin pusha(mema(popa+dynd)) end;
+DUP,DUS:</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin if insr=DUS then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=argw(k); if k&lt;&gt;wsize then
+trap(EILLINS); k:=pop end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>k:=args(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=1 to k div wsize do
+push(memw(sp+k-wsize));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; EXG: begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>k:=argw(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=1 to k div wsize do
+push(memw(sp+k-wsize));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=0 to k div wsize - 1 do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>store(sp+k+i*wsize,memw(sp+k+k+i*wsize));</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=1 to k div wsize do</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin t:=pop ; store(sp+k+k-wsize,t) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; FIL: filna(argg(k)); GTO: begin
+k:=argg(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>newlb(mema(k+2*asize)); newsp(mema(k+asize));
+newpc(mema(k))</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LIM: push(ignmask); LIN: lino(argn(k)); LNI:
+lino(memw(0)+1); LOR: begin i:=argr(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case i of 0:pusha(lb); 1:pusha(sp); 2:pusha(hp)
+end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; LPB: pusha(popa+statd); MON: domon(pop); NOP:
+writeln(&rsquo;NOP at line &rsquo;,memw(0):5) ; RCK: begin
+a:=popa;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case szindex(argw(k)) of</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>1: if (signwd(memw(sp))&lt;signwd(memw(a)))
+or</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>(signwd(memw(sp))&gt;signwd(memw(a+wsize))) then
+trap(ERANGE);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>2: if (memd(sp)&lt;memd(a)) or</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>(memd(sp)&gt;memd(a+2*wsize)) then
+trap(ERANGE);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; RTT: dortt; SIG: begin a:=popa;
+pusha(uerrorproc); uerrorproc:=a end; SIM: ignmask:=pop;
+STR: begin i:=argr(k);</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>case i of 0: newlb(popa); 1: newsp(popa); 2:
+newhp(popa) end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end; TRP: trap(pop) end end;</tt></p>
+</td>
+</table>
+
+<p>20</p>
+
+
+<p><tt>{---------------------------------------------------------------------------}
+{ Main Loop }
+{---------------------------------------------------------------------------}</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><tt>begin initialize; 8888: repeat opcode := nextpc; {
+fetch the first byte of the instruction } if opcode=escape1
+then iclass:=second else if opcode=escape2 then iclass:=tert
+else iclass:=prim; if iclass&lt;&gt;prim then opcode :=
+nextpc; with dispat[iclass][opcode] do begin
+insr:=instr;</tt></p>
+</td>
+<td width="89%">
+
+<p><tt>if not (zbit in iflag) then</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if ibit in iflag then k:=pop else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if mini in iflag then k:=implicit else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if short in iflag then k:=implicit+nextpc
+else</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>begin k:=nextpc;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if (sbit in iflag) and (k&gt;=128) then
+k:=k-256;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>for i:=2 to ilength do k:=256*k + nextpc</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>if wbit in iflag then k:=k*wsize;</tt></p>
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="89%">
+
+<p><tt>end end; case insr of</tt></p>
+</td>
+</table>
+
+<p><tt>NON: trap(EILLINS);</tt></p>
+
+<p><tt>{ LOAD GROUP }
+LDC,LOC,LOL,LOE,LIL,LOF,LAL,LAE,LXL,LXA,LOI,LOS,LDL,LDE,LDF,LPI:
+loadops;</tt></p>
+
+<p><tt>{ STORE GROUP } STL,STE,SIL,STF,STI,STS,SDL,SDE,SDF:
+storeops;</tt></p>
+
+<p><tt>{ SIGNED INTEGER ARITHMETIC }
+ADI,SBI,MLI,DVI,RMI,NGI,SLI,SRI: intarith;</tt></p>
+
+<p><tt>{ UNSIGNED INTEGER ARITHMETIC }
+ADU,SBU,MLU,DVU,RMU,SLU,SRU: unsarith;</tt></p>
+
+<p><tt>{ FLOATING POINT ARITHMETIC }
+ADF,SBF,MLF,DVF,NGF,FIF,FEF: fltarith;</tt></p>
+
+<p><tt>{ POINTER ARITHMETIC } ADP,ADS,SBS:
+ptrarith;</tt></p>
+
+<p><tt>{ INCREMENT/DECREMENT/ZERO }
+INC,INL,INE,DEC,DEL,DEE,ZRL,ZRE,ZER,ZRF: incops;</tt></p>
+
+<p><tt>{ CONVERT GROUP }
+CII,CIU,CIF,CUI,CUU,CUF,CFI,CFU,CFF: convops;</tt></p>
+
+<p><tt>{ LOGICAL GROUP } XAND,IOR,XOR,COM,ROL,ROR:
+logops;</tt></p>
+
+<p><tt>{ SET GROUP } INN,XSET: setops;</tt></p>
+
+<p><tt>{ ARRAY GROUP } LAR,SAR,AAR: arrops;</tt></p>
+
+<p><tt>{ COMPARE GROUP } CMI,CMU,CMP,CMF,CMS,
+TLT,TLE,TEQ,TNE,TGE,TGT: cmpops;</tt></p>
+
+<p><tt>{ BRANCH GROUP } BRA, BLT,BLE,BEQ,BNE,BGE,BGT,
+ZLT,ZLE,ZEQ,ZNE,ZGE,ZGT: branchops;</tt></p>
+
+<p><tt>{ PROCEDURE CALL GROUP } CAL,CAI,RET,LFR:
+callops;</tt></p>
+
+<p><tt>{ MISCELLANEOUS GROUP }
+ASP,ASS,BLM,BLS,CSA,CSB,DCH,DUP,DUS,EXG,FIL,GTO,LIM,
+LIN,LNI,LOR,LPB,MON,NOP,RCK,RTT,SIG,SIM,STR,TRP:
+miscops;</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><tt>end; { end of case statement } if not ( (insr=RET)
+or (insr=ASP) or (insr=BRA) or (insr=GTO) ) then</tt></p>
+<td width="7%"></td>
+<td width="2%"></td>
+<td width="89%">
+
+<p><tt>retsize:=0 ; until halted; 9999: writeln(&rsquo;halt
+with exit status: &rsquo;,exitstatus:1); doident;
+end.</tt></p>
+</td>
+</table>
+
+<p>21</p>
+
+<p><b>B. EM CODE TABLES</b></p>
+
+<p>The following table is used by the assembler for EM
+machine language. It specifies the opcodes used for each
+instruction and how arguments are mapped to machine language
+arguments. The table is presented in three columns, each
+line in each column contains three or four fields. Each line
+describes a range of interpreter opcodes by specifying for
+which instruction the range is used, the type of the opcodes
+(mini, shortie, etc..) and range for the instruction
+argument.</p>
+
+<p>The first field on each line gives the EM instruction
+mnemonic, the second field gives some flags. If the opcodes
+are minis or shorties the third field specifies how many
+minis/shorties are used. The last field gives the number of
+the (first) interpreter opcode.</p>
+
+<p>Flags :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Opcode type, only one of the following may be
+specified.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>opcode without argument</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>m</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>mini</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>s</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>shortie</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>2</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>opcode with 2-byte signed argument</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>4</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>opcode with 4-byte signed argument</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>8</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>opcode with 8-byte signed argument</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>u</p>
+</td>
+<td width="8%"></td>
+<td width="16%">
+
+<p>opcode with 2-byte unsigned argument</p>
+</td>
+<td width="63%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Secondary (escaped) opcodes.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>e</p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p>The opcode thus marked is in the secondary opcode group
+instead of the primary</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>restrictions on arguments</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>N</p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p>Negative arguments only</p>
+</td>
+<td width="61%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>P</p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p>Positive and zero arguments only</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>mapping of arguments</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>w</p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p>argument must be divisible by the wordsize and is
+divided by the wordsize before use as opcode argument.</p>
+</td>
+<td width="57%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>o</p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p>argument ( possibly after division ) must be &gt;= 1 and
+is decremented before use as opcode argument</p>
+</td>
+<td width="57%">
+</td>
+</table>
+
+<p>If the opcode type is 2,4 or 8 the resulting argument is
+used as opcode argument (least significant byte first). If
+the opcode type is mini, the argument is added to the first
+opcode &minus; if in range &minus; . If the argument is
+negative, the absolute value minus one is used in the
+algorithm above.<br>
+For shorties with positive arguments the first opcode is
+used for arguments in the range 0..255, the second for the
+range 256..511, etc.. For shorties with negative arguments
+the first opcode is used for arguments in the range
+&minus;1..&minus;256, the second for the range
+&minus;257..&minus;512, etc.. The byte following the opcode
+contains the least significant byte of the argument. First
+some examples of these specifications.</p>
+
+<p>aar mwPo 1 34</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Indicates that opcode 34 is used as a mini for Positive
+instruction arguments only. The w and o indicate division
+and decrementing of the instruction argument. Because the
+resulting argument must be zero ( only opcode 34 may be
+used), this mini can only be used for instruction argument
+2. Conclusion: opcode 34 is for &quot;AAR 2&quot;.</p>
+</td>
+</table>
+
+<p>adp sP 1 41</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Opcode 41 is used as shortie for ADP with arguments in
+the range 0..255.</p>
+</td>
+</table>
+
+<p>bra sN 2 60</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Opcode 60 is used as shortie for BRA with arguments
+&minus;1..&minus;256, 61 is used for arguments
+&minus;257..&minus;512.</p>
+</td>
+</table>
+
+<p>zer e&minus; 145</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Escaped opcode 145 is used for ZER.</p>
+</td>
+</table>
+
+<p>The interpreter opcode table:</p>
+
+<p align=center><img src="grohtml-974416.png"></p>
+
+<p>The table above results in the following dispatch
+tables. Dispatch tables are used by interpreters to jump to
+the routines implementing the EM instructions, indexed by
+the next opcode. Each line of the dispatch tables gives the
+routine names of eight consecutive opcodes, preceded by the
+first opcode number on that line. Routine names consist of
+an EM mnemonic followed by a suffix. The suffices show the
+encoding used for each opcode.</p>
+
+<p>The following suffices exist:</p>
+
+<p>&lt;num&gt; is a possibly negative integer.</p>
+
+<p>The dispatch table for the 256 primary opcodes:</p>
+
+<p align=center><img src="grohtml-974418.png"></p>
+
+<p>The list of secondary opcodes (escape1):</p>
+
+<p align=center><img src="grohtml-974419.png"></p>
+
+<p>Finally, the list of opcodes with four byte arguments
+(escape2).</p>
+
+<p align=center><img src="grohtml-974420.png"></p>
+
+<p>22</p>
+
+<p><b>C. AN EXAMPLE PROGRAM</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>1</p>
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>program example(output);<br>
+2</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>{This program just demonstrates typical EM code.}<br>
+3</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>type rec = record r1: integer; r2:real; r3: boolean
+end;<br>
+4</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>var mi: integer; mx:real; r:rec;</p>
+</td>
+</table>
+
+<p>5</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>6</p>
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>function sum(a,b:integer):integer;<br>
+7</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>begin<br>
+8</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>sum := a + b<br>
+9</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="6%"></td>
+<td width="92%">
+
+<p>end;</p>
+</td>
+</table>
+
+<p>10</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>11</p>
+</td>
+<td width="92%">
+
+<p>procedure test(var r: rec);</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>12</p>
+</td>
+<td width="92%">
+
+<p>label 1;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>13</p>
+</td>
+<td width="92%">
+
+<p>var i,j: integer;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>14</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>x,y: real;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>15</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>b: boolean;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>16</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>c: char;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>17</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>a: array[1..100] of integer;</p>
+</td>
+</table>
+
+<p>18</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>19</p>
+</td>
+<td width="92%">
+
+<p>begin</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>20</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>j := 1;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>21</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>i := 3 * j + 6;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>22</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>x := 4.8;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>23</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>y := x/0.5;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>24</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>b := true;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>25</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>c := &rsquo;z&rsquo;;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>26</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>for i:= 1 to 100 do a[i] := i * i;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>27</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>r.r1 := j+27;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>28</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>r.r3 := b;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>29</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>r.r2 := x+y;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>30</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>i := sum(r.r1, a[j]);</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>31</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>while i &gt; 0 do begin j := j + r.r1; i := i - 1
+end;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>32</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>with r do begin r3 := b; r2 := x+y; r1 := 0 end;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>33</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>goto 1;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>34</p>
+</td>
+<td width="92%">
+
+<p>1:</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>writeln(j, i:6, x:9:3, b)</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>35</p>
+</td>
+<td width="92%">
+
+<p>end; {test}</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>36</p>
+</td>
+<td width="92%">
+
+<p>begin {main program}</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>37</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>mx := 15.96;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>38</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>mi := 99;</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>39</p>
+</td>
+<td width="92%">
+</td>
+<tr valign="top" align="left">
+<td width="8%"></td>
+<td width="92%">
+
+<p>test(r)</p>
+</td>
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>40</p>
+</td>
+<td width="92%">
+
+<p>end.</p>
+</td>
+</table>
+
+<p>23</p>
+
+<p>The EM code as produced by the Pascal-VU compiler is
+given below. Comments have been added manually. Note that
+this code has already been optimized.</p>
+<!-- TABS -->
+
+<p>mes 2,2,2 ; wordsize 2, pointersize 2<br>
+.1</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>rom &rsquo;t.p\000&rsquo;</p>
+</td>
+<td width="52%">
+
+<p>; the name of the source file</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>hol 552,&minus;32768,0</p>
+</td>
+<td width="52%">
+
+<p>; externals and buf occupy 552 bytes</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>exp $sum</p>
+</td>
+<td width="52%">
+
+<p>; sum can be called from other modules</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>pro $sum,2</p>
+</td>
+<td width="52%">
+
+<p>; procedure sum; 2 bytes local storage</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>lin 8</p>
+</td>
+<td width="52%">
+
+<p>; code from source line 8</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>ldl 0</p>
+</td>
+<td width="52%">
+
+<p>; load two locals ( a and b )</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>adi 2</p>
+</td>
+<td width="52%">
+
+<p>; add them</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>ret 2</p>
+</td>
+<td width="52%">
+
+<p>; return the result</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>end 2</p>
+</td>
+<td width="52%">
+
+<p>; end of procedure ( still two bytes local storage )</p>
+</td>
+</table>
+
+<p>.2</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>rom 1,99,2</p>
+</td>
+<td width="52%">
+
+<p>; descriptor of array a[]</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>exp $test</p>
+</td>
+<td width="52%">
+
+<p>; the compiler exports all level 0 procedures</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>pro $test,226</p>
+</td>
+<td width="52%">
+
+<p>; procedure test, 226 bytes local storage</p>
+</td>
+</table>
+
+<p>.3</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>rom 4.8F8</p>
+</td>
+<td width="52%">
+
+<p>; assemble Floating point 4.8 (8 bytes) in</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>.4</p>
+</td>
+<td width="46%"></td>
+<td width="52%">
+
+<p>; global storage</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>rom 0.5F8</p>
+</td>
+<td width="52%">
+
+<p>; same for 0.5</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>mes 3,&minus;226,2,2</p>
+</td>
+<td width="52%">
+
+<p>; compiler temporary not referenced by address</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>mes 3,&minus;24,2,0</p>
+</td>
+<td width="52%">
+
+<p>; the same is true for i, j, b and c in test</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>mes 3,&minus;22,2,0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>mes 3,&minus;4,2,0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>mes 3,&minus;2,2,0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>mes 3,&minus;20,8,0</p>
+</td>
+<td width="52%">
+
+<p>; and for x and y</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>mes 3,&minus;12,8,0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lin 20</p>
+</td>
+<td width="52%">
+
+<p>; maintain source line number</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 1</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>stl &minus;4</p>
+</td>
+<td width="52%">
+
+<p>; j := 1</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 21 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lol &minus;4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 3</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>mli 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 6</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>adi 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>stl &minus;2</p>
+</td>
+<td width="52%">
+
+<p>; i := 3 * j + 6</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 22 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lae .3</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loi 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lal &minus;12</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sti 8</p>
+</td>
+<td width="52%">
+
+<p>; x := 4.8</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 23 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lal &minus;12</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loi 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lae .4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loi 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>dvf 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>lal &minus;20</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>sti 8</p>
+</td>
+<td width="52%">
+
+<p>; y := x / 0.5</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 24 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 1</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>stl &minus;22</p>
+</td>
+<td width="52%">
+
+<p>; b := true</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 25 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 122</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>stl &minus;24</p>
+</td>
+<td width="52%">
+
+<p>; c := &rsquo;z&rsquo;</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 26 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="2%"></td>
+<td width="46%">
+
+<p>loc 1</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="2%">
+</td>
+<td width="46%">
+
+<p>stl &minus;2</p>
+</td>
+<td width="52%">
+
+<p>; for i:= 1</p>
+</td>
+</table>
+
+<p>2</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>dup 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>mli 2</p>
+</td>
+<td width="52%">
+
+<p>; i*i</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lal &minus;224</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae .2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sar 2</p>
+</td>
+<td width="52%">
+
+<p>; a[i] :=</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 100</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>beq *3</p>
+</td>
+<td width="52%">
+
+<p>; to 100 do</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>inl &minus;2</p>
+</td>
+<td width="52%">
+
+<p>; increment i and loop</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>bra *2</p>
+</td>
+<td width="52%">
+</td>
+</table>
+
+<p>3</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lin 27</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 27</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adi 2</p>
+</td>
+<td width="52%">
+
+<p>; j + 27</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sil 0</p>
+</td>
+<td width="52%">
+
+<p>; r.r1 :=</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 28 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;22</p>
+</td>
+<td width="52%">
+
+<p>; b</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>stf 10</p>
+</td>
+<td width="52%">
+
+<p>; r.r3 :=</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 29 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lal &minus;20</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loi 16</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adf 8</p>
+</td>
+<td width="52%">
+
+<p>; x + y</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adp 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sti 8</p>
+</td>
+<td width="52%">
+
+<p>; r.r2 :=</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 30 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lal &minus;224</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae .2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lar 2</p>
+</td>
+<td width="52%">
+
+<p>; a[j]</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lil 0</p>
+</td>
+<td width="52%">
+
+<p>; r.r1</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $sum</p>
+</td>
+<td width="52%">
+
+<p>; call now</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 4</p>
+</td>
+<td width="52%">
+
+<p>; remove parameters from stack</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lfr 2</p>
+</td>
+<td width="52%">
+
+<p>; get function result</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>stl &minus;2</p>
+</td>
+<td width="52%">
+
+<p>; i :=</p>
+</td>
+</table>
+
+<p>4</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lin 31</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>zle *5</p>
+</td>
+<td width="52%">
+
+<p>; while i &gt; 0 do</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lil 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adi 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>stl &minus;4</p>
+</td>
+<td width="52%">
+
+<p>; j := j + r.r1</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>del &minus;2</p>
+</td>
+<td width="52%">
+
+<p>; i := i - 1</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>bra *4</p>
+</td>
+<td width="52%">
+
+<p>; loop</p>
+</td>
+</table>
+
+<p>5</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lin 32</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>stl &minus;226</p>
+</td>
+<td width="52%">
+
+<p>; make copy of address of r</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;226</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>stf 10</p>
+</td>
+<td width="52%">
+
+<p>; r3 := b</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lal &minus;20</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loi 16</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adf 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;226</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>adp 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sti 8</p>
+</td>
+<td width="52%">
+
+<p>; r2 := x + y</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sil &minus;226</p>
+</td>
+<td width="52%">
+
+<p>; r1 := 0</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lin 34</p>
+</td>
+<td width="52%">
+
+<p>; note the absence of the unnecessary jump</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 22</p>
+</td>
+<td width="52%">
+
+<p>; address of output structure</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_wri</p>
+</td>
+<td width="52%">
+
+<p>; write integer with default width</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 4</p>
+</td>
+<td width="52%">
+
+<p>; pop parameters</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 6</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_wsi</p>
+</td>
+<td width="52%">
+
+<p>; write integer width 6</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 6</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lal &minus;12</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loi 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 9</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 3</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_wrf</p>
+</td>
+<td width="52%">
+
+<p>; write fixed format real, width 9, precision 3</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 14</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lol &minus;22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_wrb</p>
+</td>
+<td width="52%">
+
+<p>; write boolean, default width</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 22</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_wln</p>
+</td>
+<td width="52%">
+
+<p>; writeln</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>ret 0</p>
+</td>
+<td width="52%">
+
+<p>; return, no result</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>end 226</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>exp $_main</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>pro $_main,0</p>
+</td>
+<td width="52%">
+
+<p>; main program</p>
+</td>
+</table>
+
+<p>.6</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="46%">
+
+<p>con 2,&minus;1,22</p>
+</td>
+<td width="52%">
+
+<p>; description of external files</p>
+</td>
+</table>
+
+<p>.5</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>rom 15.96F8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>fil .1</p>
+</td>
+<td width="52%">
+
+<p>; maintain source file name</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae .6</p>
+</td>
+<td width="52%">
+
+<p>; description of external files</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 0</p>
+</td>
+<td width="52%">
+
+<p>; base of hol area to relocate buffer addresses</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_ini</p>
+</td>
+<td width="52%">
+
+<p>; initialize files, etc...</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 4</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lin 37</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae .5</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loi 8</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>sti 8</p>
+</td>
+<td width="52%">
+
+<p>; mx := 15.96</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 38 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 99</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>ste 0</p>
+</td>
+<td width="52%">
+
+<p>; mi := 99</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lni</p>
+</td>
+<td width="52%">
+
+<p>; lin 39 prior to optimization</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>lae 10</p>
+</td>
+<td width="52%">
+
+<p>; address of r</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $test</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>loc 0</p>
+</td>
+<td width="52%">
+
+<p>; normal exit</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>cal $_hlt</p>
+</td>
+<td width="52%">
+
+<p>; cleanup and finish</p>
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>asp 2</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>end 0</p>
+</td>
+<td width="52%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="0%"></td>
+<td width="46%">
+
+<p>mes 5</p>
+</td>
+<td width="52%">
+
+<p>; reals were used</p>
+</td>
+</table>
+
+<p>The compact code corresponding to the above program is
+listed below. Read it horizontally, line by line, not column
+by column. Each number represents a byte of compact code,
+printed in decimal. The first two bytes form the magic
+word.</p>
+
+<p><tt>173 0 159 122 122 122 255 242 1 161 250 124 116 46
+112 0 255 156 245 40 2 245 0 128 120 155 249 123 115 117 109
+160 249 123 115 117 109 122 67 128 63 120 3 122 88 122 152
+122 242 2 161 121 219 122 255 155 249 124 116 101 115 116
+160 249 124 116 101 115 116 245 226 0 242 3 161 253 128 123
+52 46 56 255 242 4 161 253 128 123 48 46 53 255 159 123 245
+30 255 122 122 255 159 123 96 122 120 255 159 123 98 122 120
+255 159 123 116 122 120 255 159 123 118 122 120 255 159 123
+100 128 120 255 159 123 108 128 120 255 67 140 69 121 113
+116 68 73 116 69 123 81 122 69 126 3 122 113 118 68 57 242 3
+72 128 58 108 112 128 68 58 108 72 128 57 242 4 72 128 44
+128 58 100 112 128 68 69 121 113 98 68 69 245 122 0 113 96
+68 69 121 113 118 182 73 118 42 122 81 122 58 245 32 255 73
+118 57 242 2 94 122 73 118 69 220 10 123 54 118 18 122 183
+67 147 73 116 69 147 3 122 104 120 68 73 98 73 120 111 130
+68 58 100 72 136 2 128 73 120 4 122 112 128 68 58 245 32 255
+73 116 57 242 2 59 122 65 120 20 249 123 115 117 109 8 124
+64 122 113 118 184 67 151 73 118 128 125 73 116 65 120 3 122
+113 116 41 118 18 124 185 67 152 73 120 113 245 30 255 73 98
+73 245 30 255 111 130 58 100 72 136 2 128 73 245 30 255 4
+122 112 128 69 120 104 245 30 255 67 154 57 142 73 116 20
+249 124 95 119 114 105 8 124 57 142 73 118 69 126 20 249 124
+95 119 115 105 8 126 57 142 58 108 72 128 69 129 69 123 20
+249 124 95 119 114 102 8 134 57 142 73 98 20 249 124 95 119
+114 98 8 124 57 142 20 249 124 95 119 108 110 8 122 88 120
+152 245 226 0 155 249 125 95 109 97 105 110 160 249 125 95
+109 97 105 110 120 242 6 151 122 119 142 255 242 5 161 253
+128 125 49 53 46 57 54 255 50 242 1 57 242 6 57 120 20 249
+124 95 105 110 105 8 124 67 157 57 242 5 72 128 57 122 112
+128 68 69 219 110 120 68 57 130 20 249 124 116 101 115 116 8
+122 69 120 20 249 124 95 104 108 116 8 122 152 120 159 124
+160 255 159 125 255</tt></p>
+
+<p>1. INTRODUCTION ............. 1</p>
+
+<p>2. MEMORY ....... 2</p>
+
+<p>3. INSTRUCTION ADDRESS SPACE ........................
+3</p>
+
+<p>4. DATA ADDRESS SPACE ................. 4<br>
+__4.1 Global data area .................. 4<br>
+__4.2 Local data area ................. 4<br>
+__4.3 Heap data area ................ 4</p>
+
+<p>5. MAPPING OF EM DATA MEMORY ONTO TARGET MACHINE MEMORY
+............................................. 5</p>
+
+<p>6. TYPE REPRESENTATIONS .................... 6<br>
+__6.1 Unsigned integers .................... 6<br>
+__6.2 Signed Integers .................. 6<br>
+__6.3 Floating point values ....................... 6<br>
+__6.4 Pointers ............ 6<br>
+__6.5 Bit sets ........... 6</p>
+
+<p>7. DESCRIPTORS ............ 7<br>
+__7.1 Range check descriptors .........................
+7<br>
+__7.2 Array descriptors .................... 7<br>
+__7.3 Non-local goto descriptors
+............................ 7<br>
+__7.4 Case descriptors ................... 7</p>
+
+<p>8. ENVIRONMENT INTERACTIONS ........................
+8<br>
+__8.1 Program starting and stopping
+.............................. 8<br>
+__8.2 Input/Output and other monitor calls
+.................................... 8</p>
+
+<p>9. TRAPS AND INTERRUPTS ................... 9</p>
+
+<p>10. EM MACHINE LANGUAGE .................... 10<br>
+__10.1 Instruction encoding ......................... 10<br>
+__10.2 Procedure descriptors ..........................
+10<br>
+__10.3 Load format ................ 10</p>
+
+<p>11. EM ASSEMBLY LANGUAGE ..................... 11<br>
+__11.1 ASCII assembly language ...........................
+11<br>
+____11.1.1 Instruction arguments
+.............................. 11<br>
+____11.1.2 Pseudoinstruction arguments
+.................................... 11<br>
+____11.1.3 Notation .................. 11<br>
+____11.1.4 Pseudoinstructions ............................
+11<br>
+______11.1.4.1 Storage declaration
+................................ 11<br>
+______11.1.4.2 Partitioning ..........................
+11<br>
+______11.1.4.3 Visibility ........................ 11<br>
+______11.1.4.4 Miscellaneous ...........................
+11<br>
+__11.2 The Compact Assembly Language
+................................ 11<br>
+__11.3 Assembly language instruction list
+..................................... 11</p>
+
+<p>A. EM INTERPRETER ............... 12</p>
+
+<p>B. EM CODE TABLES .............. 21</p>
+
+<p>C. AN EXAMPLE PROGRAM .................. 22</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/em.pdf b/doc/tack/em.pdf
new file mode 100644 (file)
index 0000000..45d0e78
Binary files /dev/null and b/doc/tack/em.pdf differ
diff --git a/doc/tack/grohtml-100191.png b/doc/tack/grohtml-100191.png
new file mode 100644 (file)
index 0000000..ad2f031
Binary files /dev/null and b/doc/tack/grohtml-100191.png differ
diff --git a/doc/tack/grohtml-100601.png b/doc/tack/grohtml-100601.png
new file mode 100644 (file)
index 0000000..38e4683
Binary files /dev/null and b/doc/tack/grohtml-100601.png differ
diff --git a/doc/tack/grohtml-100602.png b/doc/tack/grohtml-100602.png
new file mode 100644 (file)
index 0000000..ea24351
Binary files /dev/null and b/doc/tack/grohtml-100602.png differ
diff --git a/doc/tack/grohtml-101091.png b/doc/tack/grohtml-101091.png
new file mode 100644 (file)
index 0000000..8890306
Binary files /dev/null and b/doc/tack/grohtml-101091.png differ
diff --git a/doc/tack/grohtml-101092.png b/doc/tack/grohtml-101092.png
new file mode 100644 (file)
index 0000000..1974778
Binary files /dev/null and b/doc/tack/grohtml-101092.png differ
diff --git a/doc/tack/grohtml-101093.png b/doc/tack/grohtml-101093.png
new file mode 100644 (file)
index 0000000..819befc
Binary files /dev/null and b/doc/tack/grohtml-101093.png differ
diff --git a/doc/tack/grohtml-101094.png b/doc/tack/grohtml-101094.png
new file mode 100644 (file)
index 0000000..af163c1
Binary files /dev/null and b/doc/tack/grohtml-101094.png differ
diff --git a/doc/tack/grohtml-101481.png b/doc/tack/grohtml-101481.png
new file mode 100644 (file)
index 0000000..5e571b5
Binary files /dev/null and b/doc/tack/grohtml-101481.png differ
diff --git a/doc/tack/grohtml-101482.png b/doc/tack/grohtml-101482.png
new file mode 100644 (file)
index 0000000..57ec951
Binary files /dev/null and b/doc/tack/grohtml-101482.png differ
diff --git a/doc/tack/grohtml-101483.png b/doc/tack/grohtml-101483.png
new file mode 100644 (file)
index 0000000..9efcf47
Binary files /dev/null and b/doc/tack/grohtml-101483.png differ
diff --git a/doc/tack/grohtml-101484.png b/doc/tack/grohtml-101484.png
new file mode 100644 (file)
index 0000000..1043710
Binary files /dev/null and b/doc/tack/grohtml-101484.png differ
diff --git a/doc/tack/grohtml-101485.png b/doc/tack/grohtml-101485.png
new file mode 100644 (file)
index 0000000..b896524
Binary files /dev/null and b/doc/tack/grohtml-101485.png differ
diff --git a/doc/tack/grohtml-101486.png b/doc/tack/grohtml-101486.png
new file mode 100644 (file)
index 0000000..9c5510b
Binary files /dev/null and b/doc/tack/grohtml-101486.png differ
diff --git a/doc/tack/grohtml-101487.png b/doc/tack/grohtml-101487.png
new file mode 100644 (file)
index 0000000..0d356ff
Binary files /dev/null and b/doc/tack/grohtml-101487.png differ
diff --git a/doc/tack/grohtml-101488.png b/doc/tack/grohtml-101488.png
new file mode 100644 (file)
index 0000000..8d62461
Binary files /dev/null and b/doc/tack/grohtml-101488.png differ
diff --git a/doc/tack/grohtml-101489.png b/doc/tack/grohtml-101489.png
new file mode 100644 (file)
index 0000000..85e4abe
Binary files /dev/null and b/doc/tack/grohtml-101489.png differ
diff --git a/doc/tack/grohtml-102111.png b/doc/tack/grohtml-102111.png
new file mode 100644 (file)
index 0000000..a88cfe8
Binary files /dev/null and b/doc/tack/grohtml-102111.png differ
diff --git a/doc/tack/grohtml-102411.png b/doc/tack/grohtml-102411.png
new file mode 100644 (file)
index 0000000..b3c889f
Binary files /dev/null and b/doc/tack/grohtml-102411.png differ
diff --git a/doc/tack/grohtml-102412.png b/doc/tack/grohtml-102412.png
new file mode 100644 (file)
index 0000000..de9fb31
Binary files /dev/null and b/doc/tack/grohtml-102412.png differ
diff --git a/doc/tack/grohtml-102413.png b/doc/tack/grohtml-102413.png
new file mode 100644 (file)
index 0000000..29f4afc
Binary files /dev/null and b/doc/tack/grohtml-102413.png differ
diff --git a/doc/tack/grohtml-102721.png b/doc/tack/grohtml-102721.png
new file mode 100644 (file)
index 0000000..47c7da9
Binary files /dev/null and b/doc/tack/grohtml-102721.png differ
diff --git a/doc/tack/grohtml-1027210.png b/doc/tack/grohtml-1027210.png
new file mode 100644 (file)
index 0000000..3228123
Binary files /dev/null and b/doc/tack/grohtml-1027210.png differ
diff --git a/doc/tack/grohtml-1027211.png b/doc/tack/grohtml-1027211.png
new file mode 100644 (file)
index 0000000..efee400
Binary files /dev/null and b/doc/tack/grohtml-1027211.png differ
diff --git a/doc/tack/grohtml-1027212.png b/doc/tack/grohtml-1027212.png
new file mode 100644 (file)
index 0000000..6c694f6
Binary files /dev/null and b/doc/tack/grohtml-1027212.png differ
diff --git a/doc/tack/grohtml-1027213.png b/doc/tack/grohtml-1027213.png
new file mode 100644 (file)
index 0000000..f357ee8
Binary files /dev/null and b/doc/tack/grohtml-1027213.png differ
diff --git a/doc/tack/grohtml-1027214.png b/doc/tack/grohtml-1027214.png
new file mode 100644 (file)
index 0000000..a7a0693
Binary files /dev/null and b/doc/tack/grohtml-1027214.png differ
diff --git a/doc/tack/grohtml-1027215.png b/doc/tack/grohtml-1027215.png
new file mode 100644 (file)
index 0000000..4b43183
Binary files /dev/null and b/doc/tack/grohtml-1027215.png differ
diff --git a/doc/tack/grohtml-1027216.png b/doc/tack/grohtml-1027216.png
new file mode 100644 (file)
index 0000000..30e8772
Binary files /dev/null and b/doc/tack/grohtml-1027216.png differ
diff --git a/doc/tack/grohtml-1027217.png b/doc/tack/grohtml-1027217.png
new file mode 100644 (file)
index 0000000..4c65d68
Binary files /dev/null and b/doc/tack/grohtml-1027217.png differ
diff --git a/doc/tack/grohtml-1027218.png b/doc/tack/grohtml-1027218.png
new file mode 100644 (file)
index 0000000..8e518eb
Binary files /dev/null and b/doc/tack/grohtml-1027218.png differ
diff --git a/doc/tack/grohtml-1027219.png b/doc/tack/grohtml-1027219.png
new file mode 100644 (file)
index 0000000..5f00257
Binary files /dev/null and b/doc/tack/grohtml-1027219.png differ
diff --git a/doc/tack/grohtml-102722.png b/doc/tack/grohtml-102722.png
new file mode 100644 (file)
index 0000000..18f0e21
Binary files /dev/null and b/doc/tack/grohtml-102722.png differ
diff --git a/doc/tack/grohtml-1027220.png b/doc/tack/grohtml-1027220.png
new file mode 100644 (file)
index 0000000..7bf86f3
Binary files /dev/null and b/doc/tack/grohtml-1027220.png differ
diff --git a/doc/tack/grohtml-1027221.png b/doc/tack/grohtml-1027221.png
new file mode 100644 (file)
index 0000000..998a0b5
Binary files /dev/null and b/doc/tack/grohtml-1027221.png differ
diff --git a/doc/tack/grohtml-1027222.png b/doc/tack/grohtml-1027222.png
new file mode 100644 (file)
index 0000000..bf57847
Binary files /dev/null and b/doc/tack/grohtml-1027222.png differ
diff --git a/doc/tack/grohtml-1027223.png b/doc/tack/grohtml-1027223.png
new file mode 100644 (file)
index 0000000..a63c789
Binary files /dev/null and b/doc/tack/grohtml-1027223.png differ
diff --git a/doc/tack/grohtml-1027224.png b/doc/tack/grohtml-1027224.png
new file mode 100644 (file)
index 0000000..d27a857
Binary files /dev/null and b/doc/tack/grohtml-1027224.png differ
diff --git a/doc/tack/grohtml-1027225.png b/doc/tack/grohtml-1027225.png
new file mode 100644 (file)
index 0000000..d28a241
Binary files /dev/null and b/doc/tack/grohtml-1027225.png differ
diff --git a/doc/tack/grohtml-1027226.png b/doc/tack/grohtml-1027226.png
new file mode 100644 (file)
index 0000000..f2643a7
Binary files /dev/null and b/doc/tack/grohtml-1027226.png differ
diff --git a/doc/tack/grohtml-1027227.png b/doc/tack/grohtml-1027227.png
new file mode 100644 (file)
index 0000000..fcf2400
Binary files /dev/null and b/doc/tack/grohtml-1027227.png differ
diff --git a/doc/tack/grohtml-1027228.png b/doc/tack/grohtml-1027228.png
new file mode 100644 (file)
index 0000000..18ad40c
Binary files /dev/null and b/doc/tack/grohtml-1027228.png differ
diff --git a/doc/tack/grohtml-1027229.png b/doc/tack/grohtml-1027229.png
new file mode 100644 (file)
index 0000000..149bab4
Binary files /dev/null and b/doc/tack/grohtml-1027229.png differ
diff --git a/doc/tack/grohtml-102723.png b/doc/tack/grohtml-102723.png
new file mode 100644 (file)
index 0000000..e33f7ca
Binary files /dev/null and b/doc/tack/grohtml-102723.png differ
diff --git a/doc/tack/grohtml-1027230.png b/doc/tack/grohtml-1027230.png
new file mode 100644 (file)
index 0000000..b505ccf
Binary files /dev/null and b/doc/tack/grohtml-1027230.png differ
diff --git a/doc/tack/grohtml-1027231.png b/doc/tack/grohtml-1027231.png
new file mode 100644 (file)
index 0000000..353396a
Binary files /dev/null and b/doc/tack/grohtml-1027231.png differ
diff --git a/doc/tack/grohtml-1027232.png b/doc/tack/grohtml-1027232.png
new file mode 100644 (file)
index 0000000..7511176
Binary files /dev/null and b/doc/tack/grohtml-1027232.png differ
diff --git a/doc/tack/grohtml-1027233.png b/doc/tack/grohtml-1027233.png
new file mode 100644 (file)
index 0000000..62f10d9
Binary files /dev/null and b/doc/tack/grohtml-1027233.png differ
diff --git a/doc/tack/grohtml-1027234.png b/doc/tack/grohtml-1027234.png
new file mode 100644 (file)
index 0000000..d6011a7
Binary files /dev/null and b/doc/tack/grohtml-1027234.png differ
diff --git a/doc/tack/grohtml-1027235.png b/doc/tack/grohtml-1027235.png
new file mode 100644 (file)
index 0000000..3fd8338
Binary files /dev/null and b/doc/tack/grohtml-1027235.png differ
diff --git a/doc/tack/grohtml-1027236.png b/doc/tack/grohtml-1027236.png
new file mode 100644 (file)
index 0000000..00e53e4
Binary files /dev/null and b/doc/tack/grohtml-1027236.png differ
diff --git a/doc/tack/grohtml-1027237.png b/doc/tack/grohtml-1027237.png
new file mode 100644 (file)
index 0000000..2cceea2
Binary files /dev/null and b/doc/tack/grohtml-1027237.png differ
diff --git a/doc/tack/grohtml-1027238.png b/doc/tack/grohtml-1027238.png
new file mode 100644 (file)
index 0000000..586d48a
Binary files /dev/null and b/doc/tack/grohtml-1027238.png differ
diff --git a/doc/tack/grohtml-1027239.png b/doc/tack/grohtml-1027239.png
new file mode 100644 (file)
index 0000000..4287bbd
Binary files /dev/null and b/doc/tack/grohtml-1027239.png differ
diff --git a/doc/tack/grohtml-102724.png b/doc/tack/grohtml-102724.png
new file mode 100644 (file)
index 0000000..af20645
Binary files /dev/null and b/doc/tack/grohtml-102724.png differ
diff --git a/doc/tack/grohtml-102725.png b/doc/tack/grohtml-102725.png
new file mode 100644 (file)
index 0000000..43c856c
Binary files /dev/null and b/doc/tack/grohtml-102725.png differ
diff --git a/doc/tack/grohtml-102726.png b/doc/tack/grohtml-102726.png
new file mode 100644 (file)
index 0000000..31ae765
Binary files /dev/null and b/doc/tack/grohtml-102726.png differ
diff --git a/doc/tack/grohtml-102727.png b/doc/tack/grohtml-102727.png
new file mode 100644 (file)
index 0000000..d6b437b
Binary files /dev/null and b/doc/tack/grohtml-102727.png differ
diff --git a/doc/tack/grohtml-102728.png b/doc/tack/grohtml-102728.png
new file mode 100644 (file)
index 0000000..9c0caee
Binary files /dev/null and b/doc/tack/grohtml-102728.png differ
diff --git a/doc/tack/grohtml-102729.png b/doc/tack/grohtml-102729.png
new file mode 100644 (file)
index 0000000..fca6b38
Binary files /dev/null and b/doc/tack/grohtml-102729.png differ
diff --git a/doc/tack/grohtml-105631.png b/doc/tack/grohtml-105631.png
new file mode 100644 (file)
index 0000000..829c2b4
Binary files /dev/null and b/doc/tack/grohtml-105631.png differ
diff --git a/doc/tack/grohtml-105632.png b/doc/tack/grohtml-105632.png
new file mode 100644 (file)
index 0000000..791f7a4
Binary files /dev/null and b/doc/tack/grohtml-105632.png differ
diff --git a/doc/tack/grohtml-105633.png b/doc/tack/grohtml-105633.png
new file mode 100644 (file)
index 0000000..1015348
Binary files /dev/null and b/doc/tack/grohtml-105633.png differ
diff --git a/doc/tack/grohtml-105634.png b/doc/tack/grohtml-105634.png
new file mode 100644 (file)
index 0000000..0b9604d
Binary files /dev/null and b/doc/tack/grohtml-105634.png differ
diff --git a/doc/tack/grohtml-106061.png b/doc/tack/grohtml-106061.png
new file mode 100644 (file)
index 0000000..c1484b4
Binary files /dev/null and b/doc/tack/grohtml-106061.png differ
diff --git a/doc/tack/grohtml-106062.png b/doc/tack/grohtml-106062.png
new file mode 100644 (file)
index 0000000..08803d6
Binary files /dev/null and b/doc/tack/grohtml-106062.png differ
diff --git a/doc/tack/grohtml-106561.png b/doc/tack/grohtml-106561.png
new file mode 100644 (file)
index 0000000..df12c85
Binary files /dev/null and b/doc/tack/grohtml-106561.png differ
diff --git a/doc/tack/grohtml-1065610.png b/doc/tack/grohtml-1065610.png
new file mode 100644 (file)
index 0000000..f35948c
Binary files /dev/null and b/doc/tack/grohtml-1065610.png differ
diff --git a/doc/tack/grohtml-1065611.png b/doc/tack/grohtml-1065611.png
new file mode 100644 (file)
index 0000000..99dcee8
Binary files /dev/null and b/doc/tack/grohtml-1065611.png differ
diff --git a/doc/tack/grohtml-1065612.png b/doc/tack/grohtml-1065612.png
new file mode 100644 (file)
index 0000000..1f7773f
Binary files /dev/null and b/doc/tack/grohtml-1065612.png differ
diff --git a/doc/tack/grohtml-1065613.png b/doc/tack/grohtml-1065613.png
new file mode 100644 (file)
index 0000000..45bdc5a
Binary files /dev/null and b/doc/tack/grohtml-1065613.png differ
diff --git a/doc/tack/grohtml-1065614.png b/doc/tack/grohtml-1065614.png
new file mode 100644 (file)
index 0000000..b0901b8
Binary files /dev/null and b/doc/tack/grohtml-1065614.png differ
diff --git a/doc/tack/grohtml-106562.png b/doc/tack/grohtml-106562.png
new file mode 100644 (file)
index 0000000..27f984f
Binary files /dev/null and b/doc/tack/grohtml-106562.png differ
diff --git a/doc/tack/grohtml-106563.png b/doc/tack/grohtml-106563.png
new file mode 100644 (file)
index 0000000..d429787
Binary files /dev/null and b/doc/tack/grohtml-106563.png differ
diff --git a/doc/tack/grohtml-106565.png b/doc/tack/grohtml-106565.png
new file mode 100644 (file)
index 0000000..ef2e545
Binary files /dev/null and b/doc/tack/grohtml-106565.png differ
diff --git a/doc/tack/grohtml-106566.png b/doc/tack/grohtml-106566.png
new file mode 100644 (file)
index 0000000..b5e976e
Binary files /dev/null and b/doc/tack/grohtml-106566.png differ
diff --git a/doc/tack/grohtml-106567.png b/doc/tack/grohtml-106567.png
new file mode 100644 (file)
index 0000000..72b7516
Binary files /dev/null and b/doc/tack/grohtml-106567.png differ
diff --git a/doc/tack/grohtml-106568.png b/doc/tack/grohtml-106568.png
new file mode 100644 (file)
index 0000000..4682a8a
Binary files /dev/null and b/doc/tack/grohtml-106568.png differ
diff --git a/doc/tack/grohtml-106569.png b/doc/tack/grohtml-106569.png
new file mode 100644 (file)
index 0000000..e4ccdbe
Binary files /dev/null and b/doc/tack/grohtml-106569.png differ
diff --git a/doc/tack/grohtml-107771.png b/doc/tack/grohtml-107771.png
new file mode 100644 (file)
index 0000000..6b17ec9
Binary files /dev/null and b/doc/tack/grohtml-107771.png differ
diff --git a/doc/tack/grohtml-107772.png b/doc/tack/grohtml-107772.png
new file mode 100644 (file)
index 0000000..d30d541
Binary files /dev/null and b/doc/tack/grohtml-107772.png differ
diff --git a/doc/tack/grohtml-107773.png b/doc/tack/grohtml-107773.png
new file mode 100644 (file)
index 0000000..723648f
Binary files /dev/null and b/doc/tack/grohtml-107773.png differ
diff --git a/doc/tack/grohtml-96851.png b/doc/tack/grohtml-96851.png
new file mode 100644 (file)
index 0000000..09e6997
Binary files /dev/null and b/doc/tack/grohtml-96851.png differ
diff --git a/doc/tack/grohtml-96852.png b/doc/tack/grohtml-96852.png
new file mode 100644 (file)
index 0000000..ef01349
Binary files /dev/null and b/doc/tack/grohtml-96852.png differ
diff --git a/doc/tack/grohtml-96853.png b/doc/tack/grohtml-96853.png
new file mode 100644 (file)
index 0000000..ceebd2b
Binary files /dev/null and b/doc/tack/grohtml-96853.png differ
diff --git a/doc/tack/grohtml-96854.png b/doc/tack/grohtml-96854.png
new file mode 100644 (file)
index 0000000..c53a6c6
Binary files /dev/null and b/doc/tack/grohtml-96854.png differ
diff --git a/doc/tack/grohtml-96855.png b/doc/tack/grohtml-96855.png
new file mode 100644 (file)
index 0000000..1e8bffd
Binary files /dev/null and b/doc/tack/grohtml-96855.png differ
diff --git a/doc/tack/grohtml-96856.png b/doc/tack/grohtml-96856.png
new file mode 100644 (file)
index 0000000..ca04a79
Binary files /dev/null and b/doc/tack/grohtml-96856.png differ
diff --git a/doc/tack/grohtml-96857.png b/doc/tack/grohtml-96857.png
new file mode 100644 (file)
index 0000000..5cbe89a
Binary files /dev/null and b/doc/tack/grohtml-96857.png differ
diff --git a/doc/tack/grohtml-97441.png b/doc/tack/grohtml-97441.png
new file mode 100644 (file)
index 0000000..4348fd4
Binary files /dev/null and b/doc/tack/grohtml-97441.png differ
diff --git a/doc/tack/grohtml-974410.png b/doc/tack/grohtml-974410.png
new file mode 100644 (file)
index 0000000..ee45994
Binary files /dev/null and b/doc/tack/grohtml-974410.png differ
diff --git a/doc/tack/grohtml-974411.png b/doc/tack/grohtml-974411.png
new file mode 100644 (file)
index 0000000..47d8c91
Binary files /dev/null and b/doc/tack/grohtml-974411.png differ
diff --git a/doc/tack/grohtml-974412.png b/doc/tack/grohtml-974412.png
new file mode 100644 (file)
index 0000000..67f9773
Binary files /dev/null and b/doc/tack/grohtml-974412.png differ
diff --git a/doc/tack/grohtml-974413.png b/doc/tack/grohtml-974413.png
new file mode 100644 (file)
index 0000000..a4efff5
Binary files /dev/null and b/doc/tack/grohtml-974413.png differ
diff --git a/doc/tack/grohtml-974414.png b/doc/tack/grohtml-974414.png
new file mode 100644 (file)
index 0000000..2a7f742
Binary files /dev/null and b/doc/tack/grohtml-974414.png differ
diff --git a/doc/tack/grohtml-974415.png b/doc/tack/grohtml-974415.png
new file mode 100644 (file)
index 0000000..0b8bfe4
Binary files /dev/null and b/doc/tack/grohtml-974415.png differ
diff --git a/doc/tack/grohtml-974416.png b/doc/tack/grohtml-974416.png
new file mode 100644 (file)
index 0000000..520c1da
Binary files /dev/null and b/doc/tack/grohtml-974416.png differ
diff --git a/doc/tack/grohtml-974418.png b/doc/tack/grohtml-974418.png
new file mode 100644 (file)
index 0000000..2659ec8
Binary files /dev/null and b/doc/tack/grohtml-974418.png differ
diff --git a/doc/tack/grohtml-974419.png b/doc/tack/grohtml-974419.png
new file mode 100644 (file)
index 0000000..3abe23d
Binary files /dev/null and b/doc/tack/grohtml-974419.png differ
diff --git a/doc/tack/grohtml-97442.png b/doc/tack/grohtml-97442.png
new file mode 100644 (file)
index 0000000..70e02f6
Binary files /dev/null and b/doc/tack/grohtml-97442.png differ
diff --git a/doc/tack/grohtml-974420.png b/doc/tack/grohtml-974420.png
new file mode 100644 (file)
index 0000000..523b39e
Binary files /dev/null and b/doc/tack/grohtml-974420.png differ
diff --git a/doc/tack/grohtml-97443.png b/doc/tack/grohtml-97443.png
new file mode 100644 (file)
index 0000000..157dcee
Binary files /dev/null and b/doc/tack/grohtml-97443.png differ
diff --git a/doc/tack/grohtml-97444.png b/doc/tack/grohtml-97444.png
new file mode 100644 (file)
index 0000000..7c71b25
Binary files /dev/null and b/doc/tack/grohtml-97444.png differ
diff --git a/doc/tack/grohtml-97445.png b/doc/tack/grohtml-97445.png
new file mode 100644 (file)
index 0000000..ce6791a
Binary files /dev/null and b/doc/tack/grohtml-97445.png differ
diff --git a/doc/tack/grohtml-97446.png b/doc/tack/grohtml-97446.png
new file mode 100644 (file)
index 0000000..345f51d
Binary files /dev/null and b/doc/tack/grohtml-97446.png differ
diff --git a/doc/tack/grohtml-97447.png b/doc/tack/grohtml-97447.png
new file mode 100644 (file)
index 0000000..0445942
Binary files /dev/null and b/doc/tack/grohtml-97447.png differ
diff --git a/doc/tack/grohtml-97448.png b/doc/tack/grohtml-97448.png
new file mode 100644 (file)
index 0000000..cd98a0d
Binary files /dev/null and b/doc/tack/grohtml-97448.png differ
diff --git a/doc/tack/grohtml-97449.png b/doc/tack/grohtml-97449.png
new file mode 100644 (file)
index 0000000..bf6457e
Binary files /dev/null and b/doc/tack/grohtml-97449.png differ
diff --git a/doc/tack/grohtml-99071.png b/doc/tack/grohtml-99071.png
new file mode 100644 (file)
index 0000000..5f26193
Binary files /dev/null and b/doc/tack/grohtml-99071.png differ
diff --git a/doc/tack/grohtml-99261.png b/doc/tack/grohtml-99261.png
new file mode 100644 (file)
index 0000000..f1c853f
Binary files /dev/null and b/doc/tack/grohtml-99261.png differ
diff --git a/doc/tack/grohtml-99451.png b/doc/tack/grohtml-99451.png
new file mode 100644 (file)
index 0000000..bce93cc
Binary files /dev/null and b/doc/tack/grohtml-99451.png differ
diff --git a/doc/tack/grohtml-99452.png b/doc/tack/grohtml-99452.png
new file mode 100644 (file)
index 0000000..6ecce63
Binary files /dev/null and b/doc/tack/grohtml-99452.png differ
diff --git a/doc/tack/grohtml-99453.png b/doc/tack/grohtml-99453.png
new file mode 100644 (file)
index 0000000..3f28bf6
Binary files /dev/null and b/doc/tack/grohtml-99453.png differ
diff --git a/doc/tack/grohtml-99454.png b/doc/tack/grohtml-99454.png
new file mode 100644 (file)
index 0000000..b9ff1dd
Binary files /dev/null and b/doc/tack/grohtml-99454.png differ
diff --git a/doc/tack/grohtml-99455.png b/doc/tack/grohtml-99455.png
new file mode 100644 (file)
index 0000000..32144ff
Binary files /dev/null and b/doc/tack/grohtml-99455.png differ
diff --git a/doc/tack/grohtml-99456.png b/doc/tack/grohtml-99456.png
new file mode 100644 (file)
index 0000000..3da0187
Binary files /dev/null and b/doc/tack/grohtml-99456.png differ
diff --git a/doc/tack/grohtml-99457.png b/doc/tack/grohtml-99457.png
new file mode 100644 (file)
index 0000000..b426a55
Binary files /dev/null and b/doc/tack/grohtml-99457.png differ
diff --git a/doc/tack/i80.html b/doc/tack/i80.html
new file mode 100644 (file)
index 0000000..3a01053
--- /dev/null
@@ -0,0 +1,1391 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:17 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Back end table for the Intel 8080 micro-processor</title>
+</head>
+<body>
+
+<h1 align=center>Back end table for the Intel 8080 micro-processor</h1>
+<a href="#1. THE 8080 MICRO PROCESSOR">1. THE 8080 MICRO PROCESSOR</a><br>
+<a href="#1.1. Registers">1.1. Registers</a><br>
+<a href="#1.2. Flip-flops">1.2. Flip-flops</a><br>
+<a href="#1.3. Addressing modes">1.3. Addressing modes</a><br>
+<a href="#1.3.1. Implied addressing">1.3.1. Implied addressing</a><br>
+<a href="#1.3.2. Register addressing">1.3.2. Register addressing</a><br>
+<a href="#1.3.3. Register indirect addressing">1.3.3. Register indirect addressing</a><br>
+<a href="#1.3.4. Immediate addressing">1.3.4. Immediate addressing</a><br>
+<a href="#1.3.5. Direct addressing">1.3.5. Direct addressing</a><br>
+<a href="#2. THE 8080 BACK END TABLE">2. THE 8080 BACK END TABLE</a><br>
+<a href="#2.1. Constant definitions">2.1. Constant definitions</a><br>
+<a href="#2.2. Registers and their properties">2.2. Registers and their properties</a><br>
+<a href="#2.3. Tokens">2.3. Tokens</a><br>
+<a href="#2.4. Sets">2.4. Sets</a><br>
+<a href="#2.5. Instructions">2.5. Instructions</a><br>
+<a href="#2.6. Moves">2.6. Moves</a><br>
+<a href="#2.7. Tests">2.7. Tests</a><br>
+<a href="#2.8. Stacking rules">2.8. Stacking rules</a><br>
+<a href="#2.9. Coercions">2.9. Coercions</a><br>
+<a href="#2.10. Patterns">2.10. Patterns</a><br>
+<a href="#2.10.1. Group 1: Load instructions">2.10.1. Group 1: Load instructions</a><br>
+<a href="#2.10.2. Group 2: Store instructions">2.10.2. Group 2: Store instructions</a><br>
+<a href="#2.10.3. Groups 3 and 4: Signed and unsigned integer arithmetic">2.10.3. Groups 3 and 4: Signed and unsigned integer arithmetic</a><br>
+<a href="#2.10.4. Group 5: Floating point arithmetic">2.10.4. Group 5: Floating point arithmetic</a><br>
+<a href="#2.10.5. Group 12: Compare instructions">2.10.5. Group 12: Compare instructions</a><br>
+<a href="#2.10.6. Group 9: Logical instructions">2.10.6. Group 9: Logical instructions</a><br>
+<a href="#2.10.7. Group 14: Procedure call instructions">2.10.7. Group 14: Procedure call instructions</a><br>
+<a href="#3. LIBRARY ROUTINES">3. LIBRARY ROUTINES</a><br>
+<a href="#4. TRAPS">4. TRAPS</a><br>
+<a href="#5. IMPLEMENTATION">5. IMPLEMENTATION</a><br>
+<a href="#6. INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086">6. INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086</a><br>
+<a href="#6.1. Introduction">6.1. Introduction</a><br>
+<a href="#6.2. Differences between the 8080 and z80 processors">6.2. Differences between the 8080 and z80 processors</a><br>
+<a href="#6.3. Consequences for the 8080 and z80 back end">6.3. Consequences for the 8080 and z80 back end</a><br>
+<a href="#6.4. What did I do?">6.4. What did I do?</a><br>
+<a href="#6.5. The results">6.5. The results</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Gerard Buskermolen</i></p>
+
+<p>A back end is a part of the Amsterdam Compiler Kit
+(ACK). It translates EM, a family of intermediate languages,
+into the assembly language of some target machine, here the
+Intel 8080 and Intel 8085 microprocessors. INTRODUCTION</p>
+
+<p>To simplify the task of producing portable (cross)
+compilers and interpreters, the Vrije Universiteit designed
+an integrated collection of programs, the Amsterdam Compiler
+Kit (ACK). It is based on the old UNCOL-idea ([4]) which
+attempts to solve the problem of making a compiler for each
+of <b>N</b> languages on <b>M</b> different machines without
+having to write <b>N * M</b> programs.</p>
+
+<p>The UNCOL approach is to write <b>N</b> &quot;front
+ends&quot;, each of which translates one source language
+into a common intermediate language, UNCOL (UNiversal
+Computer Oriented Language), and <b>M</b> &quot;back
+ends&quot;, each of which translates programs in UNCOL into
+a specific machine language. Under these conditions, only
+<b>N + M</b> programs should be written to provide all
+<b>N</b> languages on all <b>M</b> machines, instead of <b>N
+* M</b> programs.</p>
+
+<p>The intermediate language for the Amsterdam Compiler Kit
+is the machine language for a simple stack machine called EM
+(Encoding Machine). So a back end for the Intel 8080 micro
+translates EM code into 8080 assembly language.</p>
+
+<p>The back end is a single program that is driven by a
+machine dependent driving table. This driving table, or back
+end table, defines the mapping from EM code to the
+machine&rsquo;s assembly language.</p>
+<a name="1. THE 8080 MICRO PROCESSOR"></a>
+<h2>1. THE 8080 MICRO PROCESSOR</h2>
+
+<p>This back end table can be used without modification for
+the Intel 8085 processor. Except for two additional
+instructions, the 8085 instruction set is identical and
+fully compatible with the 8080 instruction set. So
+everywhere in this document &rsquo;8080&rsquo; can be read
+as &rsquo;8080 and 8085&rsquo;.</p>
+<a name="1.1. Registers"></a>
+<h2>1.1. Registers</h2>
+
+<p>The 8080 processor has an 8 bit accumulator, six general
+purpose 8-bit registers, a 16 bit programcounter and a 16
+bit stackpointer. Assembler programs can refer the
+accumulator by A and the general purpose registers by B, C,
+D, E, H and L. (*)</p>
+
+<p align=center><img src="grohtml-102111.png"></p>
+
+<p>Several instructions address registers in groups of two,
+thus creating 16 bit registers:</p>
+<pre>     Registers referenced:   Symbolic reference:
+           B and C                   B
+           D and E                   D
+           H and L                   H
+</pre>
+
+<p>The first named register, contains the high order byte
+(H and L stand for High and Low).<br>
+The instruction determines how the processor interprets the
+reference. For example, ADD B is an 8 bit operation, adding
+the contents of register B to accumulator A. By contrast
+PUSH B is a 16 bit operation pushing B and C onto the
+stack.</p>
+
+<p>There are no index registers.</p>
+<a name="1.2. Flip-flops"></a>
+<h2>1.2. Flip-flops</h2>
+
+<p>The 8080 microprocessor provides five flip-flops used as
+condition flags (S, Z, P, C, AC) and one interrupt enable
+flip-flop IE.<br>
+The sign bit S is set (cleared) by certain instructions when
+the most significant bit of the result of an operation
+equals one (zero). The zero bit Z is set (cleared) by
+certain operations when the 8-bit result of an operation
+equals (does not equal) zero. The parity bit P is set
+(cleared) if the 8-bit result of an operation includes an
+even (odd) number of ones. C is the normal carry bit. AC is
+an auxiliary carry that indicates whether there has been a
+carry out of bit 3 of the accumulator. This auxiliary carry
+is used only by the DAA instruction, which adjusts the 8-bit
+value in the accumulator to form two 4-bit binary coded
+decimal digits. Needless to say this instruction is not used
+in the back-end.</p>
+
+<p>The interrupt enable flip-flop IE is set and cleared
+under program control using the instructions EI (Enable
+Interrupt) and DI (Disable Interrupt). It is automatically
+cleared when the CPU is reset and when an interrupt occurs,
+disabling further interrupts until IE = 1 again.</p>
+<a name="1.3. Addressing modes"></a>
+<h2>1.3. Addressing modes</h2>
+<a name="1.3.1. Implied addressing"></a>
+<h2>1.3.1. Implied addressing</h2>
+
+<p>The addressing mode of some instructions is implied by
+the instruction itself. For example, the RAL (rotate
+accumulator left) instruction deals only with the
+accumulator, and PCHL loads the programcounter with the
+contents of register-pair HL.</p>
+<a name="1.3.2. Register addressing"></a>
+<h2>1.3.2. Register addressing</h2>
+
+<p>With each instruction using register addressing, only
+one register is specified (except for the MOV instruction),
+although in many of them the accumulator is implied as
+second operand. Examples are CMP E, which compares register
+E with the accumulator, and DCR B, which decrements register
+B. A few instructions deal with 16 bit register-pairs:
+examples are DCX B, which decrements register-pair BC and
+the PUSH and POP instructions.</p>
+<a name="1.3.3. Register indirect addressing"></a>
+<h2>1.3.3. Register indirect addressing</h2>
+
+<p>Each instruction that may refer to an 8 bit register,
+may refer also to a memory location. In this case the letter
+M (for Memory) has to be used instead of a register. It
+indicates the memory location pointed to by H and L, so ADD
+M adds the contents of the memory location specified by H
+and L to the contents of the accumulator.<br>
+The register-pairs BC and DE can also be used for indirect
+addressing, but only to load or store the accumulator. For
+example, STAX B stores the contents of the accumulator into
+the memory location addressed by register-pair BC.</p>
+<a name="1.3.4. Immediate addressing"></a>
+<h2>1.3.4. Immediate addressing</h2>
+
+<p>The immediate value can be an 8 bit value, as in ADI 10
+which adds 10 to the accumulator, or a 16 bit value, as in
+LXI H,1000, which loads 1000 in the register-pair HL.</p>
+<a name="1.3.5. Direct addressing"></a>
+<h2>1.3.5. Direct addressing</h2>
+
+<p>Jump instructions include a 16 bit address as part of
+the instruction.<br>
+The instruction SHLD 1234 stores the contents of register
+pair HL on memory locations 1234 and 1235. The high order
+byte is stored at the highest address.</p>
+<a name="2. THE 8080 BACK END TABLE"></a>
+<h2>2. THE 8080 BACK END TABLE</h2>
+
+<p>The back end table is designed as described in [5]. For
+an overall design of a back end table I refer to this
+document.<br>
+This section deals with problems encountered in writing the
+8080 back-end table. Some remarks are made about particular
+parts of the table that might not seem clear at first
+sight.</p>
+<a name="2.1. Constant definitions"></a>
+<h2>2.1. Constant definitions</h2>
+
+<p>Word size (EM_WSIZE) and pointer size (EM_PSIZE) are
+both defined as two bytes. The hole between AB and LB
+(EM_BSIZE) is four bytes: only the return address and the
+local base are saved.</p>
+<a name="2.2. Registers and their properties"></a>
+<h2>2.2. Registers and their properties</h2>
+
+<p>All properties have the default size of two bytes,
+because one-byte registers also cover two bytes when put on
+the real stack.</p>
+
+<p>The next considerations led to the choice of
+register-pair BC as local base. Though saving the local base
+in memory would leave one more register-pair available as
+scratch register, it would slow down instructions as
+&rsquo;lol&rsquo; and &rsquo;stl&rsquo; too much. So a
+register-pair should be sacrificed as local base. Because a
+back-end without a free register-pair HL is completely
+broken-winged, the only reasonable choices are BC and DE.
+Though the choice between them might seem arbitrary at first
+sight, there is a difference between register-pairs BC and
+DE: the instruction XCHG exchanges the contents of
+register-pairs DE and HL. When DE and HL are both heavily
+used on the fake-stack, this instruction is very useful.
+Since it won&rsquo;t be useful too often to exchange HL with
+the local base and since an instruction exchanging BC and HL
+does not exist, BC is chosen as local base.</p>
+
+<p>Many of the register properties are never mentioned in
+the PATTERNS part of the table. They are only needed to
+define the INSTRUCTIONS correctly.</p>
+
+<p>The properties really used in the PATTERNS part are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>areg:</p>
+</td>
+<td width="38%"></td>
+<td width="40%">
+
+<p>the accumulator only</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>reg:</p>
+</td>
+<td width="40%"></td>
+<td width="52%">
+
+<p>any of the registers A, D, E, H or L. Of course the
+registers B and C which are used as local base don&rsquo;t
+possess this property. When there is a single register on
+the fake-stack, its value is always considered
+non-negative.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>dereg:</p>
+</td>
+<td width="36%"></td>
+<td width="42%">
+
+<p>register-pair DE only</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>hlreg:</p>
+</td>
+<td width="36%"></td>
+<td width="42%">
+
+<p>register-pair HL only</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>hl_or_de:</p>
+</td>
+<td width="30%"></td>
+<td width="52%">
+
+<p>register-pairs HL and DE both have this property</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>local</p>
+</td>
+<td width="38%"></td>
+<td width="52%">
+
+<p>used only once (i.e. in the EM-instruction &rsquo;str
+0&rsquo;)</p>
+</td>
+</table>
+
+<p>The stackpointer SP and the processor status word PSW
+have to be defined explicitly because they are needed in
+some instructions (i.e. SP in LXI, DCX and INX and PSW in
+PUSH and POP).<br>
+It doesn&rsquo;t matter that the processor status word is
+not just register A but includes the condition flags.</p>
+<a name="2.3. Tokens"></a>
+<h2>2.3. Tokens</h2>
+
+<p>The tokens &rsquo;m&rsquo; and &rsquo;const1&rsquo; are
+used in the INSTRUCTIONS- and MOVES parts only. They will
+never be on the fake-stack.</p>
+
+<p>The token &rsquo;label&rsquo; reflects addresses known
+at assembly time. It is used to take full profit of the
+instructions LHLD (Load HL Direct) and SHLD (Store HL
+Direct).</p>
+
+<p>Compared with many other back-end tables, there are only
+a small number of different tokens (four). Reasons are the
+limited addressing modes of the 8080 microprocessor, no
+index registers etc. For example to translate the
+EM-instruction</p>
+<pre>     lol 10
+</pre>
+
+<p>the next 8080 instructions are generated:</p>
+<pre>LXI H,10        /* load registers pair HL with value 10 */
+DAD B           /* add local base (BC) to HL            */
+MOV E,M         /* load E with byte pointed to by HL    */
+INX H           /* increment HL                         */
+MOV D,M         /* load D with next byte                */
+</pre>
+
+<p>Of course, instead of emitting code immediately, it
+could be postponed by placing something like a {LOCAL,10} on
+the fake-stack, but some day the above mentioned code will
+have to be generated, so a LOCAL-token is hardly useful. See
+also the comment on the load instructions.</p>
+<a name="2.4. Sets"></a>
+<h2>2.4. Sets</h2>
+
+<p>Only &rsquo;src1or2&rsquo; is used in the PATTERNS.</p>
+<a name="2.5. Instructions"></a>
+<h2>2.5. Instructions</h2>
+
+<p>Each instruction indicates whether or not the condition
+flags are affected, but this information will never have any
+influence because there are no tests in the PATTERNS part of
+the table.</p>
+
+<p>For each instruction a cost vector indicates the number
+of bytes the instruction occupies and the number of time
+periods it takes to execute the instruction. The length of a
+time period depends on the clock frequency and may range
+from 480 nanoseconds to 2 microseconds on a 8080 system and
+from 320 nanoseconds to 2 microseconds on a 8085 system.</p>
+
+<p>In the TOKENS-part the cost of token &rsquo;m&rsquo; is
+defined as (0,3). In fact it usually takes 3 extra time
+periods when this register indirect mode is used instead of
+register mode, but since the costs are not completely
+orthogonal this results in small deficiencies for the DCR,
+INR and MOV instructions. Although it is not particularly
+useful these deficiencies are corrected in the INSTRUCTIONS
+part, by treating the register indirect mode separately.</p>
+
+<p>The costs of the conditional call and return
+instructions really depend on whether or not the call resp.
+return is actually made. However, this is not important to
+the behaviour of the back end.</p>
+
+<p>Instructions not used in this table have been commented
+out. Of course many of them are used in the library
+routines.</p>
+<a name="2.6. Moves"></a>
+<h2>2.6. Moves</h2>
+
+<p>This section is supposed to be straight-forward.</p>
+<a name="2.7. Tests"></a>
+<h2>2.7. Tests</h2>
+
+<p>The TESTS section is only included to refrain <b>cgg</b>
+from complaining.</p>
+<a name="2.8. Stacking rules"></a>
+<h2>2.8. Stacking rules</h2>
+
+<p>When, for example, the token {const2,10} has to be
+stacked while no free register-pair is available, the next
+code is generated:</p>
+<pre>     PUSH H
+     LXI H,10
+     XTHL
+</pre>
+
+<p>The last instruction exchanges the contents of HL with
+the value on top of the stack, giving HL its original value
+again.</p>
+<a name="2.9. Coercions"></a>
+<h2>2.9. Coercions</h2>
+
+<p>The coercion to unstack register A, is somewhat tricky,
+but unfortunately just popping PSW leaves the high-order
+byte in the accumulator.</p>
+
+<p>The cheapest way to coerce HL to DE (or DE to HL) is by
+using the XCHG instruction, but it is not possible to
+explain <b>cgg</b> this instruction in fact exchanges the
+contents of these register-pairs. Before the coercion is
+carried out other appearances of DE and HL on the fake-stack
+will be moved to the real stack, because in the
+INSTRUCTION-part is told that XCHG destroys the contents of
+both DE and HL. The coercion transposing one register-pair
+to another one by emitting two MOV-instructions, will be
+used only if one of the register-pairs is the local
+base.</p>
+<a name="2.10. Patterns"></a>
+<h2>2.10. Patterns</h2>
+
+<p>As a general habit I have allocated (uses ...) all
+registers that should be free to generate the code, although
+it is not always necessary. For example in the code rule</p>
+<pre>     pat loe
+     uses hlreg
+     gen lhld {label,$1}                   yields hl
+</pre>
+
+<p>the &rsquo;uses&rsquo;-clause could have been omitted
+because <b>cgg</b> knows that LHLD destroys register-pair
+HL.</p>
+
+<p>Since there is only one register with property
+&rsquo;hlreg&rsquo;, there is no difference between
+&rsquo;uses hlreg&rsquo; (allocate a register with property
+&rsquo;hlreg&rsquo;) and &rsquo;kills hlreg&rsquo; (remove
+all registers with property &rsquo;hlreg&rsquo; from the
+fake-stack). The same applies for the property
+&rsquo;dereg&rsquo;.<br>
+Consequently &rsquo;kills&rsquo; is rarely used in this
+back-end table.</p>
+<a name="2.10.1. Group 1: Load instructions"></a>
+<h2>2.10.1. Group 1: Load instructions</h2>
+
+<p>When a local variable must be squared, there will
+probably be EM-code like:</p>
+<pre>     lol 10
+     lol 10
+     mli 2
+</pre>
+
+<p>When the code for the first &rsquo;lol 10&rsquo; has
+been executed, DE contains the wanted value. To refrain
+<b>cgg</b> from emitting the code for &rsquo;lol 10&rsquo;
+again, an extra pattern is included in the table for cases
+like this. The same applies for two consecutive
+&rsquo;loe&rsquo;-s or &rsquo;lil&rsquo;-s.</p>
+
+<p>A bit tricky is &rsquo;lof&rsquo;. It expects either DE
+or HL on the fake-stack, moves {const2,$1} into the other
+one, and eventually adds them. The &rsquo;kills&rsquo; part
+is necessary here because if DE was on the fake-stack,
+<b>cgg</b> doesn&rsquo;t see that the contents of DE is
+destroyed by the code (in fact &rsquo;kills dereg&rsquo;
+would have been sufficient: because of the DAD instruction
+<b>cgg</b> knows that HL is destroyed).</p>
+
+<p>By lookahead, <b>cgg</b> can make a clever choice
+between the first and second code rule of &rsquo;loi
+4&rsquo;. The same applies for several other
+instructions.</p>
+<a name="2.10.2. Group 2: Store instructions"></a>
+<h2>2.10.2. Group 2: Store instructions</h2>
+
+<p>A similar idea as with the two consecutive identical
+load instructions in Group 1, applies for a store
+instruction followed by a corresponding load
+instruction.</p>
+<a name="2.10.3. Groups 3 and 4: Signed and unsigned integer arithmetic"></a>
+<h2>2.10.3. Groups 3 and 4: Signed and unsigned integer arithmetic</h2>
+
+<p>Since the 8080 instruction set doesn&rsquo;t provide
+multiply and divide instructions, special routines are made
+to accomplish these tasks.</p>
+
+<p>Instead of providing four slightly differing routines
+for 16 bit signed or unsigned division, yielding the
+quotient or the remainder, the routines are merged. This
+saves space and assembly time when several variants are used
+in a particular program, at the cost of a little speed. When
+the routine is called, bit 7 of register A indicates whether
+the operands should be considered as signed or as unsigned
+integers, and bit 0 of register A indicates whether the
+quotient or the remainder has to be delivered.<br>
+The same applies for 32 bit division.</p>
+
+<p>The routine doing the 16 bit unsigned multiplication
+could have been used for 16 bit signed multiplication too.
+Nevertheless a special 16 bit signed multiplication routine
+is provided, because this one will usually be much
+faster.</p>
+<a name="2.10.4. Group 5: Floating point arithmetic"></a>
+<h2>2.10.4. Group 5: Floating point arithmetic</h2>
+
+<p>Floating point is not implemented. Whenever an
+EM-instruction involving floating points is offered to the
+code-generator, it calls the corresponding library routine
+with the proper parameters. Each floating point library
+routine calls &rsquo;eunimpl&rsquo;, trapping with trap
+number 63. Some of the Pascal and C library routines output
+floating point EM-instructions, so code has to be generated
+for them. Of course this does not imply the code will ever
+be executed.</p>
+<a name="2.10.5. Group 12: Compare instructions"></a>
+<h2>2.10.5. Group 12: Compare instructions</h2>
+
+<p>The code for &rsquo;cmu 2&rsquo;, with its 4 labels, is
+terrible. But it is the best I could find.</p>
+<a name="2.10.6. Group 9: Logical instructions"></a>
+<h2>2.10.6. Group 9: Logical instructions</h2>
+
+<p>I have tried to merge both variants of the instructions
+&rsquo;and 2&rsquo;, &rsquo;ior 2&rsquo; and &rsquo;xor
+2&rsquo;, as in</p>
+<pre>     pat and $1==2
+     with hl_or_de hl_or_de
+     uses reusing %1, reusing %2, hl_or_de, areg
+     gen mov a,%1.2
+         ana %2.2
+         mov %a.2,a
+         mov a,%1.1
+         ana %2.1
+         mov %a.1,a                     yields %a
+</pre>
+
+<p>but the current version of <b>cgg</b> doesn&rsquo;t
+approve this. In any case <b>cgg</b> chooses either DE or HL
+to store the result, using lookahead.</p>
+<a name="2.10.7. Group 14: Procedure call instructions"></a>
+<h2>2.10.7. Group 14: Procedure call instructions</h2>
+
+<p>There is an 8 bytes function return area, called
+&rsquo;.fra&rsquo;. If only 2 bytes have to be returned,
+register-pair DE is used.</p>
+<a name="3. LIBRARY ROUTINES"></a>
+<h2>3. LIBRARY ROUTINES</h2>
+
+<p>Most of the library routines start with saving the
+return address and the local base, so that the parameters
+are on the top of the stack and the registers B and C are
+available as scratch registers. Since register-pair HL is
+needed to accomplish these tasks, and also to restore
+everything just before the routine returns, it is not
+possible to transfer data between the routines and the
+surrounding world through register H or L. Only registers A,
+D and E can be used for this.</p>
+
+<p>When a routine returns 2 bytes, they are usually
+returned in registers-pair DE. When it returns more than 2
+bytes they are pushed onto the stack.<br>
+It would have been possible to let the 32 bit arithmetic
+routines return 2 bytes in DE and the remaining 2 bytes on
+the stack (this often would have saved some space and
+execution time), but I don&rsquo;t consider that as
+well-structured programming.</p>
+<a name="4. TRAPS"></a>
+<h2>4. TRAPS</h2>
+
+<p>Whenever a trap, for example trying to divide by zero,
+occurs in a program that originally was written in C or
+Pascal, a special trap handler is called. This trap handler
+wants to write an appropriate error message on the monitor.
+It tries to read the message from a file (e.g.
+etc/pc_rt_errors in the EM home directory for Pascal
+programs), but since the 8080 back-end doesn&rsquo;t know
+about files, we are in trouble. This problem is solved, as
+far as possible, by including the &rsquo;open&rsquo;-monitor
+call in the mon-routine. It returns with file descriptor -1.
+The trap handler reacts by generating another trap, with the
+original trap number. But this time, instead of calling the
+C- or Pascal trap handler again, the next message is printed
+on the monitor:</p>
+<pre>        trap number &lt;TN&gt;
+        line &lt;LN&gt; of file &lt;FN&gt;
+
+
+where   &lt;TN&gt; is the trap number (decimal)
+        &lt;LN&gt; is the line number (decimal)
+        &lt;FN&gt; is the filename of the original program
+</pre>
+
+<p>Trap numbers are subdivided as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>1-27:</p>
+</td>
+<td width="30%"></td>
+<td width="60%">
+
+<p>EM-machine error, as described in [3]</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>63:</p>
+</td>
+<td width="34%"></td>
+<td width="60%">
+
+<p>an unimplemented EM-instruction is used</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>64-127:</p>
+</td>
+<td width="26%"></td>
+<td width="60%">
+
+<p>generated by compilers, runtime systems, etc.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>128-252:</p>
+</td>
+<td width="24%"></td>
+<td width="52%">
+
+<p>generated by user programs</p>
+</td>
+<td width="7%">
+</td>
+</table>
+<a name="5. IMPLEMENTATION"></a>
+<h2>5. IMPLEMENTATION</h2>
+
+<p>It will not be possible to run the entire Amsterdam
+Compiler Kit on a 8080-based computer system. One has to
+write a program on another system, a system where the
+compiler kit runs on. This program may be a mixture of
+high-level languages, such as C or Pascal, EM and 8080
+assembly code. The program should be compiled using the
+compiler kit, producing 8080 machine code. This code should
+come available to the 8080 machine for example by
+downloading or by storing it in ROM (Read Only Memory).</p>
+
+<p>Depending on the characteristics of the particular 8080
+based system, some adaptations have to be made:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>In &rsquo;head_em&rsquo;: the base address, which is the
+address where the first 8080 instruction will be stored, and
+the initial value of the stackpointer are set to 0x1000 and
+0x8000 respectively.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Other systems require other values.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>In &rsquo;head_em&rsquo;: before calling
+&quot;__m_a_i_n&quot;, the environment pointer, argument
+vector and argument count will have to be pushed onto the
+stack. Since this back-end is tested on a system without any
+knowledge of these things, dummies are pushed now.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>In &rsquo;tail_em&rsquo;: proper routines
+&quot;putchar&quot; and &quot;getchar&quot; should be
+provided. They should write resp. read a character on/from
+the monitor. Maybe some conversions will have to be
+made.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>In &rsquo;head_em&rsquo;: an application program returns
+control to the monitor by jumping to address 0xFB52. This
+may have to be changed for different systems.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5)</p>
+</td>
+<td width="16%"></td>
+<td width="80%">
+
+<p>In &rsquo;tail_em&rsquo;: the current version of the
+8080 back-end has very limited I/O capabilities, because it
+was tested on a system that had no knowledge of files. So
+the implementation of the EM-instruction &rsquo;mon&rsquo;
+is very simple; it can only do the following things:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="30%">
+
+<p>Monitor call 1:</p>
+</td>
+<td width="50%"></td>
+<td width="0%">
+
+<p>exit</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="30%">
+
+<p>Monitor call 3:</p>
+</td>
+<td width="50%"></td>
+<td width="0%">
+
+<p>read, always reads from the monitor.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="99%"></td>
+<td width="0%">
+<p>echos the read character.<br>
+ignores file descriptor.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="30%">
+
+<p>Monitor call 4:</p>
+</td>
+<td width="50%"></td>
+<td width="0%">
+
+<p>write, always writes on the monitor.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="99%"></td>
+<td width="0%">
+<p>ignores file descriptor.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="30%">
+
+<p>Monitor call 5:</p>
+</td>
+<td width="50%"></td>
+<td width="0%">
+
+<p>open file, returns file descriptor -1.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="99%"></td>
+<td width="0%">
+<p>(compare chapter about TRAPS)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="30%">
+
+<p>Monitor call 6:</p>
+</td>
+<td width="50%"></td>
+<td width="0%">
+
+<p>close file, returns error code = 0.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="32%">
+
+<p>Monitor call 54:</p>
+</td>
+<td width="48%"></td>
+<td width="0%">
+
+<p>io-control, returns error code = 0.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>If the system should do file-handling the routine
+&quot;.mon&quot; should be extended thoroughly.</p></td>
+</table>
+<a name="6. INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086"></a>
+<h2>6. INTEL 8080 VERSUS ZILOG Z80 AND INTEL 8086</h2>
+<a name="6.1. Introduction"></a>
+<h2>6.1. Introduction</h2>
+
+<p>At about the same time I developed the back end for the
+Intel 8080 and Intel 8085, Frans van Haarlem did the same
+job for the Zilog z80 microprocessor. Since the z80
+processor is an extension of the 8080, any machine code
+offered to a 8080 processor can be offered to a z80 too. The
+assembly languages are quite different however.<br>
+During the developments of the back ends we have used two
+micro-computers, both equipped with a z80 microprocessor. Of
+course the output of the 8080 back end is assembled by an
+8080 assembler. This should assure I have never used any of
+the features that are potentially available in the z80
+processor, but are not part of a true 8080 processor.</p>
+
+<p>As a final job, I have investigated the differences
+between the 8080 and z80 processors and their influence on
+the back ends. I have tried to measure this influence by
+examining the length of the generated code. I have also
+involved the 8086 micro-processor in this measurements.</p>
+<a name="6.2. Differences between the 8080 and z80 processors"></a>
+<h2>6.2. Differences between the 8080 and z80 processors</h2>
+
+<p>Except for some features that are less important
+concerning back ends, there are two points where the z80
+improves upon the 8080:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>First,</p>
+</td>
+<td width="24%"></td>
+<td width="64%">
+
+<p>the z80 has two additional index registers, IX and IY.
+They are used as in</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="64%">
+<pre>              LD B,(IX+10)
+</pre>
+<!-- INDENTATION -->
+<p>The offset, here 10, should fit in one byte.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>Second,</p>
+</td>
+<td width="22%"></td>
+<td width="64%">
+
+<p>the z80 has several additional instructions. The most
+important ones are:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>The 8080 can only load or store register-pair HL direct
+(using LHLD or SHLD). The z80 can handle BC, DE and SP
+too.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>Instructions are included to ease block movements.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>There is a 16 bit subtract instruction.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="4%">
+
+<p>4)</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>While the 8080 can only rotate the accumulator, the z80
+can rotate and shift each 8 bit register.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="4%">
+
+<p>5)</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>Special routines are included to jump to near locations,
+saving 1 byte.</p>
+</td>
+</table>
+<a name="6.3. Consequences for the 8080 and z80 back end"></a>
+<h2>6.3. Consequences for the 8080 and z80 back end</h2>
+
+<p>The most striking difference between the 8080 and z80
+back ends is the choice of the local base. The writer of the
+z80 back end chose index register IY as local base, because
+this results in the cheapest coding of EM-instructions like
+&rsquo;lol&rsquo; and &rsquo;stl&rsquo;. The z80
+instructions that load local 10, for example</p>
+<pre>     LD E,(IY+10)
+     LD D,(IY+11)
+</pre>
+
+<p>occupy 6 bytes and take 38 time periods to execute. The
+five corresponding 8080 instructions loading a local occupy
+7 bytes and take 41 time periods. Although the profit of the
+z80 might be not world-shocking, it should be noted that as
+a side effect it may save some pushing and popping since
+register pair HL is not used.</p>
+
+<p>The choice of IY as local base has its drawbacks too.
+The root of the problem is that it is not possible to add IY
+to HL. For the EM-instruction</p>
+<pre>     lal 20
+</pre>
+
+<p>the z80 back end generates code like</p>
+<pre>     LD BC,20
+     PUSH IY
+     POP HL
+     ADD HL,BC
+</pre>
+
+<p>leaving the wanted address in HL.<br>
+This annoying push and pop instructions are also needed in
+some other instructions, for instance in &rsquo;lol&rsquo;
+when the offset doesn&rsquo;t fit in one byte.</p>
+
+<p>Beside the choice of the local base, I think there is no
+fundamental difference between the 8080 and z80 back ends,
+except of course that the z80 back end has register pair BC
+and, less important, index register IX available as scratch
+registers.</p>
+
+<p>Most of the PATTERNS in the 8080 and z80 tables are more
+or less a direct translation of each other.</p>
+<a name="6.4. What did I do?"></a>
+<h2>6.4. What did I do?</h2>
+
+<p>To get an idea of the quality of the code generated by
+the 8080, z80 and 8086 back ends I have gathered some C
+programs and some Pascal programs. Then I produced 8080, z80
+and 8086 code for them. Investigating the assembler listing
+I found the lengths of the different parts of the generated
+code. I have checked two areas:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="12%"></td>
+<td width="40%">
+
+<p>the entire text part</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="12%"></td>
+<td width="84%">
+
+<p>the text part without any library routine, so only the
+plain user program</p>
+</td>
+</table>
+
+<p>I have to admit that neither one of them is really
+honest. When the entire text part is checked, the result is
+disturbed because not always the same library routines are
+loaded. And when only the user program itself is considered,
+the result is disturbed too. For example the 8086 has a
+multiply instruction, so the EM-instruction &rsquo;mli
+2&rsquo; is translated in the main program, but the 8080 and
+z80 call a library routine that is not counted. Also the
+8080 uses library routines at some places where the z80 does
+not.</p>
+
+<p>But nevertheless I think the measurements will give an
+idea about the code produced by the three back ends.</p>
+<a name="6.5. The results"></a>
+<h2>6.5. The results</h2>
+
+<p>The table below should be read as follows. For all
+programs I have computed the ratio of the code-lengths of
+the 8080, z80 and 8086. The averages of all Pascal/C
+programs are listed in the table, standardized to
+&rsquo;100&rsquo; for the 8080. So the listed
+&rsquo;107&rsquo; indicates that the lengths of the text
+parts of the z80 programs that originally were Pascal
+programs, averaged 7 percent larger than in the
+corresponding 8080 programs.</p>
+
+
+<p align=center>--------------------------------------------------<br>
+| | 8080 | z80 | 8086 |<br>
+--------------------------------------------------<br>
+| C, text part | 100 | 103 | 65 |<br>
+| Pascal, text part | 100 | 107 | 55 |<br>
+| C, user program | 100 | 110 | 71 |<br>
+| Pascal, user program | 100 | 118 | 67 |<br>
+--------------------------------------------------</p>
+
+<p>The most striking thing in this table is that the z80
+back end appears to produce larger code than the 8080 back
+end. The reason is that the current z80 back end table is
+not very sophisticated yet. For instance it doesn&rsquo;t
+look for any EM-pattern longer than one. So the table shows
+that the preparations in the 8080 back end table to produce
+faster code (like recognizing special EM-patterns and
+permitting one byte registers on the fake-stack) was not
+just for fun, but really improved the generated code
+significantly.</p>
+
+<p>The table shows that the 8080 table is relatively better
+when only the plain user program is considered instead of
+the entire text part. This is not very surprising since the
+8080 back end sometimes uses library routines where the z80
+and especially the 8086 don&rsquo;t.</p>
+
+<p>The difference between the 8080 and z80 on the one hand
+and the 8086 on the other is very big. But of course it was
+not equal game: the 8086 is a 16 bit processor that is much
+more advanced than the 8080 or z80 and the 8086 back end is
+known to produce very good code.</p>
+
+<p><b>REFERENCES</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[1]</p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p>8080/8085 Assembly Language Programming Manual,</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Intel Corporation (1977,1978)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[2]</p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p>Andrew S. Tanenbaum, Hans van Staveren, E.G. Keizer and
+Johan W. Stevenson,</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>A practical tool kit for making portable compilers,<br>
+Informatica report 74, Vrije Universiteit, Amsterdam,
+1983.</p>
+<!-- INDENTATION -->
+<p>An overview on the Amsterdam Compiler Kit.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[3]</p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p>Tanenbaum, A.S., Stevenson, J.W., Keizer, E.G., and van
+Staveren, H.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Description of an experimental machine architecture for
+use with block structured languages,<br>
+Informatica report 81, Vrije Universiteit, Amsterdam,
+1983.</p>
+<!-- INDENTATION -->
+<p>The defining document for EM.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[4]</p>
+</td>
+<td width="14%"></td>
+<td width="32%">
+
+<p>Steel, T.B., Jr.</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>UNCOL: The myth and the Fact. in Ann. Rev. Auto.
+Prog.<br>
+Goodman, R. (ed.), vol. 2, (1960), p325-344.</p>
+<!-- INDENTATION -->
+<p>An introduction to the UNCOL idea by its originator.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[5]</p>
+</td>
+<td width="14%"></td>
+<td width="36%">
+
+<p>van Staveren, Hans</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>The table driven code generator from the Amsterdam
+Compiler Kit (Second Revised Edition),<br>
+Vrije Universiteit, Amsterdam.</p>
+<!-- INDENTATION -->
+<p>The defining document for writing a back end table.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[6]</p>
+</td>
+<td width="14%"></td>
+<td width="20%">
+
+<p>Voors, Jan</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>A back end for the Zilog z8000 micro,<br>
+Vrije Universiteit, Amsterdam.</p>
+<!-- INDENTATION -->
+<p>A document like this one, but for the z8000.</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/i80.pdf b/doc/tack/i80.pdf
new file mode 100644 (file)
index 0000000..13c6484
Binary files /dev/null and b/doc/tack/i80.pdf differ
diff --git a/doc/tack/install.html b/doc/tack/install.html
new file mode 100644 (file)
index 0000000..d7e4fd5
--- /dev/null
@@ -0,0 +1,2645 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:16:57 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Amsterdam Compiler Kit Installation Guide</title>
+</head>
+<body>
+
+<h1 align=center>Amsterdam Compiler Kit Installation Guide</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The ACK installation process">2. The ACK installation process</a><br>
+<a href="#3. Restoring the ACK tree">3. Restoring the ACK tree</a><br>
+<a href="#4. Adapting ACK to the local system">4. Adapting ACK to the local system</a><br>
+<a href="#5. Compiling the Kit">5. Compiling the Kit</a><br>
+<a href="#5.1. Problems">5.1. Problems</a><br>
+<a href="#5.1.1. on Unisoft m68000 systems.">5.1.1. on Unisoft m68000 systems.</a><br>
+<a href="#5.1.2. with backends">5.1.2. with backends</a><br>
+<a href="#5.2. An example output of TakeAction.">5.2. An example output of TakeAction.</a><br>
+<a href="#6. Commands">6. Commands</a><br>
+<a href="#7. Machines">7. Machines</a><br>
+<a href="#8. Compilation on a different machine.">8. Compilation on a different machine.</a><br>
+<a href="#8.1. Backend">8.1. Backend</a><br>
+<a href="#8.2. Universal assembler/loader, link editor">8.2. Universal assembler/loader, link editor</a><br>
+<a href="#9. Options">9. Options</a><br>
+<a href="#9.1. Default machine">9.1. Default machine</a><br>
+<a href="#9.2. Pathnames">9.2. Pathnames</a><br>
+<a href="#10. Makefiles">10. Makefiles</a><br>
+<a href="#11. Testing">11. Testing</a><br>
+<a href="#12. Documentation">12. Documentation</a><br>
+
+<hr>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>This document describes the process of installing the
+Amsterdam Compiler Kit (ACK). It depends on the combination
+of hard- and software how hard it will be to install the
+Kit. This description is intended for a Sun-3 or SPARC
+workstation. Installation on VAXen running Berkeley
+<small>UNIX</small> &reg; or Ultrix, Sun-2 systems and most
+System V <small>UNIX</small> systems should be easy. As of
+this distribution, installation on PDP-11&rsquo;s or other
+systems with a small address space is no longer supported.
+See section 8 for installation on other systems.</p>
+<a name="2. The ACK installation process"></a>
+<h2>2. The ACK installation process</h2>
+
+<p>In the ACK installation process, three directory trees
+are used:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the ACK source tree. This is the tree on the ACK
+distribution medium. For the rest of this document, we will
+refer to this directory as $SRC_HOME;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>a configuration tree. This tree is built by the
+installation process and is used to do compilations in. Its
+structure reflects that of the source tree, but this tree
+will mostly contain Makefiles and relocatable objects. For
+the rest of this document, we will refer to this directory
+as $CONFIG;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>an ACK users tree. This tree is also built by the
+installation process. For the rest of this document, we will
+refer to this directory as $TARGET_HOME;</p>
+</td>
+</table>
+
+<p>After installation, the directories in $TARGET_HOME
+contain the following information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>bin</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>the few utilities that knot things together. See the
+section about &quot;Commands&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>lib</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>root of a tree containing almost all libraries used by
+commands. Files specific to a certain machine are collected
+in one subtree per machine. E.g. &quot;lib/pdp&quot;,
+&quot;lib/z8000&quot;. The names used here are the same
+names as used for subtrees of
+&quot;$SRC_HOME/mach&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>lib/descr</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>command descriptor files used by the program ack.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>lib/LLgen</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>files used by the LL(1) parser generator.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>lib/flex</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>files used by the lexical analyzer generator Flex.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>lib/m2</p>
+</td>
+<td width="16%"></td>
+<td width="64%">
+
+<p>definition modules for Modula-2.</p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>lib.bin</p>
+</td>
+<td width="14%"></td>
+<td width="72%">
+
+<p>root of a tree containing almost all binaries used by
+commands. All programs specific to a certain machine are
+collected in one subtree per machine. E.g.
+&quot;lib.bin/pdp&quot;, &quot;lib.bin/z8000&quot;. The
+names used here are the same names as used for subtrees of
+&quot;$SRC_HOME/mach&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>lib.bin/ego</p>
+</td>
+<td width="6%"></td>
+<td width="70%">
+
+<p>files used by the global optimizer.</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lib.bin/lint</p>
+</td>
+<td width="4%"></td>
+<td width="72%">
+
+<p>binaries for the lint passes and lint libraries.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>lib.bin/ceg</p>
+</td>
+<td width="6%"></td>
+<td width="72%">
+
+<p>files used by the code-expander-generator.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>etc</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>contains the file &quot;ip_spec.t&quot; needed for EM
+interpreters and EM documentation.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>config</p>
+</td>
+<td width="16%"></td>
+<td width="54%">
+
+<p>contains two include files:</p>
+</td>
+<td width="17%">
+</td>
+</table>
+
+<p align=center><img src="grohtml-96851.png"></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>These include files are specific for the current machine,
+so they are in a separate directory.</p>
+</td>
+</table>
+
+<p>include/_tail_cc</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>include files needed by modules in the C library from
+lang/cem/libcc.</p>
+</td>
+</table>
+
+<p>include/tail_ac</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>include files for ANSI C.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p>include/occam</p>
+</td>
+<td width="2%"></td>
+<td width="48%">
+
+<p>include files for occam.</p>
+</td>
+<td width="23%">
+</td>
+</table>
+
+<p>include/_tail_mon</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>more or less system independent include files needed by
+modules in the library lang/cem/libcc/mon.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>h</p>
+</td>
+<td width="26%"></td>
+<td width="46%">
+
+<p>the #include files for:</p>
+</td>
+<td width="25%">
+</td>
+</table>
+
+<p align=center><img src="grohtml-96852.png"></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>modules</p>
+</td>
+<td width="14%"></td>
+<td width="72%">
+
+<p>root of a tree containing modules for compiler
+writers.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>modules/man</p>
+</td>
+<td width="6%"></td>
+<td width="58%">
+
+<p>manual pages for all modules.</p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>modules/lib</p>
+</td>
+<td width="6%"></td>
+<td width="48%">
+
+<p>contains module objects.</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>modules/h</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>include files for some of the modules.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>modules/pkg</p>
+</td>
+<td width="6%"></td>
+<td width="72%">
+
+<p>include files for some of the modules.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>doc</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>this directory contains the unformatted documents for
+the Kit. A list of the available documents can be found in
+the last section. These documents must be processed by
+[nt]roff.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>man</p>
+</td>
+<td width="22%"></td>
+<td width="64%">
+
+<p>man files for various utilities.</p>
+</td>
+<td width="7%">
+</td>
+</table>
+
+<p>When installing ACK on several types of machines with a
+shared file system, it may be useful to know that the
+&quot;doc&quot;, &quot;etc&quot;, &quot;h&quot;,
+&quot;include&quot;, &quot;lib&quot; and &quot;man&quot;
+sub-directories do not depend on this particular
+installation. They do not contain binaries or path-dependent
+information. These directories can therefore be shared
+between the ACK installations. This can be accomplished by
+creating the tree and suitable symbolic links before
+starting the installation process.</p>
+
+<p>For instance, let us say there is a file-system that is
+accessible from the different machines as
+&quot;/usr/share/local&quot;, and the ACK binary tree must
+be installed in &quot;/usr/local/ack&quot;. In this case,
+proceed as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>create a directory &quot;/usr/share/local/ack&quot;,
+with subdirectories &quot;doc&quot;, &quot;etc&quot;,
+&quot;h&quot;, &quot;include&quot;, &quot;lib&quot; and
+&quot;man&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>create a directory &quot;/usr/local/ack&quot; and then
+create symbolic links &quot;doc&quot; to
+&quot;/usr/share/local/ack/doc&quot;, etc.</p>
+</td>
+</table>
+
+<p>If this is done on all machines on which ACK will be
+installed, the machine-independent part only has to be
+installed once, preferably on the fastest processor (it
+takes a long time to install all libraries).</p>
+
+<p>The directories in the source tree contain the following
+information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>bin</p>
+</td>
+<td width="22%"></td>
+<td width="58%">
+
+<p>source of some shell-scripts.</p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>lib</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>mostly description files for the &quot;ack&quot;
+program.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>etc</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>the main description of EM sits here. Files (e.g.
+em_table) describing the opcodes and pseudos in use, the
+operands allowed, effect in stack etc. etc.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>mach</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>just there to group the directories with all sources for
+each machine. The section about &quot;Machines&quot; of this
+manual indicates which subdirectories are used for which
+systems.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>These directories have subdirectories named:</p></td>
+</table>
+
+<p align=center><img src="grohtml-96853.png"></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>Actually, some of these directories will only appear in
+the configuration tree.<br>
+The directory proto contains files used by most machines,
+like machine-independent sources and Makefiles.</p></td>
+</table>
+
+<p align=center><img src="grohtml-96854.png"></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>emtest</p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p>contains prototype of em test set.</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>lang</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>just there to group the directories for all
+front-ends.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>lang/pc</p>
+</td>
+<td width="14%"></td>
+<td width="42%">
+
+<p>the Pascal front-end.</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p>lang/pc/libpc</p>
+</td>
+<td width="73%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>source of Pascal run-time system (in EM or C).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/pc/test</p>
+</td>
+<td width="4%"></td>
+<td width="72%">
+
+<p>some test programs written in Pascal.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/pc/comp</p>
+</td>
+<td width="4%"></td>
+<td width="54%">
+
+<p>the Pascal compiler proper.</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>lang/cem</p>
+</td>
+<td width="12%"></td>
+<td width="32%">
+
+<p>the C front-end.</p>
+</td>
+<td width="39%">
+</td>
+</table>
+
+<p>lang/cem/libcc</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>directories with sources of C runtime system, libraries
+(in EM or C).</p>
+</td>
+</table>
+
+<p>lang/cem/libcc/gen</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>sources for routines in chapter III of
+<small>UNIX</small> programmers manual, excluding stdio.</p>
+</td>
+</table>
+
+<p>lang/cem/libcc/stdio</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>stdio sources.</p>
+</td>
+</table>
+
+<p>lang/cem/libcc/math</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>sources for mathematical routines, normally available
+with the <b>-lm</b> option to <i>cc</i>.</p>
+</td>
+</table>
+
+<p>lang/cem/libcc/mon</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>sources for routines in chapter II, mostly written in
+EM.</p>
+</td>
+</table>
+
+<p>lang/cem/cemcom</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the compiler proper.</p>
+</td>
+</table>
+
+<p>lang/cem/cemcom.ansi</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the ANSI C compiler proper.</p>
+</td>
+</table>
+
+<p>lang/cem/cpp.ansi</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the ANSI C preprocessor.</p>
+</td>
+</table>
+
+<p>lang/cem/libcc.ansi</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the ANSI C library sources.</p>
+</td>
+</table>
+
+<p>lang/cem/ctest</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the C test set.</p>
+</td>
+</table>
+
+<p>lang/cem/ctest/cterr</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>programs developed for pinpointing previous errors.</p>
+</td>
+</table>
+
+<p>lang/cem/ctest/ct*</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the test programs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p>lang/cem/lint</p>
+</td>
+<td width="2%"></td>
+<td width="40%">
+
+<p>a C program checker.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+
+<p>lang/cem/lint/lpass1</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the first pass of lint.</p>
+</td>
+</table>
+
+<p>lang/cem/lint/lpass1.ansi</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the first pass of lint, this time for ANSI C.</p>
+</td>
+</table>
+
+<p>lang/cem/lint/lpass2</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the second pass of lint, shared between ANSI C and
+&quot;old-fashioned&quot; C.</p>
+</td>
+</table>
+
+<p>lang/cem/lint/llib</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>programs for producing lint libraries.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>lang/basic</p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p>the Basic front-end.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+
+<p>lang/basic/src</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the compiler proper.</p>
+</td>
+</table>
+
+<p>lang/basic/lib</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the Basic run-time library source.</p>
+</td>
+</table>
+
+<p>lang/basic/test</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>various Basic programs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>lang/occam</p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p>the occam front-end.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+
+<p>lang/occam/comp</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the compiler proper.</p>
+</td>
+</table>
+
+<p>lang/occam/lib</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>source of occam run-time system (in EM or C).</p>
+</td>
+</table>
+
+<p>lang/occam/test</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>some occam programs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>lang/m2</p>
+</td>
+<td width="14%"></td>
+<td width="46%">
+
+<p>the Modula-2 front-end.</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/m2/comp</p>
+</td>
+<td width="4%"></td>
+<td width="40%">
+
+<p>the compiler proper.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p>lang/m2/libm2</p>
+</td>
+<td width="2%"></td>
+<td width="72%">
+
+<p>source of Modula-2 run-time system (in EM, C and
+Modula-2).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/m2/m2mm</p>
+</td>
+<td width="4%"></td>
+<td width="64%">
+
+<p>the Modula-2 makefile generator.</p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/m2/test</p>
+</td>
+<td width="4%"></td>
+<td width="62%">
+
+<p>some Modula-2 example programs.</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>lang/fortran</p>
+</td>
+<td width="4%"></td>
+<td width="72%">
+
+<p>the Fortran front-end (translates Fortran into C). This
+compiler is not a part of ACK, but is included because it
+adds another language. The Fortran system carries the
+following copyright notice:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<pre>/**************************************************************
+Copyright 1990, 1991 by AT&amp;T Bell Laboratories and Bellcore.
+
+Permission to use, copy, modify, and distribute this software
+and its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the names of AT&amp;T Bell Laboratories or
+Bellcore or any of their entities not be used in advertising or
+publicity pertaining to distribution of the software without
+specific, written prior permission.
+
+AT&amp;T and Bellcore disclaim all warranties with regard to this
+software, including all implied warranties of merchantability
+and fitness.  In no event shall AT&amp;T or Bellcore be liable for
+any special, indirect or consequential damages or any damages
+whatsoever resulting from loss of use, data or profits, whether
+in an action of contract, negligence or other tortious action,
+arising out of or in connection with the use or performance of
+this software.
+**************************************************************/
+</pre>
+</td>
+</table>
+
+<p>lang/fortran/comp</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the compiler proper.</p>
+</td>
+</table>
+
+<p>lang/fortran/lib</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>source of Fortran runtime system and libraries.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>fast</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>contains sub-directories for installing the fast ACK
+compatible compilers.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>fast/driver</p>
+</td>
+<td width="77%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>contains the sources of the fast ACK compatible compiler
+drivers.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>fcc</p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>contains the fast cc-compatible C compiler for SUN-3 and
+VAX.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>util</p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>contains directories with sources for various
+utilities.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/ack</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the program used for translation with the Kit.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/opt</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the EM peephole optimizer (*.k =&gt; *.m).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/ego</p>
+</td>
+<td width="12%"></td>
+<td width="42%">
+
+<p>the global optimizer.</p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>util/topgen</p>
+</td>
+<td width="6%"></td>
+<td width="62%">
+
+<p>the target optimizer generator.</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>util/misc</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>decode (*.[km] =&gt; *.e) + encode (*.e =&gt; *.k).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>util/data</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>the C-code for $TARGET_HOME/lib.bin/em_data.a. These
+sources are created by the Makefile in
+&lsquo;etc&lsquo;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/ass</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the EM assembler (*.[km] + libraries =&gt; e.out).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>util/arch</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>the archivers to be used for all EM utilities.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/cgg</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>a program needed for compiling backends.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>util/ncgg</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>a program needed for compiling the newest backends.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/cpp</p>
+</td>
+<td width="12%"></td>
+<td width="38%">
+
+<p>the C preprocessor.</p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/shf</p>
+</td>
+<td width="12%"></td>
+<td width="40%">
+
+<p>various shell files.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>util/LLgen</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>the extended LL(1) parser generator.</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>util/amisc</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>contains some programs handling ACK a.out format, such
+as anm, asize.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>util/cmisc</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>contains some programs to help in resolving name
+conflicts, and a dependency generator for makefiles.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/led</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the ACK link-editor, reading ACK relocatable a.out
+format, and writing ACK a.out format.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/int</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>an EM interpreter, written in C. Very useful for
+checking out software, but slow.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>util/ceg</p>
+</td>
+<td width="12%"></td>
+<td width="48%">
+
+<p>code expander generator.</p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>util/grind</p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p>a symbolic debugger.</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>util/byacc</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>this is Berkeley yacc, in the public domain.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>util/flex</p>
+</td>
+<td width="10%"></td>
+<td width="72%">
+
+<p>this is a replacement for lex. It carries the following
+copyright notice:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<pre>Copyright (c) 1990 The Regents of the University of California.
+All rights reserved.
+
+This code is derived from software contributed to Berkeley by
+Vern Paxson.
+
+The United States Government has rights in this work pursuant
+to contract no. DE-AC03-76SF00098 between the United States
+Department of Energy and the University of California.
+
+Redistribution and use in source and binary forms are permitted
+provided that: (1) source distributions retain this entire
+copyright notice and comment, and (2) distributions including
+binaries display the following acknowledgement:  &lsquo;&lsquo;This product
+includes software developed by the University of California,
+Berkeley and its contributors&rsquo;&rsquo; in the documentation or other
+materials provided with the distribution and in all advertising
+materials mentioning features or use of this software.  Neither the
+name of the University nor the names of its contributors may be
+used to endorse or promote products derived from this software
+without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED &lsquo;&lsquo;AS IS&rsquo;&rsquo; AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.
+</pre>
+</td>
+</table>
+
+<p>All path names mentioned in the text of this document
+are relative to $SRC_HOME, unless they start with
+&rsquo;/&rsquo; or one of $SRC_HOME, $TARGET_HOME or
+$CONFIG.</p>
+<a name="3. Restoring the ACK tree"></a>
+<h2>3. Restoring the ACK tree</h2>
+
+<p>The process of installing the Amsterdam Compiler Kit is
+quite simple. The first step is to restore the Amsterdam
+Compiler Kit distribution tree structure. Proceed as
+follows</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p>Create a directory, for example
+/usr/share/local/src/ack, on a device with at least 15
+Megabytes left. This directory will be $SRC_HOME.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p>Change to that directory (cd ...).</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p>Extract all files from the distribution medium, for
+instance magtape: <b>tar x</b>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="12%"></td>
+<td width="80%">
+
+<p>Keep a copy of the original distribution to be able to
+repeat the process of installation in case of disasters.
+This copy is also useful as a reference point for
+diff-listings.</p>
+</td>
+</table>
+<a name="4. Adapting ACK to the local system"></a>
+<h2>4. Adapting ACK to the local system</h2>
+
+<p>Before compiling the sources in the Kit some
+installation dependent actions have to be taken. Most of
+these are performed by an interactive shell script in the
+file <i>$SRC_HOME/first/first.</i> Calling this script
+should be done from another directory, for instance an empty
+directory which will later become $CONFIG.</p>
+
+<p>The actions of the <i>first</i> script are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Asking for the path names of the ACK source directory
+($SRC_HOME), the configuration directory ($CONFIG), and the
+ACK users directory ($TARGET_HOME). About 5M are needed for
+the configuration tree. The disk space needed for the ACK
+users tree depends on which front-ends and back-ends are to
+be installed. For instance, on our SPARC systems we have
+installed all languages and 6 back-ends, including the
+system-independent part. This amounts to about 16M. On our
+SUN-3 systems, we have installed all front-ends and 5
+back-ends, but only the machine-dependent part. The
+machine-independent directories are symbolic links to the
+SPARC ACK users tree. We also have the fast ACK compilers
+installed on the SUN-3&rsquo;s. The total amount of
+disk-space used is less than 8M.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Asking for what type of system the binary tree must be
+produced for and creating the shell script
+&quot;ack_sys&quot; in the Kit&rsquo;s bin directory.
+Several utilities make use of &quot;ack_sys&quot; to
+determine the type of system. The current choice is
+between:</p>
+</td>
+</table>
+
+<p align=center><img src="grohtml-96855.png"></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>For some of these, the installation procedure has not
+been tested, as we don&rsquo;t have them. For others, the
+installation procedure has only been tested with earlier
+distributions, as we don&rsquo;t have those systems anymore.
+However, the sun3 and sparc systems are known to behave
+reasonably. The sparc_solaris system has only been tested
+with the GNU C compiler, because we don&rsquo;t have the SUN
+C compiler (it is unbundled in Solaris 2). The Sun systems
+should run SunOs Release 3.0 or newer. The i386 choice may
+also be used for Intel 80386 or 80486 systems running
+<small>UNIX</small> System V Release 4. These systems are
+also able to run Xenix System V binaries. If the target
+system is not on this list, choose one that comes close. If
+none of them come close, use the &quot;ANY&quot; choice. For
+ANY, any name can be used, but the Kit will not be able to
+compile programs for the target system. See the section
+about &quot;compilation on a different machine&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Setting the default machine for which code is produced
+to the local type of system according to the table above.
+This in done in the file
+&quot;$TARGET_HOME/config/local.h&quot;. See also section
+9.1.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Asking for things that don&rsquo;t have to be
+installed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Producing a shell script called &quot;INSTALL&quot; that
+will take care of the ACK installation process.</p>
+</td>
+</table>
+<a name="5. Compiling the Kit"></a>
+<h2>5. Compiling the Kit</h2>
+
+<p>The next step in the installation process is to run the
+&quot;INSTALL&quot; shell-script. When using a Bourne-shell,
+type:</p>
+<pre>     sh INSTALL &gt; INSTALL.out 2&gt;&amp;1 &amp;
+</pre>
+
+<p>When using a C-shell, type:</p>
+<pre>     sh INSTALL &gt;&amp; INSTALL.out &amp;
+</pre>
+
+<p>This shell-script performs the following steps:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Produce a configuration tree ($CONFIG), reflecting the
+structure of the source tree.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Produce Makefiles in $CONFIG. As mentioned before,
+compilations will be done in the configuration tree, not in
+the source tree. Most configuration directories will have
+Makefiles used to compile and install the programs in that
+directory. All programs needed for compilation and/or cross
+compilation with the Kit are installed in $TARGET_HOME by
+these Makefiles. These Makefiles are produced from
+corresponding files called &quot;proto.make&quot; in the
+source tree. In fact, the &quot;proto.make&quot; files are
+almost complete Makefiles, except for some macro definitions
+that are collected by the <i>first</i> script. The Makefiles
+adhere to a standard which is described in the section
+9.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Copy &quot;Action&quot; files to the configuration tree
+and editing them to reflect the choices concerning the parts
+of ACK that have to be installed. &quot;Action&quot; files
+are described below.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Copy part of the source tree to the ACK users tree
+(include files, manual pages, documentation, et cetera).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Calling the &quot;TakeAction&quot; script. All these
+Makefiles do not have to be called separately. We wrote a
+shell script calling the make&rsquo;s needed to install the
+whole Kit. This script consists of the file
+$SRC_HOME/TakeAction and a few files called Action in some
+configuration directories. The Action files describe in a
+very simple form which actions have to be performed in which
+directories. The default action is to start &quot;make
+install &amp;&amp; make clean&quot;. The output of each make
+is diverted to a file called &quot;Out&quot; in the same
+directory as the make was started in. If the make was
+successful (return code 0) the Out file is removed and the
+script TakeAction produces a small message indicating that
+it succeeded in fulfilling its goal. If the make was not
+successful (any other return code) the Out file is left
+alone for further examination and the script TakeAction
+produces a small message indicating that it failed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>For some programs the scripts already know they
+can&rsquo;t be installed on the local type of system. In
+that case they produce a message &quot;Sorry, .....&quot;
+and happily proceed with further installation commands.</p>
+</td>
+</table>
+
+<p>Installation of the Kit might take anything from a few
+hours to more than a day, depending on the speed of the
+local machine and what must be installed.</p>
+
+<p>If the installation succeeded, the Kit is ready to be
+used. Read section 6 and the manuals provided with the Kit
+(in the $TARGET_HOME/man directory) on how to use it.</p>
+<a name="5.1. Problems"></a>
+<h2>5.1. Problems</h2>
+<a name="5.1.1. on Unisoft m68000 systems."></a>
+<h2>5.1.1. on Unisoft m68000 systems.</h2>
+
+<p>The Unisoft C compiler has a bug which impedes the
+correct translation of the peephole optimizer. For a more
+detailed description of this phenomenon see the file
+&quot;$SRC_HOME/mach/m68k2/Unisoft_bug&quot;. (This
+observation was made in 1985 or so, so it is probably no
+longer true).</p>
+<a name="5.1.2. with backends"></a>
+<h2>5.1.2. with backends</h2>
+
+<p>The backends for the PDP11, VAX, Motorola 68000 and
+68020, SPARC, Intel 8086, and Intel 80386 have been heavily
+used by ourselves and are well tested. The backends for the
+other machines are known to run our own test programs, but
+might reveal errors when more heavily used.</p>
+<a name="5.2. An example output of TakeAction."></a>
+<h2>5.2. An example output of TakeAction.</h2>
+<pre>    System definition -- done
+    EM definition library -- done
+    C utilities -- done
+    Flex lexical analyzer generator -- done
+    Yacc parser generator -- done
+    system-call interface module -- done
+        .
+        .
+        .
+    EM Global optimizer -- done
+    ACK archiver -- done
+    Program &rsquo;ack&rsquo; -- done
+    Bootstrap for backend tables -- done
+    Bootstrap for newest form of backend tables -- done
+        .
+        .
+        .
+    C frontend -- done
+    ANSI-C frontend -- done
+    ANSI-C preprocessor -- done
+    ANSI-C header files -- done
+    Failed for LINT C program checker, see lang/cem/lint/Out
+    Pascal frontend -- done
+    Basic frontend -- done
+        .
+        .
+        .
+    Vax 4-4 assembler -- done
+    Vax 4-4 backend -- done
+    Vax target optimizer -- done
+    ACK a.out to VAX a.out conversion program -- done
+    Sorry, Vax code expander library can only be made on vax* systems
+    Vax 4-4 EM library -- done
+    Vax 4-4 debugger support library -- done
+    Vax 4-4 etext,edata,end library -- done
+    Vax 4-4 systemcall interface -- done
+        .
+        .
+        .
+
+</pre>
+
+<p>The lines starting with &quot;Sorry, &quot; indicate
+that certain programs cannot be translated on the local
+machine. The lines starting with &quot;Failed for&quot;
+indicate that certain programs/libraries were expected to,
+but did not compile. In this example, the installation of
+LINT failed. To repeat a certain part of the installation,
+look in the Action file, which resides in the root of the
+configuration tree, for the directory in which that part is
+to be found. If that directory contains an Action file issue
+the command &quot;sh $CONFIG/bin/TakeAction&quot;, otherwise
+type &quot;make install&quot;.</p>
+<a name="6. Commands"></a>
+<h2>6. Commands</h2>
+
+<p>The following commands are available in the
+$TARGET_HOME/bin directory after compilation of the Kit:</p>
+
+<p><i>ack</i>, <i>acc</i>, <i>abc</i>, <i>apc</i>,
+<i>ocm</i>, <i>m2</i>, <i>f2c</i> and their links</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>the names mentioned here can be used to compile Pascal,
+C, etc... programs. Most of the links can be used to
+generate code for a particular machine. See also the section
+about &quot;Machines&quot;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><i>arch</i></p>
+</td>
+<td width="20%"></td>
+<td width="72%">
+
+<p>the archiver used for the EM- and universal
+assembler/loader.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><i>aal</i></p>
+</td>
+<td width="22%"></td>
+<td width="68%">
+
+<p>the archiver used for ACK objects.</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><i>em</i></p>
+</td>
+<td width="24%"></td>
+<td width="72%">
+
+<p>this program selects a interpreter to execute an e.out
+file. Interpreters exist for PDP-11 and Motorola 68000
+systems.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><i>eminform</i></p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>the program to unravel the post-mortem information of
+the EM interpretator for the PDP-11.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><i>LLgen</i></p>
+</td>
+<td width="18%"></td>
+<td width="54%">
+
+<p>the LL(1) parser generator.</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><i>ack_sys</i></p>
+</td>
+<td width="14%"></td>
+<td width="72%">
+
+<p>a shell script producing an identification of the target
+system. Used by some utilities to determine what is, and
+what is not feasible on the target system.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><i>march</i></p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>a shell script used while compiling libraries.</p>
+</td>
+</table>
+
+<p><i>asize</i>, <i>anm</i>, <i>astrip</i></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>do the same as <i>size</i>, <i>nm</i> and <i>strip</i>,
+but for ACK object format.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><i>mkdep</i></p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>a dependency generator for makefiles.</p>
+</td>
+</table>
+
+<p><i>cid</i>, <i>prid</i>, <i>cclash</i></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>some utilities for handling name clashes in C programs.
+Some systems have C-compilers with only 7 or 8 characters
+significant in identifiers.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><i>tabgen</i></p>
+</td>
+<td width="16%"></td>
+<td width="72%">
+
+<p>a utility for generating character tables for
+C-programs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><i>int</i></p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>an EM interpreter. This one is written in C, and is very
+useful for checking out programs.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><i>grind</i></p>
+</td>
+<td width="18%"></td>
+<td width="72%">
+
+<p>a source level debugger for C, ANSI-C, Modula-2 and
+Pascal.</p>
+</td>
+</table>
+
+<p><i>afcc</i>, <i>afm2</i>, <i>afpc</i></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>these are ACK-compatible fast C, Modula-2 and Pascal
+compilers, available for M68020, VAX and Intel 80386
+systems. They compile very fast, but produce slow code.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><i>fcc</i></p>
+</td>
+<td width="22%"></td>
+<td width="72%">
+
+<p>this is a cc-compatible fast C compiler, available on
+SUN-3 and VAX systems. It compiles very fast, but produces
+slow code.</p>
+</td>
+</table>
+
+<p>We currently make the Kit available to our users by
+telling them that they should include the $TARGET_HOME/bin
+directory in their PATH shell variable. The programs will
+still work when moved to a different directory or linked to.
+Copying should preferably be done with tar, since links are
+heavily used. Renaming of the programs linked to <i>ack</i>
+will not always produce the desired result. This program
+uses its call name as an argument. Any call name not being
+<i>cc</i>, <i>acc</i>, <i>abc</i>, <i>pc</i>, <i>f2c</i>,
+<i>ocm</i>, <i>m2</i>, or <i>apc</i> will be interpreted as
+the name of a &rsquo;machine description&rsquo; and the
+program will try to find a description file with that name.
+The installation process will only touch the utilities in
+the $TARGET_HOME/bin directory, not copies of these
+utilities.</p>
+<a name="7. Machines"></a>
+<h2>7. Machines</h2>
+
+<p>Below is a table with entries for all commands in the
+bin directory used to (cross)compile for a particular
+machine. The name in the first column gives the name in the
+bin directory. The column headed dir indicates which
+subdirectories of $TARGET_HOME/lib and/or
+$TARGET_HOME/lib.bin are needed for compilation. The column
+head i/p contains the integer and pointer size used in units
+of bytes. The subdirectories with the same name in mach
+contain the sources. A * in the column headed
+&rsquo;fp&rsquo; indicates that floating point can be used
+for that particular machine. A + in that column indicates
+that floating point is available under the &rsquo;-fp&rsquo;
+option. In this case, software floating point emulation is
+used.</p>
+
+<p align=center><img src="grohtml-96856.png"></p>
+
+<p>The commands <b>em22</b>, <b>em24</b> and <b>em44</b>
+produce e.out files with EM machine code which must be
+interpreted. The Kit contains three interpreters: one
+running under PDP 11/V7 UNIX, one for the M68000, running
+under the PMDS system, Sun systems, the Mantra system, etc,
+and a portable one, written in C. The first one can only
+interpret 2/2 e.out files, the second takes 2/4 and 4/4
+files, and the last one takes 2/2, 2/4 and 4/4. The PDP 11
+interpreter executes floating point instructions.</p>
+
+<p>The program <b>$TARGET_HOME/bin/em</b> calls the
+appropriate interpreter. The interpreters are looked for in
+the em22, em24 and em44 subdirectories of
+$TARGET_HOME/lib.bin. The third interpreter is available as
+the program <b>$TARGET_HOME/bin/int</b> in the bin
+directory.</p>
+<a name="8. Compilation on a different machine."></a>
+<h2>8. Compilation on a different machine.</h2>
+
+<p>The installation mechanism of the Kit is supposed to be
+portable across <small>UNIX</small> machines, so the Kit can
+be installed and used as a cross-compiler for the languages
+it supports on any <small>UNIX</small> machine. The presence
+of most <small>UNIX</small> utilities is essential for
+compilation. A few of the programs certainly needed are: sh,
+C-compiler, sed, ed, make, and awk.</p>
+<a name="8.1. Backend"></a>
+<h2>8.1. Backend</h2>
+
+<p>The existence of a backend with a system call library
+for the target system is essential for producing executable
+files for that system. Rewriting the system call library if
+the one supplied does not work on the target system is
+fairly straightforward. If no backend exists for the target
+CPU type, a new backend has to be written which is a major
+undertaking.</p>
+<a name="8.2. Universal assembler/loader, link editor"></a>
+<h2>8.2. Universal assembler/loader, link editor</h2>
+
+<p>For most machines, the description files in
+$TARGET_HOME/lib/*/descr use our universal assembler and our
+link editor. The load file produced is not directly usable
+in any system known to us, but has to be converted before it
+can be put to use. The <i>cv</i> programs convert our a.out
+format into executable files. The <i>dl</i> programs present
+for some machines unravel our a.out files and transmit
+commands to load memory to a microprocessor over a serial
+line. The file $TARGET_HOME/man/man5/ack.out.5 contains a
+description of the format of the universal assembler load
+file. It might be useful to those who wish or need to write
+their own conversion programs. Also, a module is included to
+read and write our a.out format. See
+$TARGET_HOME/man/man3/object.3.</p>
+<a name="9. Options"></a>
+<h2>9. Options</h2>
+<a name="9.1. Default machine"></a>
+<h2>9.1. Default machine</h2>
+
+<p>There is one important option in
+$TARGET_HOME/config/local.h. The utility <i>ack</i> uses a
+default machine name when called as <i>acc</i>, <i>cc</i>,
+<i>abc</i>, <i>apc</i>, <i>pc</i>, <i>ocm</i>, <i>m2</i>,
+<i>f2c</i>, or <i>ack</i>. The machine name used by default
+is determined by the definition of ACKM in
+$TARGET_HOME/config/local.h. The Kit is distributed with
+&quot;sun3&quot; as the default machine, but the shell
+script &quot;first&quot; in the directory &quot;first&quot;
+alters this to suit the target system. There is nothing
+against using the Kit as a cross-compiler and by default
+produce code that can&rsquo;t run on the local system.</p>
+<a name="9.2. Pathnames"></a>
+<h2>9.2. Pathnames</h2>
+
+<p>Absolute path names are concentrated in
+&quot;$TARGET_HOME/config/em_path.h&quot;. Only the
+utilities <i>ack</i>, <i>flex</i>, and <i>LLgen</i> use
+absolute path names to access files in the Kit. The tree is
+distributed with /usr/em as the working directory. The
+definition of EM_DIR in em_path.h should be altered to
+specify the root directory for the Compiler Kit binaries on
+the local system ($TARGET_HOME). This is done automatically
+by the shell script &quot;first&quot; in the directory
+&quot;first&quot;. Em_path.h also specifies which directory
+should be used for temporary files. Most programs from the
+Kit do indeed use that directory although some remain
+stubborn and use /tmp.</p>
+
+<p>The shape of the tree should not be altered lightly
+because most Makefiles and the utility <i>ack</i> know the
+shape of the ACK tree. The knowledge of the utility
+<i>ack</i> about the shape of the tree is concentrated in
+the files in the directory $TARGET_HOME/lib/*/descr and
+$TARGET_HOME/lib/descr/*.</p>
+<a name="10. Makefiles"></a>
+<h2>10. Makefiles</h2>
+
+<p>Most directories contain a &quot;proto.make&quot;, from
+which a Makefile is derived. Apart from commands applying to
+that specific directory these files all recognize a few
+special commands. When called with one of these they will
+apply the command to their own directory. The special
+commands are:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>install</p>
+</td>
+<td width="26%"></td>
+<td width="60%">
+
+<p>recompile and install all binaries and libraries.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="39%"></td>
+<td width="60%">
+<p>Some Makefiles allow errors to occur in the programs they
+call. They ignore such errors and notify the user with the
+message &quot;~....... error code n: ignored&quot;. Whenever
+such a message appears in the output it can be ignored.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>cmp</p>
+</td>
+<td width="34%"></td>
+<td width="60%">
+
+<p>recompile all binaries and libraries and compare them to
+the ones already installed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>pr</p>
+</td>
+<td width="36%"></td>
+<td width="60%">
+
+<p>print the sources and documentation on the standard
+output.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>opr</p>
+</td>
+<td width="34%"></td>
+<td width="26%">
+
+<p>make pr | opr</p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="39%"></td>
+<td width="60%">
+<p>Opr should be an off-line printer daemon. On some systems
+it exists under another name e.g. lpr. The easiest way to
+call such a spooler is using a shell script with the name
+opr that calls lpr. This script should be placed in /usr/bin
+or $TARGET_HOME/bin or one of the directories in the PATH
+environment variable.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>clean</p>
+</td>
+<td width="30%"></td>
+<td width="60%">
+
+<p>remove all files not needed for day-to-day use, that is
+binaries not in $TARGET_HOME/bin or $TARGET_HOME/lib.bin,
+object files etc.</p>
+</td>
+</table>
+
+<p>Example:</p>
+<pre>     make install
+</pre>
+
+<p>given as command in a configuration directory will cause
+compilation of all programs in the directory and copying of
+the results to the $TARGET_HOME/bin and $TARGET_HOME/lib.bin
+directories.</p>
+<a name="11. Testing"></a>
+<h2>11. Testing</h2>
+
+<p>Test sets are available in Pascal, C, Basic and EM
+assembly:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>EM</p>
+</td>
+<td width="12%"></td>
+<td width="84%">
+
+<p>the directory $SRC_HOME/emtest contains a few EM test
+programs. The EM assembly files in these tests must be
+transformed into load files. These tests use the LIN and NOP
+instructions to mark the passing of each test. The NOP
+instruction prints the current line number during the test
+phase. Each test notifies its correctness by calling LIN
+with a unique number followed by a NOP which prints this
+line number. The test finishes normally with 0 as the last
+number printed In all other cases a bug showed its
+existence.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>Pascal</p>
+</td>
+<td width="4%"></td>
+<td width="84%">
+
+<p>the directory $SRC_HOME/lang/pc/test contains a few
+Pascal test programs. All these programs print the number of
+errors found and a identification of these errors.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="23%"></td>
+<td width="76%">
+<p>We also tested Pascal with the Validation Suite. The
+Validation Suite is a collection of more than 200 Pascal
+programs, designed by Brian Wichmann and Arthur Sale to test
+Pascal compilers. We are not allowed to distribute it, but a
+copy may be requested from</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<pre>     Richard J. Cichelli
+     A.N.P.A.
+     1350 Sullivan Trail
+     P.O. Box 598
+     Easton, Pennsylvania 18042
+     USA
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>C</p>
+</td>
+<td width="14%"></td>
+<td width="84%">
+
+<p>the sub-directories in $SRC_HOME/lang/cem/ctest contain
+C test programs. The idea behind these tests is: if there is
+a program called xx.c, compile it into xx.cem. Run it with
+standard output to xx.cem.r, compare this file to xx.cem.g,
+a file containing the &rsquo;ideal&rsquo; output. Any
+differences will point to implementation differences or
+bugs. Giving the command &quot;run gen&quot; or plain
+&quot;run&quot; starts this process. The differences will be
+presented on standard output. The contents of the result
+files depend on the word size, the xx.cem.g files on the
+distribution are intended for a 32-bit machine.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>Basic</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>the directory $SRC_HOME/lang/basic/test contains some
+forty Basic programs. Not all of these programs are correct,
+some have syntactic errors, some simply don&rsquo;t work.
+The Makefile in that directory attempts to compile and run
+these tests. If it compiles its output is compared to a file
+with suffix .g which contains the output to be expected. The
+make should be started with its standard input diverted to
+/dev/null. An example of the output of a make is present in
+the file Out.std.</p>
+</td>
+</table>
+<a name="12. Documentation"></a>
+<h2>12. Documentation</h2>
+
+<p>After installation, the manual pages for Amsterdam
+Compiler Kit can be found in the $TARGET_HOME/man directory.
+Also, the following documents are provided in the
+$TARGET_HOME/doc directory:</p>
+
+<p align=center><img src="grohtml-96857.png"></p>
+
+<p>Use the Makefile to get readable copies.</p>
+
+<p>Good luck.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/install.pdf b/doc/tack/install.pdf
new file mode 100644 (file)
index 0000000..618817d
Binary files /dev/null and b/doc/tack/install.pdf differ
diff --git a/doc/tack/int.html b/doc/tack/int.html
new file mode 100644 (file)
index 0000000..39552c6
--- /dev/null
@@ -0,0 +1,3910 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:37 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The EM Interpreter</title>
+</head>
+<body>
+
+<h1 align=center>The EM Interpreter</h1>
+<a href="#1. INTRODUCTION.">1. INTRODUCTION.</a><br>
+<a href="#1.1. The virtual EM machine.">1.1. The virtual EM machine.</a><br>
+<a href="#1.1.1. Instruction Space">1.1.1. Instruction Space</a><br>
+<a href="#1.1.2. The Procedure Table">1.1.2. The Procedure Table</a><br>
+<a href="#1.1.3. The Data Space">1.1.3. The Data Space</a><br>
+<a href="#1.2. Physical lay-out">1.2. Physical lay-out</a><br>
+<a href="#1.3. Speed.">1.3. Speed.</a><br>
+<a href="#2. IMPLEMENTATION DETAILS.">2. IMPLEMENTATION DETAILS.</a><br>
+<a href="#2.1. Stack manipulation and start-up">2.1. Stack manipulation and start-up</a><br>
+<a href="#2.1.1. The anomalous value of the ML register">2.1.1. The anomalous value of the ML register</a><br>
+<a href="#2.1.2. The absence of an initial Return Status Block">2.1.2. The absence of an initial Return Status Block</a><br>
+<a href="#2.2. Floating point numbers.">2.2. Floating point numbers.</a><br>
+<a href="#2.3. Pointers.">2.3. Pointers.</a><br>
+<a href="#2.3.1. Pointer arithmetic.">2.3.1. Pointer arithmetic.</a><br>
+<a href="#2.3.2. Null pointer.">2.3.2. Null pointer.</a><br>
+<a href="#2.4. Function Return Area (FRA).">2.4. Function Return Area (FRA).</a><br>
+<a href="#2.5. Environment interaction.">2.5. Environment interaction.</a><br>
+<a href="#2.5.1. Traps and interrupts.">2.5.1. Traps and interrupts.</a><br>
+<a href="#2.5.2. Monitor calls.">2.5.2. Monitor calls.</a><br>
+<a href="#2.6. Internal arithmetic.">2.6. Internal arithmetic.</a><br>
+<a href="#2.7. Shadow bytes implementation.">2.7. Shadow bytes implementation.</a><br>
+<a href="#2.8. Return Status Block (RSB)">2.8. Return Status Block (RSB)</a><br>
+<a href="#2.9. Operand access.">2.9. Operand access.</a><br>
+<a href="#2.9.1. The Dispatch Table, Method 1.">2.9.1. The Dispatch Table, Method 1.</a><br>
+<a href="#2.9.2. Intelligent Routines, Method 2.">2.9.2. Intelligent Routines, Method 2.</a><br>
+<a href="#2.9.3. Intelligent Calls, Method 3.">2.9.3. Intelligent Calls, Method 3.</a><br>
+<a href="#2.9.4. Static Evaluation.">2.9.4. Static Evaluation.</a><br>
+<a href="#2.10. Disassembly.">2.10. Disassembly.</a><br>
+<a href="#3. THE LOGGING MACHINE.">3. THE LOGGING MACHINE.</a><br>
+<a href="#3.1. Implementation.">3.1. Implementation.</a><br>
+<a href="#3.2. Controlling the Logging machine.">3.2. Controlling the Logging machine.</a><br>
+<a href="#3.3. Dumps.">3.3. Dumps.</a><br>
+<a href="#3.4. Forking.">3.4. Forking.</a><br>
+<a href="#List of Warnings.">List of Warnings.</a><br>
+<a href="#How to use the interpreter">How to use the interpreter</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Eddo de Groot<br>
+Leo van den Berge<br>
+Dick Grune</i><br>
+Faculteit Wiskunde en Informatica<br>
+Vrije Universiteit, Amsterdam</p>
+
+<p>This document describes the implementation and usage of
+a new interpreter for the EM machine language. This
+interpreter implements the full EM machine and can be
+helpful to people writing new front-ends. Moreover, it can
+be used as a thorough testing and debugging tool by anyone
+familiar with the EM language.</p>
+
+<p>A list of all warnings is given in appendix A; appendix
+B is a simple tutorial.</p>
+<a name="1. INTRODUCTION."></a>
+<h2>1. INTRODUCTION.</h2>
+
+<p>This document describes an EM interpreter which does
+extensive checking. The interpreter exists in two versions:
+the normal version with full checking and debugging
+facilities, and a fast stripped version that does
+interpretation only. This document assumes that the full
+version is used.</p>
+
+<p>First the virtual EM machine embodied by the interpreter
+(called <b>int</b>) is described, followed by some remarks
+on performance. The second section gives some specific
+implementation decisions. Section three explains the usage
+of the built-in debugging tool.</p>
+
+<p>Appendix A gives an overview of the various warnings
+<b>int</b> gives, with possible causes and solutions.
+Appendix B is a simple tutorial on the use of <b>int</b>. A
+separate manual page exists.</p>
+
+<p>The document assumes a good understanding of what EM is
+and what the assembly code looks like [1]. Notions like
+&rsquo;procedure descriptor&rsquo;, &rsquo;mini&rsquo;,
+&rsquo;shortie&rsquo; etc. are not explained. In the sequel,
+any word in <i>this font</i> refers to the name of a
+variable, constant, function or whatever, used in the source
+code under the same name.</p>
+
+<p>To avoid confusion: <b>int</b> interprets EM machine
+language (e.out files), <i>not</i> the assembly language (.e
+files) and <i>not</i> the compact code (.k files).</p>
+<a name="1.1. The virtual EM machine."></a>
+<h2>1.1. The virtual EM machine.</h2>
+
+<p>The memory layout of the virtual EM machine represented
+by the interpreter differs in details from the description
+in [1]. Virtual memory is split up into two separate spaces:
+one space containing the instructions, the other all the
+data, including stack and heap (D-space). The procedure
+descriptors are preprocessed and stored in a separate array,
+<i>proctab[]</i>. Both spaces start off at address 0. This
+is possible because pointers in the two different spaces are
+distinguishable by context (and shadow-bytes: see 2.6).</p>
+<a name="1.1.1. Instruction Space"></a>
+<h2>1.1.1. Instruction Space</h2>
+
+<p>Figure 1 shows the I-space, together with the position
+of some important EM registers.</p>
+<pre>                      NEXT --&gt;  |________________|  &lt;-- DB    \
+                                |                |            |
+                                |                |            |  T
+                                |                |  &lt;-- PC    |
+                                |     Program    |            |  e
+                                |                |            |
+                                |      Text      |            |  x
+                                |                |            |
+                                |                |            |  t
+                         0 --&gt;  |________________|  &lt;--(PB)   /
+
+</pre>
+
+<p align=center><i>Fig 1. Virtual instruction space
+(I-space).</i></p>
+
+<p>The I-space is just big enough to contain all the
+instructions. The size needed for the program text
+(<i>NTEXT</i>) is found from the header-bytes of the
+loadfile. Legal values for the program counter (<i>PC</i>)
+consist of all addresses in the range from 0 through
+<i>NTEXT</i> &minus; 1. If the <i>PC</i> is made to point to
+an illegal address, a trap will occur.</p>
+<a name="1.1.2. The Procedure Table"></a>
+<h2>1.1.2. The Procedure Table</h2>
+
+<p>The <i>NProc</i> constant indicates how many procedure
+descriptors there are in the proctab array. Elements of this
+array contain for each procedure: the number of locals, the
+entry point and the entry point of the textually following
+procedure. This is used in testing the restriction that the
+program counter may not wander from procedure to
+procedure.</p>
+<a name="1.1.3. The Data Space"></a>
+<h2>1.1.3. The Data Space</h2>
+
+<p>Figure 2 shows the layout of the data space, which
+closely conforms to the EM Manual.</p>
+<pre>                                __________________
+            maxaddr(psize) --&gt;  |                |  &lt;-- ML    \
+                                |                |            |  S
+                                |     Locals     |            |  t
+                                |       &amp;        |            |  a
+                                |      RSBs      |            |  c
+                                |                |            |  k
+                                |________________|  &lt;-- SP    /
+                                .                .
+                                .                .
+                                .     Unused     .
+                                .                .
+                                .                .
+                                .                .
+                                .                .
+                                .                .
+                                .     Unused     .
+                                .                .
+                                .                .
+                                |________________|  &lt;-- HP
+                                |                |            \
+                                |      Heap      |            |
+                                |________________|  &lt;-- HB    |
+                                |                |            |  D
+                                |    Arguments   |            |
+                                |     Environ    |            |  a
+                                |  _   _   _   _ |            |
+                                |                |            |  t
+                                |                |            |
+                                |                |            |  a
+                                |   Global data  |            |
+                                |                |            |
+                                |                |            |
+                         0 --&gt;  |________________|  &lt;--(EB)   /
+
+</pre>
+
+<p align=center><i>Fig 2. Virtual dataspace
+(D-space).</i></p>
+
+<p>D-space begins at address 0, and ends at the largest
+address representable by the pointer size (<i>psize</i>)
+being used; for a 2-byte pointer size this maximum address
+is</p>
+<pre>     ((2 ^ 16 &minus; 1) / word size * word size) &minus; 1
+</pre>
+
+<p>for a 4-byte pointer size it is</p>
+<pre>     ((2 ^ 31 &minus; 1) / word size * word size) &minus; 1
+</pre>
+
+<p>(not 2 ^ 32, to allow illegal pointers to be implemented
+in the future). The funny rounding construction is required
+to make ML+1 expressible as the initialisation value of LB
+and SP.</p>
+
+<p>D-space is split into two partitions: Data and Stack
+(indicated by the brackets). The Data partition holds the
+global data area (GDA) and the heap. Its initial size is
+given by the loadfile constant SZDATA. Some space is added
+to it, because arguments and environment are stored here
+also. This total size is static while interpreting. However,
+as the heap may grow during execution (e.g. caused by
+dynamic allocation) this results in a variable size for the
+Data partition. Initially, the size for the Data partition
+is the sum of the space needed by the GDA (including the
+space needed for arguments and environment) and the initial
+heapspace. The lowest legal Data address is 0; the highest
+<i>HP</i> &minus; 1.</p>
+
+<p>The Stack partition holds the stack. It begins at the
+highest available D-space address, and grows towards the low
+addresses, so the Stack partition is of variable size too.
+The lowest legal Stack address is the stackpointer
+(<i>SP</i>), the highest is the memory limit
+(<i>ML</i>).</p>
+<a name="1.2. Physical lay-out"></a>
+<h2>1.2. Physical lay-out</h2>
+
+<p>Each partition is mapped onto a piece of physical memory
+with the same name: <i>text</i> (fig. 1), <i>stack</i> and
+<i>data</i> (fig. 2). These are the storage structures which
+<b>int</b> uses to physically store the contents of the
+virtual EM spaces. Figure 2 thus shows the mapping of
+D-space onto two different physical parts: <i>stack</i> and
+<i>data</i>. The I-space is represented by one physical
+part: <i>text</i>.</p>
+
+<p>Each time more space is needed, the actual partition is
+reallocated, with the new size being computed with the
+formula:</p>
+<pre><i>     new size</i> = 1.5 &times; (<i>old size</i> + <i>extra</i>)
+</pre>
+
+<p><i>extra</i> is the number of bytes exceeding the <i>old
+size</i>. One can prove that using this method, there is a
+linear relationship between allocation time and needed
+partition size.</p>
+
+<p>A virtual D-space starting at address 0 is in
+correspondence with the definition in [1], p. 3&minus;6. The
+main reason for having D-space start at address 0, is that
+it induces a one-one correspondence between the heap &minus;
+and GDA addresses on the virtual machine (and hence the
+definition) on one hand, and the offset within the
+<i>data</i> partition on the other. This implies that no
+extra calculation is needed to perform load and storage
+operations.</p>
+
+<p>Some calculation however cannot be avoided, because the
+stack part of the D-space grows downwards by EM definition.
+The first address of the virtual stack (<i>ML</i>, the
+maximum address for the given <i>psize</i>) is mapped onto
+the beginning of the <i>stack</i> partition. When the stack
+grows (i.e. EM addresses get lower), the offset within the
+<i>stack</i> partition gets higher. By taking offset <i>ML
+&minus; A</i> in the stack partition, one obtains the
+physical address corresponding to some virtual EM (stack)
+address <i>A</i>.</p>
+<a name="1.3. Speed."></a>
+<h2>1.3. Speed.</h2>
+
+<p>From several test results with both versions of the
+interpreter, the following may be concluded. The speed of
+the interpreter depends strongly on the type of program
+being interpreted. If plain CPU arithmetic is performed, the
+interpreter is relatively slow (1000 &times; the cc
+version). When stack manipulation is at hand, the
+interpreter is quite fast (100 &times; the cc version).</p>
+
+<p>Most programs however will not be this extreme, so an
+interpretation time of somewhere between 300 and 500 times
+direct execution for a normal program is to be expected.</p>
+
+<p>The fast version runs in about 60% of the time of the
+full version, at the expense of a considerably lower
+functionality. Tallying costs about 10%.</p>
+<a name="2. IMPLEMENTATION DETAILS."></a>
+<h2>2. IMPLEMENTATION DETAILS.</h2>
+
+<p>The pertinent issues are addressed below, in arbitrary
+order.</p>
+<a name="2.1. Stack manipulation and start-up"></a>
+<h2>2.1. Stack manipulation and start-up</h2>
+
+<p>It is not at all easy to start the EM machine with the
+stack in a reasonable and consistent state. One reason is
+the anomalous value of the ML register and another is the
+absence of a proper RSB. It may be argued that the initial
+stack does not have to be in a consistent state, since the
+first instruction proper is only executed after <i>argc</i>,
+<i>argv</i> and <i>environ</i> have been stacked (which
+takes care of the empty stack) and the initial procedure has
+been called (which creates a RSB). We would, however, like
+to preform the stacking of these values and the calling of
+the initial procedure using the normal stack and call
+routines, which again require the stack to be in an
+acceptable state.</p>
+<a name="2.1.1. The anomalous value of the ML register"></a>
+<h2>2.1.1. The anomalous value of the ML register</h2>
+
+<p>All registers in the EM machine point to word
+boundaries, and all of them, except ML, address the
+even-numbered byte at the boundary. The exception has a good
+reason: the even numbered byte at the ML boundary does not
+exist. This problem is not particular to EM but is inherent
+in the number system: the number of N-digit numbers can
+itself not be expressed in an N-digit number, and the number
+of addresses in an N-bit machine will itself not fit in an
+N-bit address. The problem is solved in the interpreter by
+having ML point to the highest word boundary that has bytes
+on either side; this makes ML+1 expressible.</p>
+<a name="2.1.2. The absence of an initial Return Status Block"></a>
+<h2>2.1.2. The absence of an initial Return Status Block</h2>
+
+<p>When the stack is empty, there is no legal value for AB,
+since there are no actuals; LB can be set naturally to ML+1.
+This is all right when the interpreter starts with a call of
+the initial routine which stores the value of LB in the
+first RSB, but causes problems when finally this call
+returns. We want this call to return completely before
+stopping the interpreter, to check the integrity of the last
+RSB; restoring information from it will, however, cause
+illegal values to be stored in LB and AB (ML+1 and
+ML+1+rsbsize, resp.). On top of this, the initial (illegal)
+Procedure Identifier of the running procedure will be
+restored; then, upon restoring the likewise illegal PC will
+cause a check to see if it still is inside the running
+procedure. After a few attempts at writing special cases, we
+have decided that it is possible, but not worth the effort;
+the final (= initial) RSB will not be unstacked.</p>
+<a name="2.2. Floating point numbers."></a>
+<h2>2.2. Floating point numbers.</h2>
+
+<p>The interpreter is capable of working with 4- and 8-byte
+floating point (FP) numbers. In C-terms, this corresponds to
+objects of type float and double respectively. Both types
+fit in a C-double so the obvious way to manipulate these
+entities internally is in doubles. Pushing a 8-byte FP, all
+bytes of the C-double are pushed. Pushing a 4-byte FP causes
+the 4 bytes representing the smallest fraction to be
+discarded.</p>
+
+<p>In EM, floats can be obtained in two different ways: via
+conversion of another type, or via initialization in the
+loadfile. Initialized floats are represented in the loadfile
+by an ASCII string in the syntax of a Pascal real (signed
+UnsignedReal). I.e. a float looks like:</p>
+<pre>     [ <i>Sign</i> ] <i>Digit</i>+ [ . <i>Digit</i>+ ] [ <i>Exp</i> [ <i>Sign</i> ] <i>Digit</i>+ ]                                (G1)
+</pre>
+
+<p>followed by a null byte. Here <i>Sign</i> = {+,
+&minus;}; <i>Digit</i> = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+<i>Exp</i> = {e, E}; [ <i>Anything</i> ] means that
+<i>Anything</i> is optional; and a + means one or more
+times. To accommodate some loose code generators, the actual
+grammar accepted is:</p>
+<pre>     [ <i>Sign</i> ] <i>Digit</i>&lowast; [ . <i>Digit</i>&lowast; ] [ <i>Exp</i> [ <i>Sign</i> ] <i>Digit</i>+ ]                                (G2)
+</pre>
+
+<p>followed by a null byte. Here &lowast; means zero or
+more times. A floating denotation which is in G2 but not in
+G1 draws a warning, one that is not even in G2 causes a
+fatal error.</p>
+
+<p>A string, representing a float which does not fit in a
+double causes a warning to be given. In that case, the
+returned value will be the double 0.0.</p>
+
+<p>Floating point arithmetic is handled by some simple
+routines, checking for over/underflow, and returning
+appropriate values in case of an ignored error.</p>
+
+<p>Since not all C compilers provide floating point
+operations, there is a compile time flag NOFLOAT, which, if
+defined, suppresses the use of all fp operations in the
+interpreter. The resulting interpreter will still load EM
+files with floats in the global data area (and ignore them)
+but will give a fatal error upon attempt to execute a
+floating point instruction; consequently code involving
+floating point operations can be run as long as the actual
+instructions are avoided.</p>
+<a name="2.3. Pointers."></a>
+<h2>2.3. Pointers.</h2>
+
+<p>The following sub-sections both deal with problems
+concerning pointers. First, something is said about pointer
+arithmetic in general. Then, the null-pointer problem is
+dealt with.</p>
+<a name="2.3.1. Pointer arithmetic."></a>
+<h2>2.3.1. Pointer arithmetic.</h2>
+
+<p>Strictly speaking, pointer arithmetic is defined only
+within a <b>fragment</b>. From the explanation of the term
+fragment however (as given in [1], page 3), it is not quite
+clear what a fragment should look like from an
+interpreter&rsquo;s point of view. For this reason we
+introduced the term <b>segment</b>, bordering the various
+areas within which pointer arithmetic is allowed. Every
+stack-frame is a segment, and so are the global data area
+(GDA) and the heap area. Thus, the number of segments varies
+over time, and at some point in time is given by the number
+of currently active stack-frames (#CAL + #CAI &minus; #RET
+&minus; #RTT) plus 2 (gda, heap). Pointers in the area
+between heap and stack (which is inaccessible by
+definition), are assumed to be in the heap segment.</p>
+
+<p>The interpreter, while building a new stack-frame (i.e.
+segment), stores the value of the last ActualBase in a
+pointer-array (<i>AB_list[ ]</i>). When a pointer (say
+<i>P</i>) is available for arithmetic, the number of the
+segment where it points (say <i>S <small>P</small></i> ), is
+determined first. Next, the arithmetic is performed,
+followed by a check on the number of the segment where the
+resulting pointer <i>R</i> points (say <i>S
+<small>R</small></i> ). Now, if <i>S <small>P</small> != S
+<small>R</small></i> , a warning is given: <b>Pointer
+arithmetic yields pointer to bad segment</b>.<br>
+It may also be clear now, why the illegal area between heap
+and stack was joined with the heap segment. When calculating
+a new heap pointer (<i>HP</i>), one will obtain intermediate
+results being pointers in this area just before it is made
+legal. We do not want error messages all of the time, just
+because someone is allocating space in the heap.</p>
+
+<p>A similar treatment is given to the pointers in the SBS
+instruction; they have to point into the same fragment for
+subtraction to be meaningful.</p>
+
+<p>The length of the <i>AB_list[ ]</i> is initially 100,
+and it is reallocated in the same way the dynamically
+growing partitions are (see 1.1).</p>
+<a name="2.3.2. Null pointer."></a>
+<h2>2.3.2. Null pointer.</h2>
+
+<p>Because the EM language lacks an instruction for loading
+a null pointer, most programs solve this problem by loading
+a pointer-sized integer of value zero, and using this as a
+null pointer (this is also proposed in [1]). <b>Int</b>
+allows this, and will not complain. A warning is given
+however, when an attempt is made to add something to a null
+pointer (i.e. the pointer-sized integer zero).</p>
+
+<p>Since many programming languages use a pointer to
+location 0 as an illegal value, it is desirable to detect
+its use. The big problem is though that 0 is a perfectly
+legal EM address; address 0 holds the current line number in
+the source file. It may be freely read but is written only
+by means of the LIN instruction. This allows us to declare
+the area consisting of the line number and the file name
+pointer to be read-only memory. Thus a store will be caught
+(and result in a warning) but a read will succeed (and yield
+the EM information stored there).</p>
+<a name="2.4. Function Return Area (FRA)."></a>
+<h2>2.4. Function Return Area (FRA).</h2>
+
+<p>The Function Return Area (<i>FRA[ ]</i>) has a default
+size of 8 bytes; this default can be overridden through the
+use of the <b>&minus;r</b>-option, but cannot be made
+smaller than the size of two pointers, in accordance with
+the remark on page 5 of [1]. The global variable
+<i>FRASize</i> keeps track of how many bytes were stored in
+the FRA, the last time a RET instruction was executed. The
+LFR instruction only works when its argument is equal to
+this size. If not, the FRA contents are loaded anyhow, but
+one of the following warnings is given: <b>Returned function
+result too large</b> (<i>FRASize</i> &gt; LFR size) or
+<b>Returned function result too small</b> (<i>FRASize</i>
+&lt; LFR size).</p>
+
+<p>Note that a C-program, falling through the end of its
+code without doing a proper <i>return</i> or <i>exit()</i>,
+will generate this warning.</p>
+
+<p>The only instructions that do not disturb the contents
+of the FRA are GTO, BRA, ASP and RET. This is expressed in
+the program by setting <i>FRA_def</i> to
+&quot;undefined&quot; in any instruction except these four.
+We realize this is a useless action most of the time, but a
+more efficient solution does not seem to be at hand. If a
+result is loaded when <i>FRA_def</i> is
+&quot;undefined&quot;, the warning: <b>Returned function
+result may be garbled</b> is generated.</p>
+
+<p>Note that the FRA needs a shadow-FRA in order to store
+the shadow information when performing a LFR
+instruction.</p>
+<a name="2.5. Environment interaction."></a>
+<h2>2.5. Environment interaction.</h2>
+
+<p>The EM machine represented by <b>int</b> can communicate
+with the environment in three different ways. A first
+possibility is by means of (UNIX) interrupts; the second by
+executing (relatively) high level system calls (called
+monitor calls). A third means of interaction, especially
+interesting for the debugging programmer, is via internal
+variables set on the command line. The former two
+techniques, and the way they are implemented will be
+described in this section. The latter has been allotted a
+separate section (3).</p>
+<a name="2.5.1. Traps and interrupts."></a>
+<h2>2.5.1. Traps and interrupts.</h2>
+
+<p>Simple user programs will generally not mess around with
+UNIX-signals. In interpreting these programs, the default
+actions will be taken when a signal is received by the
+program: it gives a message and stops running.</p>
+
+<p>There are programs however, which try to handle certain
+signals themselves. In C, this is achieved by the system
+call <i>signal( sig_no, catch )</i>, which calls the
+handling routine <i>catch()</i>, as soon as signal
+<b>sig_no</b> occurs. EM does not provide this call;
+instead, the <i>sigtrp()</i> monitor call is available for
+mapping UNIX signals onto EM traps. This implies that a
+<i>signal()</i> call in a C-program must be translated by
+the EM library routine to a <i>sigtrp()</i> call in EM.</p>
+
+<p>The interpreter keeps an administration of the mapping
+of UNIX-signals onto EM traps in the array
+<i>sig_map[NSIG]</i>. Initially, the signals all have their
+default values. Now assume a <i>sigtrp()</i> occurs, telling
+to map signal <b>sig_no</b> onto trap <b>trap_no</b>. This
+results in:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>setting the relevant array element
+<i>sig_map[sig_no]</i> to <b>trap_no</b> (after saving the
+old value),</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>catching the next to come <b>sig_no</b> signal with the
+handling routine <i>HndlEMSig</i> (by a plain UNIX
+<i>signal()</i> of course), and</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>returning the saved map-value on the stack so the user
+can know the previous trap value onto which <b>sig_no</b>
+was mapped.</p>
+</td>
+</table>
+
+<p>On an incoming signal, the handling routine for signal
+<b>sig_no</b> arms the correct EM trap by calling the
+routine <i>arm_trap()</i> with argument
+<i>sig_map[sig_no]</i>. At the end of the EM instruction the
+proper call of <i>trap()</i> is done. <i>Trap()</i> on its
+turn examines the value of the <i>HaltOnTrap</i> variable;
+if it is set, the interpreter will stop with a message. In
+the normal case of controlled trap handling this bit is not
+on and the interpreter examines the value of the
+<i>TrapPI</i> variable, which contains the procedure
+identifier of the EM trap handling routine. It then
+initiates a call to this routine and performs a
+<i>longjmp()</i> to the main loop to bypass all further
+processing of the instruction that caused the trap.
+<i>TrapPI</i> should be set properly by the library
+routines, through the SIG instruction.</p>
+
+<p>In short:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>A UNIX interrupt is caught by the interpreter.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>A handling routine is called which generates the
+corresponding EM trap (according to the mapping).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>The trap handler calls the corresponding EM routine
+which emulates a UNIX interrupt for the benefit of the
+interpreted program.</p>
+</td>
+</table>
+
+<p>When considering UNIX signals, it is important to notice
+that some of them are real signals, i.e., messages coming
+from outside the program, like DEL and QUIT, but some are
+actually program-caused synchronous traps, like Illegal
+Instruction. The latter, if they happen, are incurred by the
+interpreter itself and consequently are of no concern to the
+interpreted program: it cannot catch them. The present code
+assumes that the UNIX signals between SIGILL (4) and SIGSYS
+(12) are really traps; <i>do_sigtrp()</i> will fail on
+them.</p>
+
+<p>To avoid losing the last line(s) of output files, the
+interpreter should always do a proper close-down, even in
+the presence of signals. To this end, all non-ignored
+genuine signals are initially caught by the interpreter,
+through the routine <i>HndlIntSig</i>, which gives a message
+and preforms a proper close-down. Synchronous trap can only
+be caused by the interpreter itself; they are never caught,
+and consequently the UNIX default action prevails. Generally
+they cause a core dump. Signals requested by the interpreted
+program are caught by the routine <i>HndlEMSig</i>, as
+explained above.</p>
+<a name="2.5.2. Monitor calls."></a>
+<h2>2.5.2. Monitor calls.</h2>
+
+<p>For the convenience of the programmer, as many monitor
+calls as possible have been implemented. The list of monitor
+calls given in [1] pages 20/21, has been implemented
+completely, except for <i>ptrace()</i>, <i>profil()</i> and
+<i>mpxcall()</i>. The semantics of <i>ptrace()</i> and
+<i>profil()</i> from an interpreted program is unclear; the
+data structure passed to <i>mpxcall()</i> is non-trivial and
+the system call has low portability and applicability. For
+these calls, on invocation a warning is generated, and the
+arguments which were meant for the call are popped properly,
+so the program can continue without the stack being messed
+up. The errorcode 5 (IOERROR) is pushed onto the stack
+(twice), in order to fake an unsuccessful monitor call. No
+other &minus; more meaningful &minus; errorcode is available
+in the errno-list.</p>
+
+<p>Now for the implemented monitor calls. The returned
+value is zero for a successful call. When something goes
+wrong, the value of the external <i>errno</i> variable is
+pushed, thus enabling the user to find out what the reason
+of failure was. The implementation of the majority of the
+monitor calls is straightforward. Those working with a
+special format buffer, (e.g. <i>ioctl()</i>, <i>time()</i>
+and <i>stat()</i> variants), need some extra attention. This
+is due to the fact that working with varying word/pointer
+size combinations may cause alignment problems.</p>
+
+<p>The data structure returned by the UNIX system call
+results from C code that has been translated with the
+regular C compiler, which, on the VAX, happens to be a 4-4
+compiler. The data structure expected by the interpreted
+program conforms to the translation by <b>ack</b> of the
+pertinent include file. Depending on the exact call of
+<b>ack</b>, sizes and alignment may differ.</p>
+
+<p>An example is in order. The EM MON 18 instruction in the
+interpreted program leads to a UNIX <i>stat()</i> system
+call by the interpreter. This call fills the given struct
+with stat information, the contents and alignments of which
+are determined by the version of UNIX and the used C
+compiler, resp. The interpreter, like any program wishing to
+do system calls that fill structs, has to be translated by a
+C compiler that uses the appropriate struct definition and
+alignments, so that it can use, e.g., <i>stab.st_mtime</i>
+and expect to obtain the right field. This struct cannot be
+copied directly to the EM memory to fulfill the MON
+instruction. First, the struct may contain extraneous,
+system-dependent fields, pertaining, e.g., to symbolic
+links, sockets, etc. Second, it may contain holes, due to
+alignment requirements. The EM program runs on an EM
+machine, knows nothing about these requirements and expects
+UNIX Version 7 fields, with offsets as determined by the
+em22, em24 or em44 compiler, resp. To do the conversion, the
+interpreter has a built-in table of the offsets of all the
+fields in the structs that are filled by the MON
+instruction. The appropriate fields from the result of the
+UNIX <i>stat()</i> are copied one by one to the appropriate
+positions in the EM memory to be filled by MON 18.</p>
+
+<p>The <i>ioctl()</i> call (MON 54) poses additional
+problems. Not only does it have a second argument which is a
+pointer to a struct, the type of which is dynamically
+determined, but its first argument is an opcode that varies
+considerably between the versions of UNIX. To solve the
+first problem, the interpreter examines the opcode (request)
+and treats the second argument accordingly. The second
+problem can be solved by translating the UNIX Version 7
+<i>ioctl()</i> request codes to their proper values on the
+various systems. This is, however, not always useful, since
+some EM run-time systems use the local request codes. There
+is a compile-time flag, V7IOCTL, which, if defined, will
+restrict the <i>ioctl()</i> call to the version 7 request
+codes and emulate them on the local system; otherwise the
+request codes of the local system will be used (as far as
+implemented).</p>
+
+<p>Minor problems also showed up with the implementation of
+<i>execve()</i> and <i>fork()</i>. <i>Execve()</i> expects
+three pointers on the stack. The first points to the name of
+the program to be executed, the second and third are the
+beginnings of the <b>argv</b> and <b>envp</b> pointer arrays
+respectively. We cannot pass these pointers to the system
+call however, because the EM addresses to which they point
+do not correspond with UNIX addresses. Moreover, (it is not
+very likely to happen but) what if someone constructs a
+program holding the contents for one of these pointers in
+the stack? The stack is implemented upside down, so passing
+the pointer to <i>execve()</i> causes trouble for this
+reason too. The only solution was to copy the pointer
+contents completely to fresh UNIX memory, constructing
+vectors which can be passed to the system call. Any
+impending memory fault while making these copies results in
+failure of the system call, with <i>errno</i> set to
+EFAULT.</p>
+
+<p>The implementation of the <i>fork()</i> call faced us
+with problems concerning IO-channels. Checking messages (as
+well as logging) must be divided over different files.
+Otherwise, these messages will coincide. This problem was
+solved by post-fixing the default message file
+<b>int.mess</b> (as well as the logging file <b>int.log</b>)
+with an automatically leveled number for every new forked
+process. Children of the original process do their
+diagnostics in files with postfix 1,2,3 etc. Second
+generation processes are assigned files numbered 11, 12, 21
+etc. When 6 generations of processes exist at one moment,
+the seventh will get the same message file as the sixth, for
+the length of the filename will become too long.</p>
+
+<p>Some of the monitor calls receive pointers (addresses)
+from to program, to be passed to the kernel; examples are
+the struct stat for <i>stat()</i>, the area to be filled for
+<i>read()</i>, etc. If the address is wrong, the kernel does
+not generate a trap, but rather the system call returns with
+failure, while <i>errno</i> is set to EFAULT. This is
+implemented by consistent checking of all pointers in the
+MON instruction.</p>
+<a name="2.6. Internal arithmetic."></a>
+<h2>2.6. Internal arithmetic.</h2>
+
+<p>Doing arithmetic on signed integers, the smallest
+negative integer (<i>minsint</i>) is considered a legal
+value. This is in contradiction with the EM Manual [1], page
+14, which proposes using <i>minsint</i> for uninitialized
+integers. The shadow bytes already check for uninitialized
+integers however, so we do not need this special illegal
+value. Although the EM Manual provides two traps, for
+undefined integers and floats, undefined objects occur so
+frequently (e.g. in block copying partially initialized
+areas) that the interpreter just gives a warning.</p>
+
+<p>Except for arithmetic on unsigneds, all arithmetic
+checks for overflow. The value that is pushed on the stack
+after an overflow occurs depends on the UNIX behavior with
+regard to that particular calculation. If UNIX would not
+accept the calculation (e.g. division by zero), a zero is
+pushed as a convention. Illegal computations which UNIX does
+accept in silence (e.g. one&rsquo;s complement of
+<i>minsint</i>), simply push the UNIX-result after giving a
+trap message.</p>
+<a name="2.7. Shadow bytes implementation."></a>
+<h2>2.7. Shadow bytes implementation.</h2>
+
+<p>A great deal of run-time checking is performed by the
+interpreter (except if used in the fast version). This
+section gives all details about the shadow bytes. In order
+to keep track of information about the contents of D-space
+(stack and global data area), there is one shadow-byte for
+each byte in these spaces. Each bit in a shadow-byte
+represents some piece of information about the contents of
+its corresponding &rsquo;sun-byte&rsquo;. All bits off
+indicates an undefined sun-byte. One or more bits on always
+guarantees a well-defined sun-byte. The bits have the
+following meaning:</p>
+
+<p>&bull; bit 0:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>indicates that the sun-byte is (a part of) an
+integer.</p>
+</td>
+</table>
+
+<p>&bull; bit 1:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>the sun-byte is a part of a floating point number.</p>
+</td>
+</table>
+
+<p>&bull; bit 2:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>the sun-byte is a part of a pointer in dataspace.</p>
+</td>
+</table>
+
+<p>&bull; bit 3:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>the sun-byte is a part of a pointer in the instruction
+space. According to [1] (paragraph 6.4), there are two types
+pointers which must be distinguishable. Conversion between
+these two types is impossible. The shadow-bytes make the
+distinction here.</p>
+</td>
+</table>
+
+<p>&bull; bit 4:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>protection bit. Indicates that the sun-byte is part of a
+protected piece of memory. There is a protected area in the
+stack, the Return Status Block. The EM machine language has
+no possibility to declare protected memory, as is possible
+in EM assembly (the ROM instruction). The protection bit is,
+however, set for the line number and filename pointer area
+near location 0, to aid in catching references to location
+0.</p>
+</td>
+</table>
+
+<p>&bull; bit 5/6/7:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>free for later use.</p>
+</td>
+</table>
+
+<p>The shadow bytes are managed by the routines declared in
+<i>shadow.h</i>. The warnings originating from checking
+these shadow-bytes during run-time are various. A list of
+them is given in appendix A, together with suggestions
+(primarily for the C-programmer) where to look for the
+trouble maker(s).</p>
+
+<p>A point to notice is, that once a warning is generated,
+it may be repeated thousands of times. Since repetitive
+warnings carry little information, but consume much file
+space, the interpreter keeps track of the number of times a
+given warning has been produced from a given line in a given
+file. The warning message will be printed only if the
+corresponding counter is a power of four (starting at 1). In
+this way, a logarithmic back-off in warning generation is
+established.</p>
+
+<p>It might be argued that the counter should be kept for
+each (warning, PC value) pair rather than for each (warning,
+file position) pair. Suppose, however, that two instruction
+in a given line would cause the same message regularly; this
+would produce two intertwined streams of identical messages,
+with their counters jumping up and down. This does not seem
+desirable.</p>
+<a name="2.8. Return Status Block (RSB)"></a>
+<h2>2.8. Return Status Block (RSB)</h2>
+
+<p>According to the description in [1], at least the return
+address and the base address of the previous RSB have to be
+pushed when performing a call. Besides these two pointers,
+other information can be stored in the RSB also. The
+interpreter pushes the following items:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p>a pointer to the current filename,</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p>the current line number (always four bytes),</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="30%">
+
+<p>the Local Base,</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="74%">
+
+<p>the return address (Program Counter),</p>
+</td>
+<td width="15%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="64%">
+
+<p>the current procedure identifier</p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the RSB code, which distinguishes between initial
+start-up, normal call, returnable trap and non-returnable
+trap (a word-size integer).</p>
+</td>
+</table>
+
+<p>Consequently, the size of the RSB varies, depending on
+word size and pointer size; its value is available as
+<i>rsbsize</i>. When the RSB is removed from the stack (by a
+RET or RTT) the RSB code is under the Stack Pointer for
+immediate checking. It is not clear what should be done if
+RSB code and return instruction do not match; at present we
+give a message and continue, for what it is worth.</p>
+
+<p>The reason for pushing filename and line number is that
+some front-ends tend to forget the LIN and FIL instructions
+after returning from a function. This may result in error
+messages in wrong source files and/or line numbers.</p>
+
+<p>The procedure identifier is kept and restored to check
+that the PC will not move out of the running procedure. The
+PI is an index in the proctab, which tells the limits in the
+text segment of the running procedure.</p>
+
+<p>If the Return Status Block is generated as a result of a
+trap, more is stacked. Before stacking the normal RSB, the
+trap function pushes the following items:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the contents of the entire Function Return Area,</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the number of bytes significant in the above (a
+word-size integer),</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>a word-size flag indicating if the contents of the FRA
+are valid,</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="76%">
+
+<p>the trap number (a word-size integer).</p>
+</td>
+<td width="13%">
+</td>
+</table>
+
+<p>The latter is followed directly by the RSB, and
+consequently acts as the only parameter to the trap
+handler.</p>
+<a name="2.9. Operand access."></a>
+<h2>2.9. Operand access.</h2>
+
+<p>The EM Manual mentions two ways to access the operands
+of an instruction. It should be noticed that the operand in
+EM is often not the direct operand of the operation; the
+operand of the ADI instruction, e.g., is the width of the
+integers to be added, not one of the integers themselves.
+The various operand types are described in [1]. Each opcode
+in the text segment identifies an instruction with a
+particular operand type; these relations are described in
+computer-readable format in a file in the EM tree,
+<i>ip_spec.t</i>.</p>
+
+<p>The interpreter uses the third method. Several other
+approaches can be designed, with increasing efficiency and
+equally increasing complexity. They are briefly treated
+below.</p>
+<a name="2.9.1. The Dispatch Table, Method 1."></a>
+<h2>2.9.1. The Dispatch Table, Method 1.</h2>
+
+<p>When the interpreter starts, it reads the ip_spec.t file
+and constructs from it a dispatch table. This table (of
+which there are actually three, for primary, secondary and
+tertiary opcodes) has 256 entries, each describing an
+instruction with indications on how to decode the operand.
+For each instruction executed, the interpreter finds the
+entry in the dispatch table, finds information there on how
+to access the operand, constructs the operand and calls the
+appropriate routine with the operand as calculated. There is
+one routine for each instruction, which is called with the
+ready-made operand. Method 1 is easy to program but requires
+constant interpretation of the dispatch table.</p>
+<a name="2.9.2. Intelligent Routines, Method 2."></a>
+<h2>2.9.2. Intelligent Routines, Method 2.</h2>
+
+<p>For each opcode there is a separate routine, and since
+an opcode uniquely defines the instruction and the operand
+format, the routine knows how to get the operand; this
+knowledge is built into the routine. Preferably the heading
+of the routine is generated automatically from the ip_spec.t
+file. Operand decoding is immediate, and no dispatch table
+is needed. Generation of the 469 required routines is,
+however, far from simple. Either a generated array of
+routine names or a generated switch statement is used to map
+the opcode onto the correct routine. The switch approach has
+the advantage that parameters can be passed to the
+routines.</p>
+<a name="2.9.3. Intelligent Calls, Method 3."></a>
+<h2>2.9.3. Intelligent Calls, Method 3.</h2>
+
+<p>The call in the switch statement does full operand
+construction, and the resulting operand is passed to the
+routine. This reduces the number of routines to 133, the
+number of EM instructions. Generation of the switch
+statement from ip_spec.t is more complicated, but the
+routine space is much cleaner. This does not give any
+speed-up since the same actions are still required; they are
+just performed in a different place.</p>
+<a name="2.9.4. Static Evaluation."></a>
+<h2>2.9.4. Static Evaluation.</h2>
+
+<p>It can be observed that the evaluation of the operand of
+a given instruction in the text segment will always give the
+same result. It is therefore possible to preprocess the text
+segment, decomposing the instructions into structs which
+contain the address, the instruction code and the operand.
+No operand decoding will be necessary at run-time: all
+operands have been precalculated. This will probably give a
+considerable speed-up. Jumps, especially GTO jumps, will,
+however, require more attention.</p>
+<a name="2.10. Disassembly."></a>
+<h2>2.10. Disassembly.</h2>
+
+<p>A disassembly facility is available, which gives a
+readable but not letter-perfect disassembly of the EM
+object. The procedure structure is indicated by placing the
+indication <b>P[n]</b> at the entry point of each procedure,
+where <b>n</b> is the procedure identifier. The number of
+locals is given in a comment.</p>
+
+<p>The disassembler was generated by the software in the
+directory <i>switch</i> and then further processed by
+hand.</p>
+<a name="3. THE LOGGING MACHINE."></a>
+<h2>3. THE LOGGING MACHINE.</h2>
+
+<p>Since messages and warnings provided by <b>int</b>
+include source code file names and line numbers, they alone
+often suffice to identify the error. If, however, the
+necessity arises, much more extensive debugging information
+can be obtained by activating the the Logging Machine. This
+Logging Machine, which monitors all actions of the EM
+machine, is the subject of this chapter.</p>
+<a name="3.1. Implementation."></a>
+<h2>3.1. Implementation.</h2>
+
+<p>When inspecting the source code of <b>int</b>, many
+lines in the following format will show up:</p>
+<pre>     LOG((&quot;@&lt;<i>letter</i>&gt;&lt;<i>digit</i>&gt; message&quot;, args));
+</pre>
+
+<p>or</p>
+<pre>     LOG((&quot; &lt;<i>letter</i>&gt;&lt;<i>digit</i>&gt; message&quot;, args));
+</pre>
+
+<p>The double parentheses are needed, because <i>LOG()</i>
+is declared as a define, and has a printf-like argument
+structure.</p>
+
+<p>The &lt;<i>letter</i>&gt; classifies the log message and
+corresponds to an entry in the <i>logmask</i>, which holds a
+threshold for each class of messages. The following classes
+exist:</p>
+
+<p align=center><img src="grohtml-107771.png"></p>
+
+<p>When the interpreter reaches a LOG(()) statement it
+scans its first argument; if <i>letter</i> occurs in the
+logmask, and if <i>digit</i> is lower or equal to the
+threshold in the logmask, the message is given. Depending on
+the first character, the message will be preceded by a
+position indication (with the @) or will be printed as is
+(with the space). The <i>letter</i> is determines the
+message class and the <i>digit</i> is used to distinguish
+various levels of logging, with a lower digit indicating a
+more important message. We will call the
+&lt;<i>letter</i>&gt;&lt;<i>digit</i>&gt; combination the
+<b>id</b> of the logging.</p>
+
+<p>In general, the lower the <i>digit</i> following the
+<i>letter</i>, the more important the message. E.g. m5
+reports about unsuccessful monitor calls only, m9 also
+reports about successful monitors (which are obviously less
+interesting). New logging messages can be added to the
+source code on relevant places.</p>
+
+<p>Reasonable settings for the logmask are:</p>
+
+<p align=center><img src="grohtml-107772.png"></p>
+
+<p>An EM interpreter without a Logging Machine can be
+obtained by undefining the macro <i>CHECKING</i> in the file
+<i>checking.h</i>.</p>
+<a name="3.2. Controlling the Logging machine."></a>
+<h2>3.2. Controlling the Logging machine.</h2>
+
+<p>The actions of the Logging Machine are controlled by a
+set of internal variables (one of which is the log mask).
+These variables can be set through assignments on the
+command line, as explained int the manual page <i>int.1</i>,
+q.v. Since there are a great many logging statements in the
+program, of which only a few will be executed in any call of
+the interpreter, it is important to be able to decide
+quickly if a given <i>id</i> has to be checked at all. To
+this end all logging statements are guarded (in the #define)
+by a test for the boolean variable <i>logging</i>. This
+variable will only be set if the command line assignments
+show the potential need for logging (<i>must_log</i>) and
+the instruction count (<i>inr</i>) is at least equal to
+<i>log_start</i> (which derives from the parameter
+<b>LOG</b>).</p>
+
+<p>The log mask can be set by the assignment</p>
+<pre>     &quot;LOGMASK=<i>logstring</i>&quot;
+</pre>
+
+<p>which sets the current logmask to <i>logstring</i>. A
+logstring has the following form:</p>
+<pre>     [ [ <i>letter</i> | <i>letter</i> &minus; <i>letter</i> ]+ <i>digit</i> ]+
+</pre>
+
+<p>E.g. LOGMASK=A&minus;D8x9R7c0hi4 will print all messages
+belonging to loggings with <b>id</b>s:
+<i>A0..A8,B0..B8,C0..C8,D0..D8,x0..x9,R0..R7,c0,h0..h4,i0..i4</i>.</p>
+
+<p>The logging variable STOP can be used to prevent
+run-away logging past the point where the user expects an
+error to occur. STOP=<i>nr</i> will stop the interpreter
+after instruction number <i>nr</i>.</p>
+
+<p>To simplify the use of the logging machine, a number of
+abbreviations have been defined. E.g., AT=<i>nr</i> can be
+thought of as an abbreviation of LOG=<i>nr&minus;1</i>
+STOP=<i>nr+1</i>; this causes three stack dumps, one before
+the suspect instruction, one on it and one after it; then
+the interpreter stops.</p>
+
+<p>Logging results will appear in a special logging file
+(default: <i>int.log</i>).</p>
+<a name="3.3. Dumps."></a>
+<h2>3.3. Dumps.</h2>
+
+<p>There are three routines available to examine the memory
+contents:</p>
+
+<p align=center><img src="grohtml-107773.png"></p>
+
+<p>These routines can be used everywhere in the program to
+examine the contents of memory. The internal variables allow
+the gda and heap to be dumped only once (according to the
+corresponding internal variable). The stack is dumped after
+each instruction if the log mask contains d1 or d2; d2 gives
+a full formatted dump, d1 produces a listing of the Return
+Status Blocks only. An attempt is made to format the stack
+correctly, based on the shadow bytes, which identify the
+Return Status Block.</p>
+
+<p>Remember to set the correct <b>id</b> in the LOGMASK,
+and to give LOG the correct value. If dumping is needed
+before the first instruction, then LOG must be set to 0.</p>
+
+<p>The dumps of the global data area and the heap are
+controlled internally by the id-s +1 and *1 resp.; the
+corresponding logmask entries are set automatically by
+setting the GDA and HEAP variables.</p>
+<a name="3.4. Forking."></a>
+<h2>3.4. Forking.</h2>
+
+<p>As mentioned earlier, a call to <i>fork()</i>, causes an
+image of the current program to start running. To prevent a
+messy logfile, the child process gets its own logfile (and
+message file, tally file, etc.). These logfiles are
+distinguished from the parent logfile by the a postfix,
+e.g., <i>logfile_1</i> for the first child, <i>logfile_2</i>
+for the second child, <i>logfile_1_2</i> for the second
+child of the first child, etc.<i><br>
+Note</i>: the implementation of this feature is shaky; it
+works for the log file but should also work for other files
+and for the names of the logging variables.</p>
+
+<p align=center>APPENDIX A</p>
+<a name="List of Warnings."></a>
+<h2>List of Warnings.</h2>
+
+<p>The shadow-byte administration makes it possible to
+check for a wide range of errors during run-time. We have
+tried to make the diagnostics self-explanatory and
+especially useful for the C-programmer. The warnings are
+printed in the message file, together with source file and
+line number. The complete list of warnings is presented
+here, followed by an explanation of what might be wrong.
+Often, these explanations implicitly assume that the program
+being interpreted, was originally written in C (and not
+Pascal, Basic etc.).</p>
+
+<p><i>Reading the load file</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="10%"></td>
+<td width="86%">
+
+<p><b>Floating point instructions flag in header
+ignored</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="10%"></td>
+<td width="78%">
+
+<p><b>No float initialisation in this version</b></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The interpreter was compiled with the NOFLOAT option;
+code involving floating point operations can be run as long
+as the actual instructions are avoided.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="10%"></td>
+<td width="66%">
+
+<p><b>Extra-test flag in header ignored</b></p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The interpreter already tests anything conceivable.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="10%"></td>
+<td width="70%">
+
+<p><b>Maximum line number in header was 0</b></p>
+</td>
+<td width="15%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>This number could be used to allocate tables for
+tallying; these tables are, however, expanded as needed, so
+the number is immaterial.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7.</p>
+</td>
+<td width="10%"></td>
+<td width="48%">
+
+<p><b>Bad float initialisation</b></p>
+</td>
+<td width="37%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The loadfile contains a floating point denotation which
+does not satisfy the syntax (see 2.6). Examining the
+loadfile (with <b>od &minus;c</b>) might show the syntax
+error. Probably there is a bug in the front-end, creating
+floats with a bad syntax.</p>
+</td>
+</table>
+
+<p><i>System calls</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>11.</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p><b>IOCTL &minus; bad or unimplemented request</b></p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The second parameter to the ioctl() request (the
+operation code) is invalid or not implemented; since there
+are many different opcodes on the various UNIX systems, it
+is difficult to tell which. The system call fails.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>14.</p>
+</td>
+<td width="8%"></td>
+<td width="62%">
+
+<p><b>MPXCALL &minus; not (yet) implemented</b></p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>15.</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><b>PROFIL &minus; not (yet) implemented</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>16.</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><b>PTRACE &minus; not (yet) implemented</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The monitor calls <i>mpxcall()</i>, <i>profil()</i> and
+<i>ptrace()</i> have not been implemented. The monitor call
+fails.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>21.</p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p><b>Inaccessible memory in system call</b></p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>Bad pointers passed to system calls do not cause a memory
+fault (which in UNIX would happen to the kernel), but cause
+the system call to fail with the UNIX variable errno set to
+14 (EFAULT). It seems likely that the program is at fault,
+but there is also a good possibility that a library routine
+made unwarranted assumptions about word size and pointer
+size.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>23.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>READ &minus; buffer resides in unallocated
+memory</b></p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>24.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>READ &minus; buffer across global data area and
+heap</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>When the buffer passed to the read() system call is
+situated (completely or partially) in unallocated memory
+(beyond <i>HP</i>) or begins in the global data area and
+ends in the heap, the appropriate warning is given. The
+buffer is not written.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>25.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>WRITE &minus; buffer resides in unallocated
+memory</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>26.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>WRITE &minus; buffer across global data area and
+heap</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>27.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>WRITE &minus; (part of) global buffer is
+undefined</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>28.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>WRITE &minus; (part of) local buffer is
+undefined</b></p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The first two are equivalent to the READ-errors above.
+Writing out a buffer usually makes no sense when the
+contents are undefined, so one of the latter two warnings
+will be generated in this case. A global buffer resides in
+the data partition; a local buffer resides in the stack
+partition. This corresponds to global and local variables in
+a C-program. In the first two cases the WRITE is not
+performed, in the latter two cases it is.</p>
+</td>
+</table>
+
+<p><i>Traps and signals</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>31.</p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p><b>SIGTRP &minus; bad signo argument</b></p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The <i>sigtrp()</i> monitor call allows <i>sig_no</i>
+arguments in the range [1..17] (UNIX Version 7 signals); the
+actual argument is out of range.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>32.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>SIGTRP &minus; signo argument is a synchronous
+trap</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The signal is one that can only be caused synchronously
+by the running program on UNIX; it cannot occur to an
+interpreted program.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>33.</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p><b>SIGTRP &minus; bad trapno argument</b></p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The <i>sigtrp()</i> monitor call allows <i>trap_no</i>
+arguments between 0 and 252, and the special values &minus;2
+and &minus;3; the actual argument is not one of these.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>36.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Heap overflow due to command line limitation</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>37.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Stack overflow due to command line limitation</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The maximum sizes of the heap and the stack can be
+limited by options on the command line. If overflow occurs
+due to such limitations, the corresponding trap is taken,
+preceded by one of the above warnings. If the memory of the
+interpreter itself is exhausted, a fatal error follows.</p>
+</td>
+</table>
+
+<p><i>Run-time type checking</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>41.</p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p><b>Local character expected</b></p>
+</td>
+<td width="37%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>42.</p>
+</td>
+<td width="8%"></td>
+<td width="50%">
+
+<p><b>Global character expected</b></p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>43.</p>
+</td>
+<td width="8%"></td>
+<td width="44%">
+
+<p><b>Local integer expected</b></p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>44.</p>
+</td>
+<td width="8%"></td>
+<td width="46%">
+
+<p><b>Global integer expected</b></p>
+</td>
+<td width="39%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>45.</p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p><b>Local float expected</b></p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>46.</p>
+</td>
+<td width="8%"></td>
+<td width="42%">
+
+<p><b>Global float expected</b></p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>47.</p>
+</td>
+<td width="8%"></td>
+<td width="54%">
+
+<p><b>Local data pointer expected</b></p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>48.</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p><b>Global data pointer expected</b></p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>49.</p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p><b>Local instruction pointer expected</b></p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>50.</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p><b>Global instruction pointer expected</b></p>
+</td>
+<td width="15%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>In general, a type violation has taken place when one of
+these warnings is given. The <b>float</b>- and
+<b>instruction pointer</b> warnings are rare and will
+usually be easy traceable. <b>Integer/character expected</b>
+will normally occur when unsigned arithmetic is performed on
+datapointers or when memory containing objects other than
+integers is copied bytewise. Often, this warning is followed
+by a warning <b>datapointer expected</b>. This is due to our
+decision of transforming pointers to (unsigned) integers
+after doing unsigned arithmetic on them. When such a
+transformed integer is dereferenced (as if it were a
+pointer) or, in general, when it is treated as a pointer,
+this results in a warning. The present library
+implementation of malloc() causes such a sequence of
+errors.</p>
+</td>
+</table>
+
+<p>These messages are always followed by a tentative
+description of what is found in memory at the offending
+place.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>61.</p>
+</td>
+<td width="8%"></td>
+<td width="52%">
+
+<p><b>Actual memory is undefined</b></p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>62.</p>
+</td>
+<td width="8%"></td>
+<td width="66%">
+
+<p><b>Actual memory contains an integer</b></p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>63.</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><b>Actual memory contains a float</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>64.</p>
+</td>
+<td width="8%"></td>
+<td width="74%">
+
+<p><b>Actual memory contains a data pointer</b></p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>65.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Actual memory contains an instruction pointer</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>66.</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><b>Actual memory contains mixed information</b></p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>If the contents of the area was undefined, check the
+source code for an uninitialized variable of the mentioned
+type. Officially, the use of an undefined value should
+result in a EIUND or EFUND trap but the occurrence is so
+common that a warning is more appropriate. The contents of
+memory are described as mixed if the data consists of pieces
+of different types. This happens, e.g., when caller and
+callee do not agree on the types and lengths of the
+parameters.</p>
+</td>
+</table>
+
+<p><i>Protection</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>71.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Destroying contents of ROM (at or near loc 0)</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The program stores a value in Read-Only Memory; the only
+ROM in the present implementation is the area near location
+0. The warning probably results from storing under a NULL
+pointer. This is only a warning, the store operation is
+executed normally. Reads from location 0 are not
+detected.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>72.</p>
+</td>
+<td width="8%"></td>
+<td width="84%">
+
+<p><b>Destroying contents of Return Status Block</b></p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The Return Status Block is the stack area containing the
+return address, the dynamic link, etc. This may or may not
+be an error. The current implementation of
+<i>setjmp()</i>/<i>longjmp()</i> may be responsible for it.
+If the program does not use setjmp(), there <i>is</i>
+something very wrong (e.g. argument for ASP too large). Note
+that there are some library routines (such as
+<i>alarm()</i>) which use <i>setjmp()</i>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>81.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Logical operation using undefined operand(s)</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>82.</p>
+</td>
+<td width="8%"></td>
+<td width="60%">
+
+<p><b>Comparing undefined operand(s)</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The logical operations AND, XOR, IOR, COM and the compare
+operation CMS do their jobs bytewise. If one of the bytes is
+found to be undefined, the corresponding warning is given,
+and the operation is stopped immediately. The stack is
+adjusted so interpretation may continue.<br>
+It is hard to say what went wrong. Possibly, the argument of
+the instruction at hand (which indicates the size of the
+objects to be compared), was too large.</p>
+</td>
+</table>
+
+<p><i>Bad operands</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>91.</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p><b>Shift over negative distance</b></p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>92.</p>
+</td>
+<td width="8%"></td>
+<td width="58%">
+
+<p><b>Shift over too large distance</b></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>Shift instructions yield undefined results if the shift
+distance is negative or larger than the object size.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>93.</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><b>Pointer arithmetic yields pointer to bad
+segment</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>When doing pointer arithmetic (ADP, ADS), the operand and
+result pointer must be in the same <i>segment</i> (see sec.
+4). E.g. loading the address of the first local and adding
+20 to it will certainly give this warning.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>94.</p>
+</td>
+<td width="8%"></td>
+<td width="84%">
+
+<p><b>Subtracting pointers to different segments</b></p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>Pointers may be subtracted only if they point into the
+same segment.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>96.</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p><b>Pointer arithmetic with NULL pointer</b></p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>By definition it is illegal to do arithmetic with null
+pointers. Integers with the size of a pointer and the value
+zero are recognized as NULL pointers. A well-known C-trick
+to compute the offset of some field in a struct is
+converting the null-pointer to the type of the struct and
+simply taking the address of the field. This trick will
+&minus;when translated and interpreted&minus; generate this
+warning because it results in arithmetic with the NULL
+pointer.</p>
+</td>
+</table>
+
+<p><i>Return area</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>101.</p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><b>Returned function result too large</b></p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>102.</p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><b>Returned function result too small</b></p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>This warning is generated when the size of the expected
+return value is not equal to the size actually returned.<br>
+An interpreted program may have fallen through the end of
+the code without explicitly doing an <i>exit()</i> or
+<i>return()</i>. The start-up routine (<i>crt0()</i>)
+however always expects to get some value returned by the
+program proper.<br>
+Another (less probable) possibility of course is that the
+code contains a subroutine or function call that does not
+return properly (e.g. it returns a short instead of a
+long).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>103.</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p><b>Returned function result may be garbled</b></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>This warning will be generated, when the contents of the
+FRA are fetched after some instruction is executed which can
+mess up the area. Compiler-generated loadfiles should not
+generate this message.</p>
+</td>
+</table>
+
+<p><i>Return Status Block</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>111.</p>
+</td>
+<td width="6%"></td>
+<td width="76%">
+
+<p><b>RET did not find a Return Status Block</b></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>112.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Used RET to return from a trap</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The RET instruction found a garbled Return Status Block,
+or on that resulted from a trap.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>115.</p>
+</td>
+<td width="6%"></td>
+<td width="76%">
+
+<p><b>RTT did not find a Return Status Block</b></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>116.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p><b>RTT on empty stack</b></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>117.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Used RTT to return from a call</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>118.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Used RTT to return from a non-returnable trap</b></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>The RTT (Return from Trap) instruction found a Return
+Status block that was not created properly by a trap.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>121.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Stack Pointer too large in RET</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>122.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Stack Pointer too small in RET</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>125.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Stack Pointer too large in RTT</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>126.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Stack Pointer too small in RTT</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<p>According to the EM Manual (4.2), &quot;the value of SP
+just after the return value has been popped must be the same
+as the value of SP just before executing the first
+instruction of the invocation.&quot; If the Stack Pointer is
+too large, some dynamically allocated item or some temporary
+result may have been left behind on the stack. If the Stack
+Pointer is too small, some locals have been unstacked. Since
+the interpreter has enough information in the Return Status
+Block, it recovers correctly from these errors.</p>
+</td>
+</table>
+
+<p><i>Traps</i></p>
+
+<p>Some traps have ambiguous or non-obvious causes. As far
+as possible, these are preceded by a warning, explaining the
+circumstances of the trap.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>131.</p>
+</td>
+<td width="6%"></td>
+<td width="52%">
+
+<p><b>Trap ESTACK: DCH on bad LB</b></p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>132.</p>
+</td>
+<td width="6%"></td>
+<td width="52%">
+
+<p><b>Trap ESTACK: LPB on bad LB</b></p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>133.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap ESTACK: SP retracted over Return Status
+Block</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>134.</p>
+</td>
+<td width="6%"></td>
+<td width="72%">
+
+<p><b>Trap ESTACK: SP moved into data area</b></p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>135.</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><b>Trap ESTACK: SP set to non-word-boundary</b></p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>136.</p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p><b>Trap ESTACK: LB set out of stack</b></p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>137.</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><b>Trap ESTACK: LB set to non-word-boundary</b></p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>138.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap ESTACK: LB set to position where there is no
+RSB</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>141.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EHEAP: HP retracted into Global Data
+Area</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>142.</p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p><b>Trap EHEAP: HP pushed into stack</b></p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>143.</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p><b>Trap EHEAP: HP set to non-word-boundary</b></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>151.</p>
+</td>
+<td width="6%"></td>
+<td width="56%">
+
+<p><b>Trap EILLINS: unknown opcode</b></p>
+</td>
+<td width="29%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>152.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: conversion with unacceptable size for
+this machine</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>153.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: FIL with non-existing address</b></p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>154.</p>
+</td>
+<td width="6%"></td>
+<td width="74%">
+
+<p><b>Trap EILLINS: LFR with too large size</b></p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>155.</p>
+</td>
+<td width="6%"></td>
+<td width="74%">
+
+<p><b>Trap EILLINS: RET with too large size</b></p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>156.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: instruction argument of class c does
+not fit a word</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>157.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: instruction on double word on machine
+with word size 4</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>158.</p>
+</td>
+<td width="6%"></td>
+<td width="72%">
+
+<p><b>Trap EILLINS: local offset too large</b></p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>159.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: instruction argument of class g not in
+GDA</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>160.</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p><b>Trap EILLINS: fragment offset too large</b></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>161.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: counter in lexical instruction out of
+range</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>162.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EILLINS: non-existent procedure
+identifier</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>163.</p>
+</td>
+<td width="6%"></td>
+<td width="74%">
+
+<p><b>Trap EILLINS: illegal register number</b></p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>172.</p>
+</td>
+<td width="6%"></td>
+<td width="74%">
+
+<p><b>Trap EBADPC: jump out of text segment</b></p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>173.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EBADPC: jump out of procedure fragment</b></p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>181.</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><b>Trap EBADGTO: GTO does not restore an existing
+RSB</b></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>182.</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p><b>Trap EBADGTO: GTO descriptor on the stack</b></p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>191.</p>
+</td>
+<td width="6%"></td>
+<td width="60%">
+
+<p><b>Trap caused by TRP instruction</b></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="13%"></td>
+<td width="86%">
+<pre>     APPENDIX B
+</pre>
+</td>
+</table>
+<a name="How to use the interpreter"></a>
+<h2>How to use the interpreter</h2>
+
+<p>The interpreter is not normally used for the debugging
+of programs under construction. Its primary application is
+as a verification tool for almost completed programs.
+Although the proper operation of the interpreter is
+obviously a black art, this chapter tries to provide some
+guidelines.</p>
+
+<p>For the sake of the argument, the source language is
+assumed to be C, but most hints apply equally well to other
+languages supported by ACK.</p>
+
+<p><i>Initial measures</i></p>
+
+<p>Start with a test case of trivial size; to be on the
+safe side, reckon with a time dilatation factor of about
+500, i.e., a second grows into 10 minutes. (The interpreter
+takes 0.5 msec to do one EM instruction on a Sun 3/50).
+Fortunately many trivial test cases are much shorter than
+one second.</p>
+
+<p>Compile the program into an <i>e.out</i>, the EM machine
+version of a <i>a.out</i>, by calling <i>em22</i> (for
+2-byte integers and 2-byte pointers), <i>em24</i> (for 2 and
+4) or <i>em44</i> (for 4 and 4) as seems appropriate; if in
+doubt, use <i>em44</i>. These compilers can be found in the
+ACK <i>bin</i> directory, and should be used instead of
+<i>acc</i> (or normal <small>UNIX</small> &reg; <i>cc</i>).
+Alternatively, <i>acc &minus;memNN</i> can be used instead
+of <i>emNN</i>.</p>
+
+<p>If a C program consists of more than one file, as it
+usually does, there is a small problem. The <i>acc</i> and
+<i>cc</i> compilers generate .o files, whereas the
+<i>emNN</i> compilers generate .m files as object files. A
+simple technique to avoid the problem is to call</p>
+<pre>     em44 *.c
+</pre>
+
+<p>if possible. If not, the following hack on the
+<i>Makefile</i> generally works.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Make sure the <i>Makefile</i> is reasonably clean and
+complete: all calls to the compiler are through
+<i>$(CC)</i>, <i>CFLAGS</i> is used properly and all
+dependencies are specified.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Add the following lines to the <i>Makefile</i> (possibly
+permanently):</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>.SUFFIXES:</p>
+<td width="19%"></td>
+<td width="10%">
+
+<p>.o</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>.c.o:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>$(CC) &minus;c $(CFLAGS) $&lt;</p>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Set CC to <i>em44 &minus;.c</i> (for example). Make sure
+CFLAGS includes the &minus;O option; this yields a speed-up
+of about 15 %.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Change all .o to .m (or .k if the &minus;O option is not
+used).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>If necessary, change <i>a.out</i> to <i>e.out</i>.</p>
+</td>
+<td width="17%">
+</td>
+</table>
+
+<p>With these changes, <i>make</i> will produce an EM
+object; <i>esize</i> can be used to verify that it is indeed
+an EM object and obtain some statistics. Then call the
+interpreter:</p>
+<pre>     int &lt;EM-object-file&gt; [ parameters ]
+</pre>
+
+<p>where the parameters are the normal parameters of the
+program. This should work exactly like the original program,
+though slower. It reads from the terminal if the original
+does, it opens and closes files like the original and it
+accepts interrupts.</p>
+
+<p><i>Interpreting the results</i></p>
+
+<p>Now there are several possibilities.</p>
+
+<p>It does all this. Great! This means the program does not
+do very uncouth things. Now read the file <i>int.mess</i> to
+see if any messages were generated. If there are none, the
+program did not really run (perhaps the original cc
+<i>a.out</i> got called instead?) Normally there is at least
+a termination message like</p>
+<pre>     (Message): program exits with status 0 at &quot;awa.p&quot;, line 64, INR = 4124
+</pre>
+
+<p>This says that the program terminated through an exit(0)
+on line 64 of the file <i>awa.p</i> after 4124 EM
+instructions. If this is the only message it is time to move
+to a bigger test case.</p>
+
+<p>On the other hand, the program may come to a grinding
+halt with an error message. All messages (errors and
+warnings) have a format in which the sequence</p>
+<pre>     &quot;&lt;file name&gt;&quot;, line &lt;ln#&gt;
+</pre>
+
+<p>occurs, which is the same sequence many compilers
+produce for their error messages. Consequently, the
+<i>int.mess</i> file can be processed as any compiler
+message output.</p>
+
+<p>One such message can be</p>
+<pre>     (Fatal error) a.em: trap &quot;Addressing non existent memory&quot; not caught at &quot;a.c&quot;, line 2, INR = 16
+</pre>
+
+<p>produced by the abysmal program</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>main()</p>
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>{</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>*(int*)200000 = 1;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>}</p>
+
+<p>Often the effects are more subtle, however. The
+program</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>main()</p>
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>{</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>int *a, b = 777;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>b = *a;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>}</p>
+
+<p>produces the following five warnings (in far less than a
+second):</p>
+<pre>     (Warning 47, #1): Local data pointer expected at &quot;t.c&quot;, line 4, INR = 17
+     (Warning 61, cont.): Actual memory is undefined at &quot;t.c&quot;, line 4, INR = 17
+     (Warning 102, #1): Returned function result too small at &quot;&lt;unknown&gt;&quot;, line 0, INR = 21
+     (Warning 43, #1): Local integer expected at &quot;exit.c&quot;, line 11, INR = 34
+     (Warning 61, cont.): Actual memory is undefined at &quot;exit.c&quot;, line 11, INR = 34
+</pre>
+
+<p>The one about the function result looks the most
+frightening, but is the most easily solved: <i>main</i> is a
+function returning an int, so the start-up routine expects a
+(four-byte) integer but gets an empty (zero-byte) return
+area.</p>
+
+<p><i>Note</i>: The experts are divided about this. The
+traditional school holds that <i>main</i> is an int function
+and its result is the return code; this leaves them with two
+ways of supplying a return code: one as the parameter of
+<i>exit()</i> and one as the result of <i>main</i>. The
+modern school (Berkeley 4.2 etc.) claims that return codes
+are supplied exclusively by <i>exit()</i>, and they have an
+<i>exit(0)</i> in the start-up routine, just after the call
+to <i>main()</i>; leaving <i>main()</i> through the bottom
+implies successful termination.</p>
+
+<p>We shall satisfy both groups by</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>main()</p>
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p>{</p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>int *a, b = 777;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>b = *a;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>exit(0);</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>}</p>
+
+<p>This results in</p>
+<pre>     (Warning 47, #1): Local data pointer expected at &quot;t.c&quot;, line 4, INR = 17
+     (Warning 61, cont.): Actual memory is undefined at &quot;t.c&quot;, line 4, INR = 17
+     (Message): program exits with status 0 at &quot;exit.c&quot;, line 11, INR = 33
+</pre>
+
+<p>which is pretty clear as it stands.</p>
+
+<p><i>Using stack dumps</i></p>
+
+<p>Let&rsquo;s, for the sake of argument and to avoid the
+fierce realism of 10000-line programs, assume that the above
+still does not give enough information. Since the error
+occurred in EM instruction number 17, we should like to see
+more information around that moment. Call the interpreter
+again, now with the shell variable AT set at 17:</p>
+<pre>     int AT=17 t.em
+</pre>
+
+<p>(The interpreter has a number of internal variables that
+can be set by assignments on the command line, like with
+<i>make</i>.) This gives a file called <i>int.log</i>
+containing the stack dump of 150 lines presented at the end
+of this chapter.</p>
+
+<p>Since dumping is a subfacility of logging in the
+interpreter, the formats of the lines are the same. If a
+line starts with an @, it will contain a
+file-name/line-number indication; the next two characters
+are the subject and the log level. Then comes the
+information, preceded by a space. The text contains three
+stack dumps, one before the offending instruction, one at
+it, and one after it; then the interpreter stops. All kinds
+of other dumps can be obtained, but this is default.</p>
+
+<p>For each instruction we have, in order:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>an @x9 line, giving the position in the program,</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>the messages, warnings and errors from the instruction
+as it is being executed,</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="44%">
+
+<p>dump(s), as requested.</p>
+</td>
+<td width="45%">
+</td>
+</table>
+
+<p>The first two lines mean that at line 4 in file
+<i>t.c</i> the interpreter performed its 16-th instruction,
+with the Program Counter at 30 pointing at opcode 180 in the
+text segment; the instruction was an LOL (LOad Local) with
+the operand &minus;4 derived from the opcode. It copies the
+local at offset &minus;4 to the top of the stack. The effect
+can be seen from the subsequent stack dump, where the
+undefined word at addresses 2147483568 to ...571 (the
+variable <i>a</i>) has been copied to the top of the stack
+at 2147483560 (copying undefined values does not generate a
+warning). Since we used the <i>em44</i> compiler, all
+pointers and ints in our dump are 4 bytes long. So a
+variable at address X in reality extends from address X to
+X+3.<br>
+Note that this is not the offending instruction; this stack
+dump represents the situation just before the error.</p>
+
+<p>The stack consists of a sequence of frames, each
+containing data followed by a Return Status Block resulting
+from a call; the last frame ends in top-of-stack. The first
+frame represents the stack when the program starts, through
+a call to the start-up routine. This routine prepares the
+second stack frame with the actual parameters to
+<i>main()</i>: <i>argc</i> at 2147483596, <i>argv</i> at
+2147483600 and <i>environ</i> at 2147483604.</p>
+
+<p>The RSB line shows that the call to <i>main()</i> was
+made from procedure 0 which has 0 locals, with PC at 16, an
+LB of 2147483608 and file name and line number still
+unknown. The <i>code</i> in the RSB tells how this RSB was
+made; possible values are STP (start-up), CAL, RTT
+(returnable trap) and NRT (non-returnable trap).</p>
+
+<p>The next frame shows the local variable(s) of
+<i>main()</i>; there are two of them, the pointer <i>a</i>
+at 2147483568, which is undefined, and variable <i>b</i> at
+2147483564, which has the value 777. Then comes a copy of
+<i>a</i>, just made by the LOL instruction, at 2147483560.
+The following line shows that the Function Return Area
+(which does not reside at the end of the stack, but just
+happens to be printed here) has size 0 and is presently
+undefined. The stack dump ends by showing that the Actuals
+Base is at 2147483596 (pointing at <i>argc</i>), the Locals
+Base at 2147483572 (pointing just above the local <i>a</i>),
+the Stack Pointer at 2147483560 (pointing at the undefined
+pointer), the line count is 4 and the file name is
+&quot;t.c&quot;.</p>
+
+<p>(Notice that there is one more stack frame than one
+would probably expect, the one above the start-up
+routine.)</p>
+
+<p>The Function Return Area could have a size larger than 0
+and still be undefined, for example when an instruction that
+does not preserve the contents of the FRA has just been
+executed; likewise the FRA could have size 0 and be defined
+nevertheless, for example just after a RET 0
+instruction.</p>
+
+<p>All this has set the scene for the distaster which is
+about to strike in the next instruction. This is indeed a
+LOI (LOad Indirect) of size 4, opcode 169; it causes the
+message</p>
+<pre>     warning: Local data pointer expected [stack.c: 242]
+</pre>
+
+<p>and its continuation</p>
+<pre>     warning cont.: Actual memory is undefined
+</pre>
+
+<p>(detected in the interpreter file <i>stack.c</i> at line
+242; this can be useful for sorting out dubious semantics).
+We see that the effect, as shown in the third frame of this
+stack dump (at instruction number 17) is somewhat
+unexpected: the LOI has fetched the value 4 and stacked it.
+The reason is that, unfortunately, undefinedness is not
+transitive in the interpreter. When an undefined value is
+used in an operation (other than copying) a warning is
+given, but thereafter the value is treated as if it were
+zero. So, after the warning a normal null pointer remains,
+which is then used to pick up the value at location 0. This
+is the place where the EM machine stores its current line
+number, which is presently 4.</p>
+
+<p>The third stack dump shows the final effect: the value 4
+has been unstacked and copied to variable <i>b</i> at
+2147483564 through an STL (STore Local) instruction.</p>
+
+<p>Since this form of logging dumps the stack only, the log
+file is relatively small as dumps go. Nevertheless, a useful
+excerpt can be obtained with the command</p>
+<pre>     grep &rsquo;d1&rsquo; int.log
+</pre>
+
+<p>This extracts the Return Status Block lines from the
+log, thus producing three traces of calls, one for each
+instruction in the log:</p>
+<pre>      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483560, HP = 848, LIN = 4, FIL = &quot;t.c&quot;
+      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483560, HP = 848, LIN = 4, FIL = &quot;t.c&quot;
+      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483564, HP = 848, LIN = 4, FIL = &quot;t.c&quot;
+</pre>
+
+<p>Theoretically, the pertinent trace is the middle one,
+but in practice all three are equal. In the present case
+there isn&rsquo;t much to trace, but in real programs the
+trace can be useful.</p>
+
+<p><i>Errors in libraries</i></p>
+
+<p>Since libraries are generally compiled with suppression
+of line number and file name information, the line number
+and file name in the interpreter will not be updated when it
+enters a library routine. Consequently, all messages
+generated by interpreting library routines will seem to
+originate from the line of the call. This is especially true
+for the routine malloc(), which, from the nature of its
+business, often contains dubitable code.</p>
+
+<p>A usual message is:</p>
+<pre>     (Warning 43, #1): Local integer expected at &quot;buff.c&quot;, line 18, INR = 266
+     (Warning 64, cont.): Actual memory contains a data pointer at &quot;buff.c&quot;, line 18, INR = 266
+</pre>
+
+<p>and indeed at line 18 of the file buff.c we find:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>buff = malloc(buff_size = BFSIZE);</p>
+</table>
+
+<p>This problem can be avoided by using a specially
+compiled version of the library that contains the correct
+LIN and FIL instructions, or, less elegantly, by including
+the source code of the library routines in the program; in
+the latter case, one has to be sure to have them all.</p>
+
+<p><i>Unavoidable messages</i><br>
+Some messages produced by the logging are almost
+unavoidable; sometimes the writer of a library routine is
+forced to take liberties with the semantics of EM.</p>
+
+<p>Examples from C include the memory allocation routines.
+For efficiency reasons, one bit of an pointer in the
+administration is used as a flag; setting, clearing and
+reading this bit requires bitwise operations on pointers,
+which gives the above messages. Realloc causes a problem in
+that it may have to copy the originally allocated area to a
+different place; this area may contain uninitialised
+bytes.</p>
+<pre>     @x9 &quot;t.c&quot;, line 4, INR = 16, PC = 30 OPCODE = 180
+     @L6 &quot;t.c&quot;, line 4, INR = 16, DoLOLm(-4)
+      d2
+      d2 . . STACK_DUMP[4/4] . . INR = 16 . . STACK_DUMP . .
+      d2 ----------------------------------------------------------------
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483643        0                  (Dp)
+      d2    2147483642        0                  (Dp)
+      d2    2147483641        0                  (Dp)
+      d2    2147483640       40    [        40]  (Dp)
+      d2    2147483639        0                  (Dp)
+      d2    2147483638        0                  (Dp)
+      d2    2147483637        3                  (Dp)
+      d2    2147483636       64    [       832]  (Dp)
+      d2    2147483635        0                  (In)
+      d2    2147483634        0                  (In)
+      d2    2147483633        0                  (In)
+      d2    2147483632        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483607        0                  (Dp)
+      d2    2147483606        0                  (Dp)
+      d2    2147483605        0                  (Dp)
+      d2    2147483604       40    [        40]  (Dp)
+      d2    2147483603        0                  (Dp)
+      d2    2147483602        0                  (Dp)
+      d2    2147483601        3                  (Dp)
+      d2    2147483600       64    [       832]  (Dp)
+      d2    2147483599        0                  (In)
+      d2    2147483598        0                  (In)
+      d2    2147483597        0                  (In)
+      d2    2147483596        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483571    undef
+      d2         | | |    | | |
+      d2    2147483568    undef (1 word)
+      d2    2147483567        0                  (In)
+      d2    2147483566        0                  (In)
+      d2    2147483565        3                  (In)
+      d2    2147483564        9    [       777]  (In)
+      d2    2147483563    undef
+      d2         | | |    | | |
+      d2    2147483560    undef (1 word)
+      d2        FRA: size = 0, undefined
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483560, HP = 848, \
+                                        LIN = 4, FIL = &quot;t.c&quot;
+      d2 ----------------------------------------------------------------
+      d2
+     @x9 &quot;t.c&quot;, line 4, INR = 17, PC = 31 OPCODE = 169
+     @w1 &quot;t.c&quot;, line 4, INR = 17, warning: Local data pointer expected [stack.c: 242]
+     @w1 &quot;t.c&quot;, line 4, INR = 17, warning cont.: Actual memory is undefined
+     @L6 &quot;t.c&quot;, line 4, INR = 17, DoLOIm(4)
+      d2
+      d2 . . STACK_DUMP[4/4] . . INR = 17 . . STACK_DUMP . .
+      d2 ----------------------------------------------------------------
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483643        0                  (Dp)
+      d2    2147483642        0                  (Dp)
+      d2    2147483641        0                  (Dp)
+      d2    2147483640       40    [        40]  (Dp)
+      d2    2147483639        0                  (Dp)
+      d2    2147483638        0                  (Dp)
+      d2    2147483637        3                  (Dp)
+      d2    2147483636       64    [       832]  (Dp)
+      d2    2147483635        0                  (In)
+      d2    2147483634        0                  (In)
+      d2    2147483633        0                  (In)
+      d2    2147483632        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483607        0                  (Dp)
+      d2    2147483606        0                  (Dp)
+      d2    2147483605        0                  (Dp)
+      d2    2147483604       40    [        40]  (Dp)
+      d2    2147483603        0                  (Dp)
+      d2    2147483602        0                  (Dp)
+      d2    2147483601        3                  (Dp)
+      d2    2147483600       64    [       832]  (Dp)
+      d2    2147483599        0                  (In)
+      d2    2147483598        0                  (In)
+      d2    2147483597        0                  (In)
+      d2    2147483596        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483571    undef
+      d2         | | |    | | |
+      d2    2147483568    undef (1 word)
+      d2    2147483567        0                  (In)
+      d2    2147483566        0                  (In)
+      d2    2147483565        3                  (In)
+      d2    2147483564        9    [       777]  (In)
+      d2    2147483563        0                  (In)
+      d2    2147483562        0                  (In)
+      d2    2147483561        0                  (In)
+      d2    2147483560        4    [         4]  (In)
+      d2        FRA: size = 0, undefined
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483560, HP = 848, \
+                                        LIN = 4, FIL = &quot;t.c&quot;
+      d2 ----------------------------------------------------------------
+      d2
+     @x9 &quot;t.c&quot;, line 4, INR = 18, PC = 32 OPCODE = 229
+     @S6 &quot;t.c&quot;, line 4, INR = 18, DoSTLm(-8)
+      d2
+      d2 . . STACK_DUMP[4/4] . . INR = 18 . . STACK_DUMP . .
+      d2 ----------------------------------------------------------------
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483643        0                  (Dp)
+      d2    2147483642        0                  (Dp)
+      d2    2147483641        0                  (Dp)
+      d2    2147483640       40    [        40]  (Dp)
+      d2    2147483639        0                  (Dp)
+      d2    2147483638        0                  (Dp)
+      d2    2147483637        3                  (Dp)
+      d2    2147483636       64    [       832]  (Dp)
+      d2    2147483635        0                  (In)
+      d2    2147483634        0                  (In)
+      d2    2147483633        0                  (In)
+      d2    2147483632        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = STP, PI = uninit, PC = 0, LB = 2147483644, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483607        0                  (Dp)
+      d2    2147483606        0                  (Dp)
+      d2    2147483605        0                  (Dp)
+      d2    2147483604       40    [        40]  (Dp)
+      d2    2147483603        0                  (Dp)
+      d2    2147483602        0                  (Dp)
+      d2    2147483601        3                  (Dp)
+      d2    2147483600       64    [       832]  (Dp)
+      d2    2147483599        0                  (In)
+      d2    2147483598        0                  (In)
+      d2    2147483597        0                  (In)
+      d2    2147483596        1    [         1]  (In)
+      d1 &gt;&gt; RSB: code = CAL, PI = (0,0), PC = 16, LB = 2147483608, LIN = 0, FIL = NULL
+      d2
+      d2       ADDRESS     BYTE     ITEM VALUE   SHADOW
+      d2    2147483571    undef
+      d2         | | |    | | |
+      d2    2147483568    undef (1 word)
+      d2    2147483567        0                  (In)
+      d2    2147483566        0                  (In)
+      d2    2147483565        0                  (In)
+      d2    2147483564        4    [         4]  (In)
+      d2        FRA: size = 0, undefined
+      d1 &gt;&gt; AB = 2147483596, LB = 2147483572, SP = 2147483564, HP = 848, \
+                                        LIN = 4, FIL = &quot;t.c&quot;
+      d2 ----------------------------------------------------------------
+      d2
+</pre>
+
+<p align=center>BIBLIOGRAPHY</p>
+
+<p>[1] A.S. Tanenbaum, H. van Staveren, E.G. Keizer and
+J.W. Stevenson. <i>Description of a Machine Architecture for
+use with Block Structured Languages</i>. VU Informatica
+Rapport IR-81, august 1983.</p>
+
+<p>[2] E.G. Keizer. <i>Ack description file reference
+manual.</i></p>
+
+<p>[3] K. Jensen and N. Wirth. <i>PASCAL, User Manual and
+Report</i>. Springer Verlag.</p>
+
+<p>[4] B.W. Kernighan and D.M. Ritchie. <i>The C
+Programming Language</i>. Prentice-Hall, 1978.</p>
+
+<p>[5] D.M. Ritchie. <i>C Reference Manual</i>.</p>
+
+<p>[6] <i>Amsterdam Compiler Kit, reference manual.</i></p>
+
+<p>[7] <i>Unix Programmer&rsquo;s Manual, 4.1BSD</i>. UCB,
+August 1983.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/int.pdf b/doc/tack/int.pdf
new file mode 100644 (file)
index 0000000..f330d8d
Binary files /dev/null and b/doc/tack/int.pdf differ
diff --git a/doc/tack/lint.html b/doc/tack/lint.html
new file mode 100644 (file)
index 0000000..b195de0
--- /dev/null
@@ -0,0 +1,3054 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:38 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Lint, a C Program Checker</title>
+</head>
+<body>
+
+<h1 align=center>Lint, a C Program Checker</h1>
+<a href="#Contents">Contents</a><br>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Outline of the program">2. Outline of the program</a><br>
+<a href="#3. What lint checks">3. What lint checks</a><br>
+<a href="#3.1. Set, used and unused variables">3.1. Set, used and unused variables</a><br>
+<a href="#3.2. Flow of control">3.2. Flow of control</a><br>
+<a href="#3.3. Functions">3.3. Functions</a><br>
+<a href="#3.4. Undefined evaluation order">3.4. Undefined evaluation order</a><br>
+<a href="#3.5. Pointer alignment problems">3.5. Pointer alignment problems</a><br>
+<a href="#3.6. Libraries">3.6. Libraries</a><br>
+<a href="#4. How lint checks">4. How lint checks</a><br>
+<a href="#4.1. The first pass first pass data structure">4.1. The first pass first pass data structure</a><br>
+<a href="#4.1.1. The changes">4.1.1. The changes</a><br>
+<a href="#4.1.1.1. Idf descriptor">4.1.1.1. Idf descriptor</a><br>
+<a href="#4.1.1.2. Def descriptor">4.1.1.2. Def descriptor</a><br>
+<a href="#4.1.2. The additions">4.1.2. The additions</a><br>
+<a href="#4.1.2.1. Lint_stack_entry descriptor">4.1.2.1. Lint_stack_entry descriptor</a><br>
+<a href="#4.1.2.2. State descriptor">4.1.2.2. State descriptor</a><br>
+<a href="#4.1.2.3. Auto_def descriptor">4.1.2.3. Auto_def descriptor</a><br>
+<a href="#4.1.2.4. Expr_state descriptor">4.1.2.4. Expr_state descriptor</a><br>
+<a href="#4.1.2.5. Outdef descriptor">4.1.2.5. Outdef descriptor</a><br>
+<a href="#4.2. The first pass checking mechanism">4.2. The first pass checking mechanism</a><br>
+<a href="#4.2.1. Used and/or set variables">4.2.1. Used and/or set variables</a><br>
+<a href="#4.2.2. Undefined evaluation orders">4.2.2. Undefined evaluation orders</a><br>
+<a href="#4.2.3. Useless statements">4.2.3. Useless statements</a><br>
+<a href="#4.2.4. Not-reachable statements">4.2.4. Not-reachable statements</a><br>
+<a href="#4.2.5. Functions returning expressions and just returning">4.2.5. Functions returning expressions and just returning</a><br>
+<a href="#4.2.6. Output definitions for the second pass">4.2.6. Output definitions for the second pass</a><br>
+<a href="#4.2.7. Generating libraries">4.2.7. Generating libraries</a><br>
+<a href="#4.2.8. Interpreting the pseudocomments">4.2.8. Interpreting the pseudocomments</a><br>
+<a href="#4.3. The second pass data structure">4.3. The second pass data structure</a><br>
+<a href="#4.3.1. Inp_def descriptor">4.3.1. Inp_def descriptor</a><br>
+<a href="#4.4. The second pass checking mechanism">4.4. The second pass checking mechanism</a><br>
+<a href="#4.4.1. Read_defs()">4.4.1. Read_defs()</a><br>
+<a href="#4.4.2. Check()">4.4.2. Check()</a><br>
+<a href="#4.4.3. Check_usage()">4.4.3. Check_usage()</a><br>
+<a href="#5. How to make lint shut up">5. How to make lint shut up</a><br>
+<a href="#6. User options">6. User options</a><br>
+<a href="#7. Ideas for further development">7. Ideas for further development</a><br>
+<a href="#8. Testing the program">8. Testing the program</a><br>
+<a href="#9. References">9. References</a><br>
+<a href="#Appendix A">Appendix A</a><br>
+<a href="#The warnings">The warnings</a><br>
+<a href="#Pass one warnings">Pass one warnings</a><br>
+<a href="#Pass two warnings">Pass two warnings</a><br>
+<a href="#Appendix B">Appendix B</a><br>
+
+<hr>
+
+<p><b>Lint, a C Program Checker</b></p>
+
+<p align=center><small>Afstudeer verslag</small></p>
+
+<p align=center><small>18 mei 1988</small></p>
+
+<p align=center><small><i>Frans Kunst</i></small></p>
+
+<p align=center><small>Vrije Universiteit<br>
+Amsterdam<br>
+This document describes an implementation of a program
+which<br>
+does an extensive consistency and plausibility check on a
+set<br>
+of C program files.<br>
+This may lead to warnings which help the programmer to
+debug<br>
+the program, to remove useless code and to improve his
+style.<br>
+The program has been used to test itself and has found<br>
+bugs in sources of some heavily used code.</small></p>
+<a name="Contents"></a>
+<h2>Contents</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p>Introduction</p>
+</td>
+<td width="65%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="44%">
+
+<p>Outline of the program</p>
+</td>
+<td width="45%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="32%">
+
+<p>What lint checks</p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.1</p>
+</td>
+<td width="4%"></td>
+<td width="60%">
+
+<p>Set, used and unused variables</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.2</p>
+</td>
+<td width="4%"></td>
+<td width="30%">
+
+<p>Flow of control</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.3</p>
+</td>
+<td width="4%"></td>
+<td width="18%">
+
+<p>Functions</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.4</p>
+</td>
+<td width="4%"></td>
+<td width="52%">
+
+<p>Undefined evaluation order</p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.5</p>
+</td>
+<td width="4%"></td>
+<td width="52%">
+
+<p>Pointer alignment problems</p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>3.6</p>
+</td>
+<td width="4%"></td>
+<td width="18%">
+
+<p>Libraries</p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4.</p>
+</td>
+<td width="6%"></td>
+<td width="30%">
+
+<p>How lint checks</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>4.1</p>
+</td>
+<td width="4%"></td>
+<td width="58%">
+
+<p>The first pass data structure</p>
+</td>
+<td width="21%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>4.2</p>
+</td>
+<td width="4%"></td>
+<td width="66%">
+
+<p>The first pass checking mechanism</p>
+</td>
+<td width="13%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>4.3</p>
+</td>
+<td width="4%"></td>
+<td width="60%">
+
+<p>The second pass data structure</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="6%">
+
+<p>4.4</p>
+</td>
+<td width="4%"></td>
+<td width="68%">
+
+<p>The second pass checking mechanism</p>
+</td>
+<td width="11%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5.</p>
+</td>
+<td width="6%"></td>
+<td width="48%">
+
+<p>How to make lint shut up</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>6.</p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p>User options</p>
+</td>
+<td width="65%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>7.</p>
+</td>
+<td width="6%"></td>
+<td width="58%">
+
+<p>Ideas for further development</p>
+</td>
+<td width="31%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>8.</p>
+</td>
+<td width="6%"></td>
+<td width="38%">
+
+<p>Testing the program</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>9.</p>
+</td>
+<td width="6%"></td>
+<td width="20%">
+
+<p>References</p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p>Appendix A &minus; The warnings<br>
+Appendix B &minus; The Ten Commandments for C
+programmers</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>C [1][2] is a dangerous programming language. The
+programmer is allowed to do almost anything, as long as the
+syntax of the program is correct. This has a reason. In this
+way it is possible to make a fast compiler which produces
+fast code. The compiler will be fast because it
+doesn&rsquo;t do much checking at compile time. The code is
+fast because the compiler doesn&rsquo;t generate run time
+checks. The programmer should protect himself against
+producing error prone code. One way to do that is to obey
+the <i>Ten Commandments for C programmers</i> [appendix B].
+This document describes an implementation of the <i>lint</i>
+program, as referred to in Commandment 1. It is a common
+error to run <i>lint</i> only after a few hours of debugging
+and some bug can&rsquo;t be found. <i>Lint</i> should be run
+when large pieces of new code are accepted by the compiler
+and as soon as bugs arise. Even for working programs it is
+useful to run <i>lint,</i> because it can find constructions
+that may lead to problems in the future.</p>
+<a name="2. Outline of the program"></a>
+<h2>2. Outline of the program</h2>
+
+<p>The program can be divided into three parts. A first
+pass, which parses C program files and outputs definitions,
+a second pass which processes the definitions and a driver,
+which feeds the set of files to the first pass and directs
+its output to the second pass. Both passes produce the
+warnings on standard error output, which are redirected to
+standard output by the driver.</p>
+
+<p>The first pass is based on an existing C front end,
+called <i>cem</i> [3]. <i>Cem</i> is part of the Amsterdam
+Compiler Kit (ACK), as described in [4].</p>
+
+<p>Most of the code of <i>cem</i> is left unchanged. This
+has several reasons. A lot of work, which is done by
+<i>cem</i> , must also be done by <i>lint.</i> E.g. the
+lexical analysis, the macro expansions, the parsing part and
+the semantical analysis. Only the code generation part is
+turned off. An advantage of this approach is, that a person
+who understands <i>cem</i> will not have to spend to much
+time in understanding <i>lint.</i></p>
+
+<p>All changes and extensions to <i>cem</i> can be turned
+off by not defining the compiler directive <tt>LINT.</tt>
+Compiling should then result in the original C compiler.</p>
+
+<p>The second pass is a much less complex program. It reads
+simple definitions generated by the first pass and checks
+their consistency. This second pass gives warnings about
+wrong usage of function arguments, their results and about
+external variables, which are used and defined in more than
+one file.</p>
+
+<p>The driver is a shell program, to be executed by the
+<small>UNIX</small> &reg; shell <i>sh.</i> It executes the
+two passes and let them communicate through a filter (sort).
+Actually it is simplex communication: the first pass only
+talks to the second pass through the filter.</p>
+<a name="3. What lint checks"></a>
+<h2>3. What lint checks</h2>
+<a name="3.1. Set, used and unused variables"></a>
+<h2>3.1. Set, used and unused variables</h2>
+
+<p>We make a distinction between two classes of variables:
+the class of automatic variables (including register
+variables) and the other variables. The other variables,
+global variables, static variables, formal parameters et
+cetera, are assumed to have a defined value. Global
+variables e.g., are initialized by the compiled code at
+zeros; formal parameters have a value which is equal to the
+value of the corresponding actual parameter. These variables
+can be used without explicitly initializing them. The
+initial value of automatic variables is undefined (if they
+are not initialized at declaration). These variables should
+be set before they are used. A variable is set by</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>an assignment (including an initialization)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p>taking the address</p>
+</td>
+<td width="43%">
+</td>
+</table>
+
+<p>The first case is clear. The second case is plausible.
+It would take to much effort (if at all possible) to check
+if a variable is set through one of its aliases. Because
+<i>lint</i> should not warn about correct constructs, it
+does this conservative approach. Structures (and unions) can
+also be set by setting at least one member. Again a
+conservative approach. An array can be set by using its name
+(e.g. as actual parameter of a function call). <i>Lint</i>
+warns for usage as <i>rvalue</i> of automatic variables
+which are not set.</p>
+
+<p>A variable is used if</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="44%">
+
+<p>it is used as a <i>rvalue</i></p>
+</td>
+<td width="35%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>2</p>
+</td>
+<td width="8%"></td>
+<td width="40%">
+
+<p>its address is taken</p>
+</td>
+<td width="39%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>Arrays and structures (and unions) are also used if one
+entry or one member respectively is used.</p>
+</td>
+</table>
+
+<p>When a variable is never used in the part of the program
+where it is visible, a warning is given. For variables
+declared at the beginning of a compound statement, a check
+is made at the end of this statement. For formal parameters
+a check is made at the end of the function definition. At
+the end of a file this is done for global static
+definitions. For external variables a warning can be given
+when all the files are parsed.</p>
+<a name="3.2. Flow of control"></a>
+<h2>3.2. Flow of control</h2>
+
+<p>The way <i>lint</i> keeps track of the flow of control
+is best explained by means of an example. See the program of
+figure 1.</p>
+<pre>   if (cond)
+        /* a statement which is executed if cond is true,
+         * the if-part
+         */
+   else
+        /* the else-part */
+
+
+</pre>
+
+<p align=center><i>figure 1.</i></p>
+
+<p>After evaluation of <tt>cond</tt>, two things can
+happen. The if-part is executed or the else-part is executed
+(but not both). Variables which are set in the if-part but
+not in the else-part, need not be set after the if
+statement, and vice versa. <i>Lint</i> detects this and
+assumes these variables after the if statement to be
+<i>maybe set</i>. (See figure 2.)</p>
+<pre>  int cond;
+
+
+  main()
+  {
+          int i, j;
+
+
+          if (cond) {
+                  i = 0;
+                  j = 0;
+          }
+          else
+                  use(i);  /* i may be used before set */
+          use(j);          /* maybe j used before set  */
+  }
+
+
+</pre>
+
+<p align=center><i>figure 2.</i></p>
+
+<p>If both the if-part and the else-part are never left
+(i.e. they contain an endless loop or a return statement),
+<i>lint</i> knows that the if statement is never left too.
+Besides the if statement, <i>lint</i> knows the possible
+flows of control in while, do, for and switch statements. It
+also detects some endless loops like <tt>while(1)</tt>,
+<tt>do ... while (1)</tt>, <tt>for (;;)</tt>.</p>
+<a name="3.3. Functions"></a>
+<h2>3.3. Functions</h2>
+
+<p>Most C compilers will not complain if a function is
+called with actual parameters of a different type than the
+function expects. Using a function in one file as a function
+of type <i>A</i> while defining it in another file as a
+function of type <i>B</i> is also allowed by most compilers.
+It needs no explanation that this can lead to serious
+trouble.</p>
+
+<p><i>Lint</i> checks if functions are called with the
+correct number of arguments, if the types of the actual
+parameters correspond with the types of the formal
+parameters and if function values are used in a way
+consistently with their declaration. When the result of a
+function is used, a check is made to see if the function
+returns a value. When a function returns a value,
+<i>lint</i> checks if the values of all calls of this
+function are used.</p>
+<a name="3.4. Undefined evaluation order"></a>
+<h2>3.4. Undefined evaluation order</h2>
+
+<p>The semantics of C do not define evaluation orders for
+some constructs, which, at first sight, seem well defined.
+The evaluation order of the expression <tt>a[i] = i++;</tt>
+e.g., is undefined. It can be translated to something with
+the semantics of <tt>a[i] = i; i++;</tt> which is what
+probably was meant, or <tt>a[i+1] = i; i++;.</tt> An easier
+example to explain why, is <tt>j = a[i] + i++;.</tt>
+&lsquo;<tt>+</tt>&rsquo; Is a so called <i>commutative</i>
+operator (with respect to the evaluation order) , as is
+&lsquo;<tt>=</tt>&rsquo;. This allows the compiler to choose
+which term to evaluate first. It is easy to see, that it
+makes a difference for the value of <tt>j,</tt> which order
+is chosen. The expression <tt>i++</tt> is said to have
+<i>side effects.</i> It affects the value of <tt>i.</tt>
+Because this value is used in the other term, this gives a
+conflict.</p>
+
+<p>A function call with reference to a variable as argument
+can have side effects to. Therefor, the evaluation order of
+<tt>i</tt> in the expression <tt>f(&amp;i) + i</tt> is
+undefined. When a function is called with an array as
+argument, this array can be affected by the function,
+because only the address of the array is passed to the
+function. (In Pascal a copy of the array is passed to the
+function if the formal parameter is not declared
+<i>var</i>.) So the evaluation order of <tt>a</tt> in the
+expression <tt>f(a) + a[0]</tt> is undefined. This one is
+not yet detected by <i>lint.</i></p>
+
+<p>Global variables can still cause trouble. If function
+<tt>f</tt> affects the global variable <tt>i,</tt> the value
+of the expression <tt>f() + i</tt> is undefined, because the
+evaluation order of <tt>i</tt> is undefined.</p>
+
+<p>The evaluation order of the arguments of a function is
+not defined, so the expression <tt>f(i, i++)</tt> gives a
+warning <tt>i evaluation order undefined.</tt></p>
+<a name="3.5. Pointer alignment problems"></a>
+<h2>3.5. Pointer alignment problems</h2>
+
+<p>For pointers to objects of different types there are
+different alignment restrictions. On some machines pointers
+to type char can have both odd and even values, whereas
+pointers to type int should contain an even address.
+<i>Lint</i> could warn for all pointer conversions. This is
+not what <i>lint</i> does. <i>Lint</i> assumes that some
+pointers are more restricted than others, and that pointers
+of some types can safely be converted to a pointer of a less
+restrictive type. The order of restriction is as follows
+(&lsquo;&le;&rsquo; means &lsquo;is not more restricted
+than&rsquo;) :</p>
+
+<p align=center>char &le; short &le; int &le; long</p>
+
+<p align=center>float &le; double</p>
+<a name="3.6. Libraries"></a>
+<h2>3.6. Libraries</h2>
+
+<p>C is a small language. As a matter of fact it has no i/o
+routines. To make it a useful language, C is supported by
+libraries. These libraries contain functions and variables
+that can be used by any C program. <i>Lint</i> knows some
+libraries too. At this moment it knows the
+&lsquo;-<i>lc</i>&rsquo;, &lsquo;-<i>lm</i>&rsquo; and
+&lsquo;-<i>lcurses</i>&rsquo; libraries. The
+&lsquo;-<i>lc</i>&rsquo; library, containing definitions for
+functions from chapter two and three of the
+<small>UNIX</small> programmers manual, is default.
+<i>Lint</i> warns for definitions of functions or global
+variables with the same name as a function definition in a
+library.</p>
+<a name="4. How lint checks"></a>
+<h2>4. How lint checks</h2>
+<a name="4.1. The first pass first pass data structure"></a>
+<h2>4.1. The first pass first pass data structure</h2>
+
+<p>The data structure of <i>cem</i> is changed a little and
+some structures have been added.</p>
+<a name="4.1.1. The changes"></a>
+<h2>4.1.1. The changes</h2>
+<a name="4.1.1.1. Idf descriptor"></a>
+<h2>4.1.1.1. Idf descriptor</h2>
+
+<p>A member <tt>id_line</tt> is added to the <i>idf</i>
+selector. This line number is used for some warnings.</p>
+<a name="4.1.1.2. Def descriptor"></a>
+<h2>4.1.1.2. Def descriptor</h2>
+
+<p>The <i>def</i> selector is extended with the members
+<tt>df_set</tt> df_line. The <tt>df_used</tt> member did
+exist already, but was only used for code generation. This
+usage is eliminated so it can be used by <i>lint.</i> The
+meaning of these members should be clear.</p>
+<a name="4.1.2. The additions"></a>
+<h2>4.1.2. The additions</h2>
+<a name="4.1.2.1. Lint_stack_entry descriptor"></a>
+<h2>4.1.2.1. Lint_stack_entry descriptor</h2>
+<pre>     struct lint_stack_entry {
+             struct lint_stack_entry *next;
+             struct lint_stack_entry *previous;
+             short ls_class;
+             int ls_level;
+             struct state *ls_current;
+             union {
+                     struct state *S_if;
+                     struct state *S_end;
+                     struct switch_states switch_state;
+             } ls_states;
+     };
+</pre>
+
+<p>Structure to simulate a stacking mechanism.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><tt>next</tt></p>
+</td>
+<td width="22%"></td>
+<td width="70%">
+
+<p>Pointer to the entry on top of this one.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>previous</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>Pointer to the entry beneath this one.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>ls_class</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>The class of statement this entry belongs to. Possible
+classes are <tt>IF</tt>, <tt>WHILE</tt>, <tt>DO</tt>,
+<tt>FOR</tt>, <tt>SWITCH</tt> and <tt>CASE</tt>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>ls_level</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>The level the corresponding statement is nested.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><tt>ls_current</tt></p>
+</td>
+<td width="10%"></td>
+<td width="70%">
+
+<p>A pointer to the state descriptor which describes the
+state of the function (the state of the automatic variables,
+if the next statement can be reached, et cetera) if control
+passes the flow of control to the part of the program
+currently parsed. The initialization of this state is as
+follows</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="39%"></td>
+<td width="60%">
+<p>If <tt>ls_class</tt> in [<tt>IF</tt>, <tt>SWITCH</tt>]
+the state after parsing the conditional expression.</p>
+<!-- INDENTATION -->
+<p>If <tt>ls_class</tt> in [<tt>WHILE</tt>, <tt>FOR</tt>]
+the state after parsing the code between the brackets.</p>
+<!-- INDENTATION -->
+<p>If <tt>ls_class</tt> in [<tt>DO</tt>, <tt>CASE</tt>] the
+state at entrance of the statement after the <tt>DO</tt> or
+<tt>CASE</tt> token.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><tt>ls_states</tt></p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>Union of pointers to state descriptors containing
+different information for different values of
+<tt>ls_class</tt>.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="39%"></td>
+<td width="60%">
+<p>If <tt>ls_class</tt> is <tt>IF</tt> and in case of
+parsing an else part, <tt>ls_states.S_if</tt> points to the
+state that is reached after the if part.</p>
+<!-- INDENTATION -->
+<p>If <tt>ls_class</tt> in [<tt>WHILE</tt>, <tt>FOR</tt>,
+<tt>DO</tt>] then <tt>ls_states.S_end</tt> contains a
+conservative description of the state of the program after
+&lsquo;jumping&rsquo; to the end of the statement after the
+<tt>WHILE</tt>, <tt>DO</tt> or <tt>FOR</tt> token. I.e. the
+state at reaching a break (not inside a switch) or continue
+statement.</p>
+<!-- INDENTATION -->
+<p>If ls_class is <tt>SWITCH</tt>, <tt>ls_states</tt> is
+used as a structure</p>
+<!-- INDENTATION -->
+<pre>     struct switch_states {
+             struct state S_case;
+             struct state S_break;
+     };
+</pre>
+<!-- INDENTATION -->
+<p>containing two pointers to state descriptors.
+<tt>ls_states.switch_state.S_case</tt> contains a
+conservative description of the state of the program after
+<tt>case ... case</tt> parts are parsed.
+<tt>ls_states.switch_state.S_break</tt> the state after
+parsing all the <tt>case ... break</tt> parts. The reason
+for <tt>ls_states.switch_state.default_met</tt> should be
+self-explanatory.</p>
+<!-- INDENTATION -->
+<p>In case <tt>ls_class</tt> is <tt>CASE</tt>,
+<tt>ls_states</tt> is not used.</p>
+</td>
+</table>
+<a name="4.1.2.2. State descriptor"></a>
+<h2>4.1.2.2. State descriptor</h2>
+<pre>           struct state {
+                   struct state *next;
+                   struct auto_def *st_auto_list;
+                   int st_nrchd;
+                   int st_warned;
+           };
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p>st_auto_list</p>
+</td>
+<td width="6%"></td>
+<td width="70%">
+
+<p>Pointer to a list of definitions of the automatic
+variables whose scope contain the current position in the
+program.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>st_nrchd</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>True if the next statement can&rsquo;t be reached.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><tt>st_warned</tt></p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>True if a warning has already been given.</p>
+</td>
+</table>
+<a name="4.1.2.3. Auto_def descriptor"></a>
+<h2>4.1.2.3. Auto_def descriptor</h2>
+<pre>               struct auto_def {
+                       struct auto_def *next;
+                       struct idf *ad_idf;
+                       struct def *ad_def;
+                       int ad_used;
+                       int ad_set;
+                       int ad_maybe_set;
+               };
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>next</p>
+</td>
+<td width="22%"></td>
+<td width="70%">
+
+<p>Points to the next auto_definition of the list.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><tt>ad_idf</tt></p>
+</td>
+<td width="18%"></td>
+<td width="70%">
+
+<p>Pointer to the idf descriptor associated with this
+auto_definition.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><tt>ad_def</tt></p>
+</td>
+<td width="18%"></td>
+<td width="50%">
+
+<p>Ditto for def descriptor.</p>
+</td>
+<td width="19%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><tt>ad_used</tt></p>
+</td>
+<td width="16%"></td>
+<td width="70%">
+
+<p>Indicates the state of this automatic variable. Ditto
+for <tt>ad_set</tt> and <tt>ad_maybe_set</tt>. Only one of
+<tt>ad_set</tt> and <tt>ad_maybe_set</tt> may be true.</p>
+</td>
+</table>
+<a name="4.1.2.4. Expr_state descriptor"></a>
+<h2>4.1.2.4. Expr_state descriptor</h2>
+<pre>              struct expr_state {
+                      struct expr_state *next;
+                      struct idf *es_idf;
+                      arith es_offset;
+                      int es_used;
+                      int es_set;
+              };
+</pre>
+
+<p>This structure is introduced to keep track of which
+variables, array entries and structure members (union
+members) are set and/or used in evaluating an
+expression.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><tt>next</tt></p>
+</td>
+<td width="22%"></td>
+<td width="70%">
+
+<p>Pointer to the next descriptor of this list.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><tt>es_idf</tt></p>
+</td>
+<td width="18%"></td>
+<td width="70%">
+
+<p>Pointer to the idf descriptor this descriptor belongs
+to.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><tt>es_offset</tt></p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>In case of an array, a structure or union, this member
+contains the offset the compiler would generate for locating
+the array entry or structure/union member.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><tt>es_used</tt></p>
+</td>
+<td width="16%"></td>
+<td width="70%">
+
+<p>True if the indicated memory location is used in
+evaluating the expression.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><tt>es_set</tt></p>
+</td>
+<td width="18%"></td>
+<td width="28%">
+
+<p>Ditto for set.</p>
+</td>
+<td width="41%">
+</td>
+</table>
+<a name="4.1.2.5. Outdef descriptor"></a>
+<h2>4.1.2.5. Outdef descriptor</h2>
+<pre>             struct outdef {
+                     int od_class;
+                     char *od_name;
+                     char *od_file;
+                     unsigned int od_line;
+                     int od_nrargs;
+                     struct tp_entry *od_entry;
+                     int od_returns;
+                     struct type *od_type;
+             };
+</pre>
+
+<p>As structures of this type are not allocated dynamically
+by a storage allocator, it contains no next member. An
+outdef can be given to to <tt>output_def()</tt> to be passed
+to the second pass. Basically this forms the interface with
+the second pass.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>od_class</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>Indicates what kind of definition it is. Possible
+classes are <tt>EFDF</tt>, <tt>EVDF</tt>, <tt>SFDF</tt>,
+<tt>SVDF</tt>, <tt>LFDF</tt>, <tt>LVDF</tt>, <tt>EFDC</tt>,
+<tt>EVDC</tt>, <tt>IFDC</tt>, <tt>FC</tt>, <tt>VU</tt>.
+([<tt>E</tt>xternal, <tt>S</tt>tatic, <tt>L</tt>ibrary,
+<tt>I</tt>mplicit] [<tt>F</tt>unction, <tt>V</tt>ariable]
+[<tt>D</tt>e<tt>F</tt>inition,
+<tt>D</tt>e<tt>C</tt>laration, <tt>C</tt>all,
+<tt>U</tt>sage])</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><tt>od_name</tt></p>
+</td>
+<td width="16%"></td>
+<td width="70%">
+
+<p>The name of the function or variable.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><tt>od_file</tt></p>
+</td>
+<td width="16%"></td>
+<td width="70%">
+
+<p>The file this definition comes from.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><tt>od_nrargs</tt></p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>If <tt>od_class</tt> is one of <tt>EFDF</tt>,
+<tt>SFDF</tt> or <tt>LFDF</tt>, this member contains the
+number of arguments this function has. If the function was
+preceded by the pseudocomment <tt>/* VARARGS */</tt>,
+<tt>od_nrargs</tt> gets the value <tt>-1-n</tt>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><tt>od_entry</tt></p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>A pointer to a list of <tt>od_nrargs</tt> cells, each
+containing a pointer to the type descriptor of an argument.
+(<tt>-1-od_nrargs</tt> cells if <tt>od_nrargs &lt; 0</tt>.)
+<tt>Tp_entry</tt> is defined as</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="70%">
+<pre>struct tp_entry {
+        struct tp_entry *next; /* pointer to next cell */
+        struct type *te_type;  /* an argument type     */
+};
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>od_returns</p>
+</td>
+<td width="10%"></td>
+<td width="70%">
+
+<p>For classes <tt>EFDF</tt>, <tt>SFDF</tt> and
+<tt>LFDF</tt> this member tells if the function returns an
+expression or not. In case <tt>od_class</tt> is <tt>FC</tt>
+it is true if the value of the function is used, false
+otherwise. For other classes this member is not used.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><tt>od_type</tt></p>
+</td>
+<td width="16%"></td>
+<td width="70%">
+
+<p>A pointer to the type of the function or variable
+defined or declared. Not used for classes <tt>FC</tt> and
+<tt>VU</tt>.</p>
+</td>
+</table>
+<a name="4.2. The first pass checking mechanism"></a>
+<h2>4.2. The first pass checking mechanism</h2>
+
+<p>In the description of the implementation of the pass one
+warnings, it is assumed that the reader is familiar with the
+<i>LLgen</i> parser generator, as described in [6].</p>
+<a name="4.2.1. Used and/or set variables"></a>
+<h2>4.2.1. Used and/or set variables</h2>
+
+<p>To be able to give warnings like <tt>%s used before
+set</tt> and <tt>%s set but not used in function %s</tt> ,
+there needs to be a way to keep track of the state of a
+variable. A first approach to do this was by adding two
+fields to the <i>def</i> selector: <tt>df_set</tt> and
+<tt>df_used.</tt> While parsing the program, each time an
+expression was met this expression was analyzed and the
+fields of each <i>def</i> selector were possibly set during
+this analysis. This analysis was done by passing each
+expression to a function <tt>lint_expr</tt> , which walks
+the expression tree in a way similar to the function
+<tt>EVAL</tt> in the file <i>eval.c</i> of the original
+<i>cem</i> compiler. This approach has one big disadvantage:
+it is impossible to keep track of the flow of control of the
+program. No warning will be given for the program fragment
+of figure 3.</p>
+<pre>  func()
+  {
+          int i;
+
+
+          if (cond)
+                  i = 0;
+          else
+                  use(i);  /* i may be used before set */
+  }
+
+
+</pre>
+
+<p align=center>figure 3.</p>
+
+<p>It is clear that it would be nice having <i>lint</i>
+warn for this construction.</p>
+
+<p>This was done in the second approach. When there was a
+choice between two statements, each statement was parsed
+with its own copy of the state at entrance of the
+<i>choosing statement.</i> A state consisted of the state of
+the automatic variables (including register variables). In
+addition to the possibilities of being used and set, a
+variable could be <i>maybe set</i>. These states were passed
+between the statement parsing routines using the
+<i>LLgen</i> parameter mechanism. At the end of a choosing
+statement, the two states were merged into one state, which
+became the state after this statement. The construction of
+figure 4 was now detected, but switch statements still gave
+problems and continue and break statements were not
+understood. The main problem of a switch statement is, that
+the closing bracket (&lsquo;<tt>)</tt>&rsquo;) has to be
+followed by a <i>statement</i>. The syntax shows no choice
+of statements, as is the case with if, while, do and for
+statements. Using the <i>LLgen</i> parameter mechanism, it
+is not a trivial task to parse the different case parts of a
+switch statement with the same initial state and to merge
+the results into one state. This observation led to the
+third and final approach, as described next.</p>
+
+<p>Instead of passing the state of the program through the
+statements parsing routines using the <i>LLgen</i>
+parameters, a special stack is introduced, the
+<i>lint_stack.</i> When a choosing statement is parsed, an
+entry is pushed on the stack containing the information that
+is needed to keep track of the state of the program. Each
+entry contains a description of the <i>current</i> state of
+the program and a field that indicates what part of the
+program the parser is currently parsing. For all the
+possible choosing statements I describe the actions to be
+taken.</p>
+
+<p>At entrance of an if statement, an entry is pushed on
+the stack with the current state being a copy of the current
+state of the stack element one below. The class of this
+entry is <tt>IF</tt>. At reaching the else part, the current
+state is moved to another place in this stack entry (to
+<tt>S_IF</tt>), and a new copy of the current state at
+entrance of this if statement is made. At the end of the
+else part, the two states are merged into one state, the new
+current state, and the <tt>IF</tt> entry is popped from the
+stack. If there is no else part, then the state that is
+reached after parsing the if part is merged with the current
+state at entrance of the if statement into the new current
+state.</p>
+
+<p>At entrance of a while statement a <tt>WHILE</tt> entry
+is pushed on the stack containing a copy of the current
+state. If a continue or break statement is met in the while
+statement, the state at reaching this continue or break
+statement is merged with a special state in the
+<tt>WHILE</tt> entry, called <tt>S_END</tt>. (If
+<tt>S_END</tt> did not yet contain a state, the state is
+copied to <tt>S_END</tt>.) At the end of the while statement
+this <tt>S_END</tt> is merged with the current state, which
+result is merged with the state at entrance of the while
+statement into the new current state.</p>
+
+<p>A for statement is treated similarly. A do statement is
+treated the same way too, except that <tt>S_END</tt>
+isn&rsquo;t merged with the state at entrance of the do
+statement, but becomes the new current state.</p>
+
+<p>For switch statements a <tt>SWITCH</tt> entry is pushed
+on the stack. Apart from the current state, this entry
+contains two other states, <tt>S_BREAK</tt> and
+<tt>S_CASE</tt>. <tt>S_BREAK</tt> initially contains no
+state, <tt>S_CASE</tt> initially contains a copy of the
+current state at entrance of the switch statement. After
+parsing a case label, a <tt>CASE</tt> entry is pushed on the
+stack, containing a copy of the current state. If, after
+zero or more statements, we meet another case label, the
+state at reaching this case label is merged with
+<tt>S_CASE</tt> of the <tt>SWITCH</tt> entry below and a new
+copy of the state at entrance of the switch statement is put
+in the <tt>CASE</tt> entry. If we meet a break statement, we
+merge the current state with <tt>S_BREAK</tt> of the
+<tt>SWITCH</tt> entry below and pop the <tt>CASE</tt> entry.
+In addition to this, the occurrence of a default statement
+inside the switch statement is recorded in the
+<tt>SWITCH</tt> entry. At the end of the switch statement we
+check if we have met a default statement. If not,
+<tt>S_BREAK</tt> is merged with the current state at
+entrance of the switch statement. (Because it is possible
+that no case label will be chosen.) Next the <tt>S_CASE</tt>
+is &lsquo;special_merged&rsquo; with <tt>S_BREAK</tt> into
+the new current state. For more details about these merge
+functions see the sources.</p>
+
+<p>With the approach described above, <i>lint</i> is aware
+of the flow of control in the program. There still are some
+doubtful constructions <i>lint</i> will not detect and there
+are some constructions (although rare) for which <i>lint</i>
+gives an incorrect warning (see figure 4).</p>
+<pre>       {
+               int i;
+
+
+               for (;;) {
+                       if (cond) {
+                               i = 0;
+                               break;
+                       }
+               }
+               use(i);
+               /* lint warns: maybe i used before set
+                * although  the  fragment  is correct
+                */
+       }
+
+
+</pre>
+
+<p align=center><i>figure 4.</i></p>
+
+<p>A nice advantage of the method is, that the parser stays
+clear, i.e. it isn&rsquo;t extended with extra parameters
+which must pass the states. In this way the parser still is
+very readable and we have a nice interface with <i>lint</i>
+using function calls.</p>
+<a name="4.2.2. Undefined evaluation orders"></a>
+<h2>4.2.2. Undefined evaluation orders</h2>
+
+<p>In expressions the values of some variables are used and
+some variables are set. Of course, the same holds for
+subexpressions. The compiler is allowed to choose the order
+of evaluation of subexpressions involving a commutative and
+associative operator (<tt>*</tt>, <tt>+</tt>,
+<tt>&amp;</tt>, <tt>|</tt>, <tt>^</tt>), the comma in a
+parameter list or an assignment operator. In section 3.4 it
+is made clear that this will lead to statements with
+ambiguous semantics.</p>
+
+<p>The way these constructs are detected is rather straight
+forward. The function which parses an expression
+(<tt>lint_expr</tt>) returns a linked list containing
+information telling which variables are set and which
+variables are used. A variable is indicated by its
+<i>idf</i> descriptor and an <i>offset.</i> This offset is
+needed for discriminating entries of the same array and
+members of the same structure or union, so it is possible to
+warn about the statement <tt>a[b[0]] = b[0]++;.</tt> When
+<tt>lint_expr</tt> meets a commutative operator (with
+respect to the evaluation order), it calls itself
+recursively with the operands of the operator as expression.
+The returned results are checked for undefined evaluation
+orders and are put together. This is done by the function
+<tt>check_and_merge</tt>.</p>
+<a name="4.2.3. Useless statements"></a>
+<h2>4.2.3. Useless statements</h2>
+
+<p>Statements which compute a value that is not used, are
+said to have a <i>null effect</i>. Examples are <tt>x = 2,
+3;</tt>, <tt>f() + g();</tt> and <tt>*p++;</tt>. (<tt>*</tt>
+and <tt>++</tt> have the same precedence and associate from
+right to left.)</p>
+
+<p>A conditional expression computes a value too. If this
+value isn&rsquo;t used, it is better to use an if-else
+statement. So, if <i>lint</i> sees</p>
+<pre>                       b ? f() : g();
+</pre>
+
+<p>it warns <tt>use if-else construction</tt>.</p>
+<a name="4.2.4. Not-reachable statements"></a>
+<h2>4.2.4. Not-reachable statements</h2>
+
+<p>The algorithm to detect not-reachable statements
+(including not reachable initializations) is as follows.
+Statements after a label and a case statement and the
+compound statement of a function are always reachable. Other
+statements are not-reachable after:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a goto statement</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a return statement</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a break statement</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a continue statement</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a switch statement</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>an endless loop (a while, do or for loop with a
+conditional which always evaluates to true and without a
+break statement)</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>an if-else statement of which both if part and else part
+end up in a not-reachable state</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>a switch statement of which all <tt>case ... break</tt>
+parts (including a <tt>default ... break</tt> part) end up
+in a not-reachable state</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>the pseudocomment <tt>/* NOTREACHED */</tt></p>
+</td>
+</table>
+
+<p>The algorithm is easily implemented using the
+<tt>st_nrchd</tt> selector in the <i>state</i> descriptor.
+The <tt>st_warned</tt> selector is used to prevent
+superfluous warnings. To detect an endless loop, after a
+while (&lt;true&gt;), for (..;&lt;true&gt;;..) and do part
+the current state of the stack entry beneath the top one is
+set to not reached. If, in the statement following, a break
+statement is met, this same state is set to reached. If the
+while (&lt;cond&gt;) part of the do statement is met, this
+state is set to reached if &lt;cond&gt; doesn&rsquo;t
+evaluates to true. The detection of not-reachable statements
+after a switch statement is done in a similar way. In
+addition it is checked if a default statement isn&rsquo;t
+met, in which case the statement after the switch statement
+can be reached. The warning <tt>statement not reached</tt>
+is not given for compound statements. If <i>lint</i> did, it
+would warn for the compound statement in a switch statement,
+which would be incorrect.</p>
+
+<p>Not-reachable statements are still interpreted by
+<i>lint.</i> I.e. when <i>lint</i> warns that some statement
+can&rsquo;t be reached, it assumes this is not what the
+programmer really wants and it ignores this fact. In this
+way a lot of useless warnings are prevented in the case of a
+not-reachable statement. See figure 5.</p>
+<pre> {
+         int i;
+
+
+         for (;;) {
+                 /* A loop in which the programmer
+                  * forgot to introduce a conditional
+                  * break statement.
+                  * Suppose i is not used in this part.
+                  */
+         }
+         /* some more code in which i is used */
+ }
+ /* The warning &quot;statement not reached&quot; highlights the bug.
+  * An additional warning &quot;i unused in function %s&quot; is
+  * formally correct, but doesn&rsquo;t provide the programmer
+  * with useful information.
+  */
+
+
+</pre>
+
+<p align=center><i>figure 5.</i></p>
+<a name="4.2.5. Functions returning expressions and just returning"></a>
+<h2>4.2.5. Functions returning expressions and just returning</h2>
+
+<p>Each time a return statement is met, <i>lint</i> checks
+if an expression is returned or not. If a function has a
+return with expression and a return without expression,
+<i>lint</i> warns <tt>function %s has return(e); and
+return;.</tt> If the flow of control can <i>fall through</i>
+the end of the compound statement of a function, this
+indicates an implicit return statement without an
+expression. If the end of the compound statement of the
+function can be reached, <i>lint</i> introduces this
+implicit return statement without expression.</p>
+
+<p>Sometimes the programmer knows for sure that all case
+parts inside a switch statement include all possible cases,
+so he doesn&rsquo;t introduce a default statement. This can
+lead to an incorrect warning. Figure 6 shows how to prevent
+this warning.</p>
+<pre>            func()
+            {
+                    switch (cond) {
+                    case 0: return(e0);
+                    case 1: return(e1);
+                    }
+                    /* NOTREACHED */
+            }
+/* no warning: &quot;function func has return(e); and return; */
+
+
+</pre>
+
+<p align=center><i>figure 6.</i></p>
+
+<p>The pseudocomment <tt>/* NOTREACHED */</tt> can also be
+used to tell <i>lint</i> that some function doesn&rsquo;t
+return. See figure 7.</p>
+<pre>  func()
+  {
+          switch (cond) {
+          case 0: return(e0);
+          case 1: return(e1);
+          default: error();   /* calls exit or abort */
+                   /* NOTREACHED */
+          }
+  }
+/* no warning: &quot;function func has return(e); and return;&quot; */
+
+
+</pre>
+
+<p align=center>figure 7.</p>
+<a name="4.2.6. Output definitions for the second pass"></a>
+<h2>4.2.6. Output definitions for the second pass</h2>
+
+<p>The first pass can only process one program file. To be
+able to process a program that spreads over more than one
+file, the first pass outputs definitions that are processed
+by a second pass. The format of such a definition is
+different for different classes:</p>
+
+<p>For class in {EFDF, SFDF, LFDF}</p>
+
+
+<p align=center>&lt;name&gt;:&lt;class&gt;:&lt;file&gt;:&lt;line&gt;:&lt;nr
+of args&gt;:&lt;type of args&gt;:&lt;returns
+value&gt;:&lt;type&gt;</p>
+
+<p>A negative <i>nr of args</i> indicates that the function
+can be called with a varying number of arguments.</p>
+
+<p>For class = FC</p>
+
+
+<p align=center>&lt;name&gt;:&lt;class&gt;:&lt;file&gt;:&lt;line&gt;:&lt;value
+is used&gt;:&lt;type&gt;</p>
+
+<p>The <i>value is used</i> part can have three meanings:
+the value of the function is ignored; the value of the
+function is used; the value of the function is cast to type
+<i>void</i>.</p>
+
+<p>For other classes</p>
+
+
+<p align=center>&lt;name&gt;:&lt;class&gt;:&lt;file&gt;:&lt;line&gt;:&lt;type&gt;</p>
+
+<p>Definitions of class VU (Variable Usage) are only output
+for <i>used</i> global variables.</p>
+
+<p>Structure and union types that are output to the
+intermediate file are simplified. (The following occurrences
+of <i>structure</i> should be read as <i>structure or
+union</i> and <i>struct</i> as <i>struct or union</i>.)
+Structures that are identified by a <i>structure tag</i> are
+output to the intermediate file as <tt>struct
+&lt;tag&gt;</tt>. Structures without a structure tag are
+output as <tt>struct {&lt;mems&gt;}</tt> with
+<tt>&lt;mems&gt;</tt> a semicolon-separated list of types of
+the members of this structure. An alternative way would be
+to output the complete structure definition. However, this
+gives practical problems. It is allowed to define some
+object of a structure type with a structure tag, without
+this structure being defined at that place. The first
+approach leaves errors, such as in figure 8, undetected.</p>
+<pre>       &quot;a.c&quot;                           &quot;b.c&quot;
+
+
+   struct str {                    struct str {
+           float f;                        int i;
+   } s;                            };
+
+
+   main()                          func(s)
+   {                                       struct str s;
+           func(s);                {}
+   }
+
+
+</pre>
+
+<p align=center>figure 8.</p>
+
+<p>To be able to detect these errors, the first pass should
+also output definitions of structure tags. The example of
+figure 8 would then get a warning like <tt>structure str
+defined inconsistently</tt></p>
+
+<p>More information on these definitions in section 4.3 and
+4.4.</p>
+<a name="4.2.7. Generating libraries"></a>
+<h2>4.2.7. Generating libraries</h2>
+
+<p><i>Lint</i> knows the library &lsquo;-lc&rsquo;,
+&lsquo;-lm&rsquo; and &lsquo;-lcurses&rsquo;. If a program
+uses some other library, it is possible to generate a
+corresponding <i>lint library</i>. To do this, precede all
+the C source files of this library by the pseudocomment
+<tt>/* LINTLIBRARY */</tt>. Then feed these files one by one
+to the first pass of <i>lint</i> collecting the standard
+output in a file and ignoring the warnings. The resulting
+file contains library definitions of the functions and
+external variables defined in the library sources, and not
+more than that. If this file is called
+&lsquo;llib-l<i>name</i>.ln <i>lint</i> can be told to
+search the library by passing it as argument in the command
+line &lsquo;-llib-l<i>name</i>.ln. The implementation of
+this feature is simple.</p>
+
+<p>As soon as the pseudocomment <tt>/* LINTLIBRARY */</tt>
+is met, only function and variable definitions are output
+with class LFDF and LVDF respectively. Other definitions,
+which otherwise would have been output, are discarded.</p>
+
+<p>Instead of generating a special lint library file, one
+can make a file containing the library definitions and
+starting with <tt>/* LINTLIBRARY */</tt>. This file can then
+be passed to <i>lint</i> just by its name. This method
+isn&rsquo;t as efficient as the first one.</p>
+<a name="4.2.8. Interpreting the pseudocomments"></a>
+<h2>4.2.8. Interpreting the pseudocomments</h2>
+
+<p>The interpretation of the pseudocomments is done by the
+lexical analyzer, because this part of the program already
+took care of the comments. At first sight this seems very
+easy: as soon as some pseudocomment is met, raise the
+corresponding flag. Unfortunately this doesn&rsquo;t work.
+The lexical analyzer is a <i>one token look ahead
+scanner</i>. This causes the above procedure to raise the
+flags one token too soon. A solution to get the right effect
+is to reserve two flags per pseudocomment. The first is set
+as soon as the corresponding pseudocomment is scanned. At
+the returning of each token this flag is moved to the second
+flag. The delay in this way achieved makes the
+pseudocomments have effect at the correct place.</p>
+<a name="4.3. The second pass data structure"></a>
+<h2>4.3. The second pass data structure</h2>
+<a name="4.3.1. Inp_def descriptor"></a>
+<h2>4.3.1. Inp_def descriptor</h2>
+<pre>             struct inp_def {
+                     struct inp_def *next;
+                     int id_class;
+                     char id_name[NAMESIZE];
+                     char id_file[FNAMESIZE];
+                     unsigned int id_line;
+                     int id_nrargs;
+                     char argtps[ARGSTPSSIZE];
+                     int id_returns;
+                     char id_type[TYPESIZE];
+                     int id_called;
+                     int id_used;
+                     int id_ignored;
+                     int id_voided;
+             };
+</pre>
+
+<p>This description is almost similar to the <i>outdef</i>
+descriptor as described in 4.1.2.5. There are some
+differences too.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><tt>next</tt></p>
+</td>
+<td width="22%"></td>
+<td width="70%">
+
+<p>As structures of this type are allocated dynamically,
+this field is added so the same memory allocator as used in
+the first pass can be used.</p>
+</td>
+</table>
+
+<p><tt>id_called<br>
+id_used<br>
+id_ignored</tt></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><tt>id_voided</tt></p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>Some additional fields only used for function
+definitions.Their meaning should be clear.</p>
+</td>
+</table>
+
+<p>The other fields have the same meaning as the
+corresponding fields in the <i>outdef</i> descriptor. Some
+attention should be paid to <tt>id_argtps</tt> and
+<tt>id_type</tt>. These members have type <tt>array of
+char</tt>, in contrast to their counterparts in the
+<i>outdef</i> descriptor. The only operation performed on
+types is a check on equality. Types are output by the first
+pass as a string describing the type. The type of <tt>i</tt>
+in <tt>int *i();</tt> e.g. is output as <tt>int *()</tt>.
+Such a string is best put in an <tt>array of char</tt> to be
+compared easily.</p>
+<a name="4.4. The second pass checking mechanism"></a>
+<h2>4.4. The second pass checking mechanism</h2>
+
+<p>After all the definitions that are output by the first
+pass are sorted by name, the definitions belonging to one
+name are ordered as follows.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>external definitions</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>static definitions</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>library definitions</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>declarations</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>function calls</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>-</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="21%"></td>
+<td width="78%">
+<p>variable usages</p>
+</td>
+</table>
+
+<p>The main program of the second pass is easily explained.
+For all different names, do the following. First read the
+definitions. If there is more than one definition, check for
+conflicts. Then read the declarations, function calls and
+variable usages and check them against the definitions.
+After having processed all the declarations, function calls
+and variable usages, check the definitions to see if they
+are used correctly. The next three paragraphs will explain
+the three most important functions of the program.</p>
+<a name="4.4.1. Read_defs()"></a>
+<h2>4.4.1. Read_defs()</h2>
+
+<p>This function reads all definitions belonging to the
+same name. Only one external definition is allowed, so if
+there are more, a warning is given. In different files it is
+allowed to define static functions or variables with the
+same name. So if a static function is read,
+<tt>read_defs</tt> checks if there isn&rsquo;t already an
+external definition, and if not it puts the static
+definition in the list of static definitions, to be used
+later. If no external or static definitions are met, a
+library definition is taken as definition. If a function or
+a variable is defined with the same name as a function or a
+variable in a library (which is allowed) <i>lint</i> gives a
+warning. Of course it is also possible that there is no
+definition at all. In that case <tt>check</tt> will
+warn.</p>
+<a name="4.4.2. Check()"></a>
+<h2>4.4.2. Check()</h2>
+
+<p><tt>Check</tt> verifies declarations, function calls and
+variable usages against the definitions. For each of these
+entries the corresponding definition is looked up. As there
+may be more than one static definition, first a static
+definition from the same file as the entry is searched. If
+not present, the external definition (which may be a library
+definition) is taken as definition. If no definition can be
+found and the current entry is an external declaration,
+<i>lint</i> warns. However in the case of an implicit
+function declaration <i>lint</i> will not warn, because we
+will get a warning <tt>%s used but not defined</tt> later
+on. Next a check is done if the declarations are consistent
+with their definitions. After the declarations, the function
+calls and variable usages are verified against their
+corresponding definitions. If no definition exists,
+<i>lint</i> warns. Else the field <tt>id_called</tt> is set
+to 1. (For variable definitions this should be interpreted
+as <i>used</i>.) For variable usages this will be all. If we
+are processing a function call we also check the number and
+types of the arguments and we warn for function values which
+are used from functions that don&rsquo;t return a value. For
+each function call we administrate if a function value is
+used, ignored or voided.</p>
+<a name="4.4.3. Check_usage()"></a>
+<h2>4.4.3. Check_usage()</h2>
+
+<p>Checks if the external definition and static definitions
+are used correctly. If a function or variable is defined but
+never used, <i>lint</i> warns, except for library
+definitions. Functions, which return a value but whose value
+is always or sometimes ignored, get a warning. (A function
+value which is voided (cast to void) is not ignored, but it
+isn&rsquo;t used either.)</p>
+<a name="5. How to make lint shut up"></a>
+<h2>5. How to make lint shut up</h2>
+
+<p>It can be very annoying having <i>lint</i> warn about
+questionable constructs of which the programmer already is
+aware. There should be a mechanism to give <i>lint</i> some
+extra information in the source code. This could be done by
+introducing some special keywords, which would have a
+special meaning to <i>lint.</i> This is a bad solution,
+because these keywords would cause existing C compilers not
+to work on these programs. A neater solution is to invent
+some comments having a special meaning to <i>lint.</i> We
+call these comments <i>pseudocomments.</i> The
+pseudocomments have no meaning to existing C compilers, so
+compilers will not have to be rewritten for C programs
+containing the previously proposed special keywords. The
+following pseudocomments are recognized by <i>lint.</i></p>
+
+<p><tt>/* VARARGS</tt><i>n</i> <tt>*/</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The next function can be called with a variable number of
+arguments. Only check the first <i>n</i> arguments. The
+<i>n</i> must follow the word <tt>VARARGS</tt> immediately.
+This pseudocomment is useful for functions like e.g. printf.
+(The definition of the function printf should be preceded by
+<tt>/* VARARGS1 */</tt>.)</p></td>
+</table>
+
+<p><tt>/* VARARGS */</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Means the same as <tt>/* VARARGS0 */</tt>.</p></td>
+</table>
+
+<p><tt>/* ARGSUSED */</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Don&rsquo;t complain about unused arguments in the next
+function. When we are developing a program we sometimes
+write functions of which we do not yet use the arguments.
+Because we do want to use <i>lint</i> on these programs, it
+is nice to have this pseudocomment.</p></td>
+</table>
+
+<p><tt>/* NOTREACHED */</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><i>Lint</i> makes no attempt to discover functions which
+never return, although it <i>is</i> possible to find
+functions that don&rsquo;t return. This would require a
+transitive closure with respect to the already known
+<i>not-returning</i> functions; an inacceptable time
+consuming process. To make <i>lint</i> aware of a function
+that doesn&rsquo;t return, a call of this function should be
+followed by the pseudocomment <tt>/* NOTREACHED */</tt>.
+This pseudocomment can also be used to indicate that some
+case part inside a switch (especially a default part)
+can&rsquo;t be reached. The above mentioned cases of use of
+this pseudocomment are examples. The comment can be used
+just to indicate that some part of the program can&rsquo;t
+be reached. It sometimes is necessary to introduce an extra
+compound statement to get the right effect. See figure
+9.</p>
+</td>
+</table>
+<pre>         if (cond)
+                 /* if part */ ;
+         else {
+                 error();  /* doesn&rsquo;t return */
+                 /* NOTREACHED */
+         }
+ /* Without  the compound  else  part, lint  would  assume
+  * the statement after the if statement to be NOTREACHED,
+  * instead of the end of the else part.
+  */
+
+
+</pre>
+
+<p align=center>figure 9.</p>
+
+<p><tt>/* LINTLIBRARY */</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>All definitions following this comment are assumed to be
+library definitions. It shuts off complaints about unused
+functions and variables. See also section 4.2.7 for how to
+use this comment for generating lint libraries.</p></td>
+</table>
+<a name="6. User options"></a>
+<h2>6. User options</h2>
+
+<p><i>Lint</i> recognizes the following command line flags.
+Some of them are identical to the flags of <i>cem. Lint</i>
+warns for flags it doesn&rsquo;t know.</p>
+
+<p><tt>-D&lt;name&gt;<br>
+-D&lt;name&gt;=&lt;text&gt;</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Causes <tt>&lt;name&gt;</tt> to be defined as a macro.
+The first form is equivalent to
+&lsquo;<tt>-D&lt;name&gt;=1</tt>&rsquo;. The second form is
+equivalent to putting &lsquo;<tt>#define &lt;name&gt;
+&lt;text&gt;</tt>&rsquo; in front of all the source
+files.</p></td>
+</table>
+
+<p><tt>-U&lt;name&gt;</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Acts as if the line &lsquo;<tt>#undef
+&lt;name&gt;</tt>&rsquo; is put in front of all the source
+files.</p></td>
+</table>
+
+<p><tt>-I&lt;directory&gt;</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This puts <tt>&lt;directory&gt;</tt> in the include
+directory list.</p></td>
+</table>
+
+<p><tt>-R</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Turn off the &lsquo;strict&rsquo; option. Default
+<i>lint</i> checks the program according to the Reference
+Manual, because this gives a definition of the language with
+which there is a better chance of writing portable programs.
+With this flag on, some constructs, otherwise not allowed,
+are accepted.</p></td>
+</table>
+
+<p><tt>-l&lt;name&gt;<br>
+-llib-l&lt;name&gt;.ln<br>
+-l</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>&lsquo;<tt>-l&lt;name&gt;</tt>&rsquo; tells <i>lint</i>
+to search the lint library <tt>llib-l&lt;name&gt;.ln</tt>
+for missing definitions of functions and variables. The
+option &lsquo;<tt>-llib-l&lt;name&gt;.ln</tt>&rsquo; makes
+<i>lint</i> search the lint library file
+<tt>llib-l&lt;name&gt;.ln</tt> in the current directory for
+missing definitions. Default is &lsquo;<tt>-lc</tt>&rsquo;;
+this default can be suppressed by
+&lsquo;<tt>-l</tt>&rsquo;.</p></td>
+</table>
+
+<p><tt>-a</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Warn for conversions from integer to long and vice
+versa.</p></td>
+</table>
+
+<p><tt>-b</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Don&rsquo;t report not-reachable break statements. This
+flag is useful for running <i>lint</i> on a <i>lex</i>- or
+<i>yacc</i>-generated source file.</p></td>
+</table>
+
+<p><tt>-h</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Check for useless statements and possible pointer
+alignment problems.</p></td>
+</table>
+
+<p><tt>-n</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Don&rsquo;t complain about unused and undefined functions
+and variables.</p></td>
+</table>
+
+<p><tt>-v</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Don&rsquo;t warn about unused arguments of
+functions.</p></td>
+</table>
+
+<p><tt>-x</tt></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Complain about unused external variables.</p></td>
+</table>
+<a name="7. Ideas for further development"></a>
+<h2>7. Ideas for further development</h2>
+
+<p>Although the program in its current state is a useful
+program, there are still a lot of features that should be
+implemented in following versions. I&rsquo;ll summarize them
+in this section.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Actually the program consists of three passes. The
+filter <i>sort</i> is a complete pass, just as the first and
+the second pass. I think we speed up the program by removing
+the filter and making the second pass accept an unsorted
+file. The sorting process can be done in parallel to the
+first pass if both processes communicate through a pipe. In
+addition to this sorting, the second pass can generate
+already some warnings. (Warnings like <tt>%s defined but
+never used</tt> can only be generated after having processed
+all the input.) These warnings generated in parallel to the
+warnings of the first pass, should be sent to an
+intermediate file, otherwise the warnings would get messed
+up. Such an improvement will have best effect on a multi
+processing machine, but even on single processing machines
+this will give a better performance. (On a single processing
+machine the pipe should be replaced by an intermediate
+file.)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Expressions could be classified so <i>lint</i> can warn
+for some classes of expressions in strange contexts. Suppose
+as class &lt;boolean&gt;. <tt>b</tt> Will be of class
+&lt;boolean&gt; if e.g. <tt>b</tt> is assigned to the
+expression <tt>&lt;ex1&gt; || &lt;ex2&gt;</tt>. The
+following expression should then give a warning</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>           b + i;    /* weird expression */
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A mechanism to check printf like routines. This
+mechanism should verify the format string against the
+following arguments. There is a public domain program that
+can be used to do this job. It is called printfck and should
+be used as a filter between the source files and
+<i>lint.</i></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Raise warnings for incomplete initializer lists like</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>          int a[10] = {0, 1, 2};
+          /* initializer list not complete */
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="56%">
+
+<p>Warnings for constructs like</p>
+</td>
+<td width="33%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>     for (i = 0; i &lt; 10; i++) {
+             . . . .
+             i--;
+             /* loop control variable affected */
+             . . . .
+     }
+</pre>
+<!-- INDENTATION -->
+<p>and</p>
+<!-- INDENTATION -->
+<pre>       while (var) {
+               /* statements in which the value
+                * of var is never changed
+                */
+       }
+       /* loop control variable not updated */
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A warning <tt>bad layout</tt> for program fragments
+like</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>             if (cond1)
+                     if (cond2)
+                             statement();
+             else  /* bad layout */
+                     statement();
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A warning <tt>assignment in conditional context</tt> in
+case of</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>                      if (a = b)
+</pre>
+<!-- INDENTATION -->
+<p>The programmer probably meant <tt>if (a == b)</tt>. No
+warning should be given for <tt>if ((a = b) != c)</tt>, nor
+for <tt>if ((a = b))</tt>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Warnings for empty statements in strange contexts,
+like</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>               if (cond);  /* mistake */
+                       statement();
+</pre>
+<!-- INDENTATION -->
+<p>(This mistake would also be detected by a warning <tt>bad
+layout</tt>.)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>A mechanism to prevent the warning <tt>possible pointer
+alignment problem</tt> for functions of which the programmer
+already knows that no problem will arise. E.g. for functions
+like malloc and family.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&bull;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>The current version of <i>lint</i> warns for conversions
+from long to int (if -a flag is on). It even warns if the
+programmer used the proper cast, as e.g.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>                     int i;
+                     long l = 0L;
+
+
+                     i = (int)l;
+</pre>
+<!-- INDENTATION -->
+<p>In this case I think <i>lint</i> need not warn. The
+explicit cast indicates that the programmer knows what he is
+doing. This feature is not implemented because the
+expression tree doesn&rsquo;t show if the cast was implicit
+or explicit.</p>
+</td>
+</table>
+<a name="8. Testing the program"></a>
+<h2>8. Testing the program</h2>
+
+<p>There is no test-suite for testing <i>lint.</i> I have
+written a lot of small files that each test one particular
+property of the program. At this moment there are about 220
+test programs.</p>
+
+<p>It would take a lot of time and effort to run these
+tests by hand. To ease this work I wrote a program that runs
+these tests automatically. The test program (the program
+that runs the tests) needs, associated with each .c file, a
+.w file, containing from each expected warning a substring.
+E.g. when the following warnings should be given by
+<i>lint:</i></p>
+<pre>        file t.c, line 3, i evaluation order undefined
+        file t.c, line 6, a set but not used in function main
+</pre>
+
+<p>it is sufficient to write a file <tt>t.w</tt>
+containing</p>
+<pre>                a set but not used in function main
+                i evaluation order undefined
+</pre>
+
+<p>The test program is called with all the .c files to be
+tested as arguments.</p>
+
+<p>Sometimes it is necessary to test <i>lint</i> on two
+files. The test program runs <i>lint</i> on two files when
+two consecutive arguments are of the form <i>name</i>a.c and
+<i>name</i>b.c. It then compares the output of <i>lint</i>
+with the file <i>name</i>.w.</p>
+
+<p><i>Lint</i> is also tested by running it on existing
+programs. <i>Lint</i> has been run on some
+<small>UNIX</small> utility programs in /usr/src/cmd, on
+Unipress Emacs (consisting of more than 30,000 lines of
+code) and the program itself. Bugs have been found in e.g.
+/usr/src/cmd/cat.c and /usr/src/cmd/ld.c. To test the
+robustness of the program, it was run on the password file
+/etc/passwd and on &lsquo;mixed&rsquo; C program files.
+These mixed C program files are C program files that were
+broken in chunks and then put together in a different
+order.</p>
+<a name="9. References"></a>
+<h2>9. References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[1]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Dennis M. Ritchie, <i>C Reference Manual,</i> Bell
+Laboratories, Murray Hill, New Jersey, 1978.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[2]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>B.W. Kernighan and D.M. Ritchie, <i>The C Programming
+Language,</i> Prentice Hall, 1978.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[3]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Eric H. Baalbergen, Dick Grune, Maarten Waage, <i>The
+CEM Compiler,</i> Manual IM-4, Vrije Universiteit,
+Amsterdam, 1985.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[4]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Andrew S. Tanenbaum et al., <i>A practical tool kit for
+making portable compilers,</i> Comm. ACM, Sep. 1983.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[5]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>S. C. Johnson, <i>Lint, a C program verifier,</i> Bell
+Laboratories, Murray Hill, New Jersey, 1978.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[6]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Dick Grune, Ceriel J. H. Jacobs, <i>A
+Programmer-friendly LL(1) Parser Generator,</i> IR 127,
+Vrije Universiteit, Amsterdam, 1987.</p>
+</td>
+</table>
+<a name="Appendix A"></a>
+<h2>Appendix A</h2>
+<a name="The warnings"></a>
+<h2>The warnings</h2>
+<a name="Pass one warnings"></a>
+<h2>Pass one warnings</h2>
+<pre>     %s may be used before set
+     maybe %s used before set
+     %s unused in function %s
+     %s set but not used in function %s
+     argument %s unused in function %s
+     static [variable, function] %s unused
+     %s declared extern but never used
+
+
+     long conversion may lose accuracy
+     comparison of unsigned with negative constant
+     unsigned comparison with 0?
+     degenerate unsigned comparison
+     nonportable character comparison
+     possible pointer alignment problem
+
+
+     %s evaluation order undefined
+
+
+     null effect
+     constant in conditional context
+     use if-else construction
+     while (0) ?
+     do ... while (0) ?
+     [case, default] statement in strange context
+
+
+     function %s has return(e); and return;
+     statement not reached
+     function %s declared %s but no value returned
+</pre>
+<a name="Pass two warnings"></a>
+<h2>Pass two warnings</h2>
+<pre>     %s variable # of args
+     %s arg %d used inconsistently
+     %s multiply defined
+     %s value declared inconsistently
+     %s used but not defined
+     %s defined (%s(%d)) but never used
+     %s declared but never defined
+     %s value is used but none is returned
+     %s returns value which is [sometimes, always] ignored
+     %s also defined in library
+</pre>
+<a name="Appendix B"></a>
+<h2>Appendix B</h2>
+
+<p align=center><b><big>The Ten Commandments for C
+Programmers</big></b></p>
+
+<p align=center><i>Henry Spencer</i></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>1</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt run <i>lint</i> frequently and study its
+pronouncements with care, for verily its perception and
+judgement oft exceed thine.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>2</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt not follow the NULL pointer, for chaos and
+madness await thee at its end.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>3</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt cast all function arguments to the expected
+type if they are not of that type already, even when thou
+art convinced that this is unnecessary, lest they take cruel
+vengeance upon thee when thou least expect it.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>4</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>If thy header files fail to declare the return types of
+thy library functions, thou shalt declare them thyself with
+the most meticulous care, lest grievous harm befall thy
+program.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>5</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt check the array bounds of all strings
+(indeed, all arrays), for surely where thou typest
+&lsquo;&lsquo;foo&rsquo;&rsquo; someone someday shall type
+&lsquo;&lsquo;supercalifragilisticexpialidocious&rsquo;&rsquo;.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>6</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>If a function be advertised to return an error code in
+the event of difficulties, thou shalt check for that code,
+yea, even though the checks triple the size of thy code and
+produce aches in thy typing fingers, for if thou thinkest
+&lsquo;&lsquo;it cannot happen to me&rsquo;&rsquo;, the gods
+shall surely punish thee for thy arrogance.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>7</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt study thy libraries and strive not to
+re-invent them without cause, that thy code may be short and
+readable and thy days pleasant and productive.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>8</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thou shalt make thy program&rsquo;s purpose and
+structure clear to thy fellow man by using the One True
+Brace Style, even if thou likest it not, for thy creativity
+is better used in solving problems than in creating
+beautiful new impediments to understanding.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>9</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>Thy external identifiers shall be unique in the first
+six characters, though this harsh discipline be irksome and
+the years of its necessity stretch before thee seemingly
+without end, lest thou tear thy hair out and go mad on that
+fateful day when thou desirest to make thy program run on an
+old system.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>10</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>Thou shalt foreswear, renounce, and abjure the vile
+heresy which claimeth that &lsquo;&lsquo;All the
+world&rsquo;s a VAX&rsquo;&rsquo;, and have no commerce with
+the benighted heathens who cling to this barbarous belief,
+that the days of thy program may be long even though the
+days of thy current machine be short.</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/lint.pdf b/doc/tack/lint.pdf
new file mode 100644 (file)
index 0000000..342b0f6
Binary files /dev/null and b/doc/tack/lint.pdf differ
diff --git a/doc/tack/m2ref.html b/doc/tack/m2ref.html
new file mode 100644 (file)
index 0000000..f81f52e
--- /dev/null
@@ -0,0 +1,831 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:32 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The ACK Modula-2 Compiler</title>
+</head>
+<body>
+
+<h1 align=center>The ACK Modula-2 Compiler</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The language implemented">2. The language implemented</a><br>
+<a href="#2.1. Syntax (section 2)">2.1. Syntax (section 2)</a><br>
+<a href="#2.2. Vocabulary and Representation (section 3)">2.2. Vocabulary and Representation (section 3)</a><br>
+<a href="#2.3. Declarations and scope rules (section 4)">2.3. Declarations and scope rules (section 4)</a><br>
+<a href="#2.4. Constant expressions (section 5)">2.4. Constant expressions (section 5)</a><br>
+<a href="#2.5. Type declarations (section 6)">2.5. Type declarations (section 6)</a><br>
+<a href="#2.5.1. Basic types (section 6.1)">2.5.1. Basic types (section 6.1)</a><br>
+<a href="#2.5.2. Enumerations (section 6.2)">2.5.2. Enumerations (section 6.2)</a><br>
+<a href="#2.5.3. Record types (section 6.5)">2.5.3. Record types (section 6.5)</a><br>
+<a href="#2.5.4. Set types (section 6.6)">2.5.4. Set types (section 6.6)</a><br>
+<a href="#2.6. Expressions (section 8)">2.6. Expressions (section 8)</a><br>
+<a href="#2.6.1. Operators (section 8.2)">2.6.1. Operators (section 8.2)</a><br>
+<a href="#2.6.1.1. Arithmetic operators (section 8.2.1)">2.6.1.1. Arithmetic operators (section 8.2.1)</a><br>
+<a href="#2.7. Statements (section 9)">2.7. Statements (section 9)</a><br>
+<a href="#2.7.1. Assignments (section 9.1)">2.7.1. Assignments (section 9.1)</a><br>
+<a href="#2.7.2. Case statements (section 9.5)">2.7.2. Case statements (section 9.5)</a><br>
+<a href="#2.7.3. For statements (section 9.8)">2.7.3. For statements (section 9.8)</a><br>
+<a href="#2.7.4. Return and exit statements (section 9.11)">2.7.4. Return and exit statements (section 9.11)</a><br>
+<a href="#2.8. Procedure declarations (section 10)">2.8. Procedure declarations (section 10)</a><br>
+<a href="#2.8.1. Standard procedures (section 10.2)">2.8.1. Standard procedures (section 10.2)</a><br>
+<a href="#2.9. System-dependent facilities (section 12)">2.9. System-dependent facilities (section 12)</a><br>
+<a href="#3. Backwards compatibility">3. Backwards compatibility</a><br>
+<a href="#4. Compile time errors">4. Compile time errors</a><br>
+<a href="#5. Runtime errors">5. Runtime errors</a><br>
+<a href="#6. Calling the compiler">6. Calling the compiler</a><br>
+<a href="#7. The procedure call interface">7. The procedure call interface</a><br>
+<a href="#8. References">8. References</a><br>
+
+<hr>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p align=center><i>Ceriel J.H. Jacobs</i><br>
+Department of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam<br>
+The Netherlands</p>
+</td>
+</table>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>This document describes the implementation-specific
+features of the ACK Modula-2 compiler. It is not intended to
+teach Modula-2 programming. For a description of the
+Modula-2 language, the reader is referred to [1].</p>
+
+<p>The ACK Modula-2 compiler is currently available for use
+with the VAX, Motorola MC68020, Motorola MC68000, PDP-11,
+and Intel 8086 code-generators. For the 8086, MC68000, and
+MC68020, floating point emulation is used. This is made
+available with the <i>-fp</i> option, which must be passed
+to <i>ack</i>[4,5].</p>
+<a name="2. The language implemented"></a>
+<h2>2. The language implemented</h2>
+
+<p>This section discusses the deviations from the Modula-2
+language as described in the &quot;Report on The Programming
+Language Modula-2&quot;, as it appeared in [1], from now on
+referred to as &quot;the Report&quot;. Also, the Report
+sometimes leaves room for interpretation. The section
+numbers mentioned are the section numbers of the Report.</p>
+<a name="2.1. Syntax (section 2)"></a>
+<h2>2.1. Syntax (section 2)</h2>
+
+<p>The syntax recognized is that of the Report, with some
+extensions to also recognize the syntax of an earlier
+definition, given in [2]. Only one compilation unit per file
+is accepted.</p>
+<a name="2.2. Vocabulary and Representation (section 3)"></a>
+<h2>2.2. Vocabulary and Representation (section 3)</h2>
+
+<p>The input &quot;<tt>10..</tt>&quot; is parsed as two
+tokens: &quot;<tt>10</tt>&quot; and
+&quot;<tt>..</tt>&quot;.</p>
+
+<p>The empty string <tt>&quot;&quot;</tt> has type</p>
+<pre>     ARRAY [0 .. 0] OF CHAR
+</pre>
+
+<p>and contains one character: <tt>0C</tt>.</p>
+
+<p>When the text of a comment starts with a
+&rsquo;<tt>$</tt>&rsquo;, it may be a pragma. Currently, the
+following pragmas exist:</p>
+<pre>     (*$F      (F stands for Foreign) *)
+     (*$R[+|-] (Runtime checks, on or off, default on) *)
+     (*$A[+|-] (Array bound checks, on or off, default off) *)
+     (*$U      (Allow for underscores within identifiers) *)
+</pre>
+
+<p>The Foreign pragma is only meaningful in a
+<tt>DEFINITION MODULE</tt>, and indicates that this
+<tt>DEFINITION MODULE</tt> describes an interface to a
+module written in another language (for instance C, Pascal,
+or EM). Runtime checks that can be disabled are: range
+checks, <tt>CARDINAL</tt> overflow checks, checks when
+assigning a <tt>CARDINAL</tt> to an <tt>INTEGER</tt> and
+vice versa, and checks that <tt>FOR</tt>-loop
+control-variables are not changed in the body of the loop.
+Array bound checks can be enabled, because many EM
+implementations do not implement the array bound checking of
+the EM array instructions. When enabled, the compiler
+generates a check before generating an EM array instruction.
+Even when underscores are enabled, they still may not start
+an identifier.</p>
+
+<p>Constants of type <tt>LONGINT</tt> are integers with a
+suffix letter <tt>D</tt> (for instance <tt>1987D</tt>).
+Constants of type <tt>LONGREAL</tt> have suffix <tt>D</tt>
+if a scale factor is missing, or have <tt>D</tt> in place of
+<tt>E</tt> in the scale factor (f.i. <tt>1.0D</tt>,
+<tt>0.314D1</tt>). This addition was made, because there was
+no way to indicate long constants, and also because the
+addition was made in Wirth&rsquo;s newest Modula-2
+compiler.</p>
+<a name="2.3. Declarations and scope rules (section 4)"></a>
+<h2>2.3. Declarations and scope rules (section 4)</h2>
+
+<p>Standard identifiers are considered to be predeclared,
+and valid in all parts of a program. They are called
+<i>pervasive</i>. Unfortunately, the Report does not state
+how this pervasiveness is accomplished. However, page 87 of
+[1] states: &quot;Standard identifiers are automatically
+imported into all modules&quot;. Our implementation
+therefore allows redeclarations of standard identifiers
+within procedures, but not within modules.</p>
+<a name="2.4. Constant expressions (section 5)"></a>
+<h2>2.4. Constant expressions (section 5)</h2>
+
+<p>Each operand of a constant expression must be a
+constant: a string, a number, a set, an enumeration literal,
+a qualifier denoting a constant expression, a type transfer
+with a constant argument, or one of the standard procedures
+<tt>ABS</tt>, <tt>CAP</tt>, <tt>CHR</tt>, <tt>LONG</tt>,
+<tt>MAX</tt>, <tt>MIN</tt>, <tt>ODD</tt>, <tt>ORD</tt>,
+<tt>SIZE</tt>, <tt>SHORT</tt>, <tt>TSIZE</tt>, or
+<tt>VAL</tt>, with constant argument(s); <tt>TSIZE</tt> and
+<tt>SIZE</tt> may also have a variable as argument.</p>
+
+<p>Floating point expressions are never evaluated compile
+time, because the compiler basically functions as a
+cross-compiler, and thus cannot use the floating point
+instructions of the machine on which it runs. Also,
+<tt>MAX(REAL)</tt> and <tt>MIN(REAL)</tt> are not
+allowed.</p>
+<a name="2.5. Type declarations (section 6)"></a>
+<h2>2.5. Type declarations (section 6)</h2>
+<a name="2.5.1. Basic types (section 6.1)"></a>
+<h2>2.5.1. Basic types (section 6.1)</h2>
+
+<p>The type <tt>CHAR</tt> includes the ASCII character set
+as a subset. Values range from <tt>0C</tt> to <tt>377C</tt>,
+not from <tt>0C</tt> to <tt>177C</tt>.</p>
+<a name="2.5.2. Enumerations (section 6.2)"></a>
+<h2>2.5.2. Enumerations (section 6.2)</h2>
+
+<p>The maximum number of enumeration literals in any one
+enumeration type is <tt>MAX(INTEGER)</tt>.</p>
+<a name="2.5.3. Record types (section 6.5)"></a>
+<h2>2.5.3. Record types (section 6.5)</h2>
+
+<p>The syntax of variant sections in [1] is different from
+the one in [2]. Our implementation recognizes both, giving a
+warning for the older one. However, see section 3.</p>
+<a name="2.5.4. Set types (section 6.6)"></a>
+<h2>2.5.4. Set types (section 6.6)</h2>
+
+<p>The only limitation imposed by the compiler is that the
+base type of the set must be a subrange type, an enumeration
+type, <tt>CHAR</tt>, or <tt>BOOLEAN</tt>. So, the lower
+bound may be negative. However, if a negative lower bound is
+used, the compiler gives a warning of the <i>restricted</i>
+class (see the manual page of the compiler).</p>
+
+<p>The standard type <tt>BITSET</tt> is defined as</p>
+<pre>     TYPE BITSET = SET OF [0 .. 8*SIZE(INTEGER)-1];
+</pre>
+<a name="2.6. Expressions (section 8)"></a>
+<h2>2.6. Expressions (section 8)</h2>
+<a name="2.6.1. Operators (section 8.2)"></a>
+<h2>2.6.1. Operators (section 8.2)</h2>
+
+<a name="2.6.1.1. Arithmetic operators (section 8.2.1)"></a>
+<h2>2.6.1.1. Arithmetic operators (section 8.2.1)</h2>
+
+<p>The Report does not specify the priority of the unary
+operators <tt>+</tt> or <tt>-</tt>: It does not specify
+whether</p>
+<pre>     - 1 + 1
+</pre>
+
+<p>means</p>
+<pre>     - (1 + 1)
+</pre>
+
+<p>or</p>
+<pre>     (-1) + 1
+</pre>
+
+<p>I have seen some compilers that implement the first
+alternative, and others that implement the second. Our
+compiler implements the second, which is suggested by the
+fact that their priority is not specified, which might
+indicate that it is the same as that of their binary
+counterparts. And then the rule about left to right decides
+for the second. On the other hand one might argue that,
+since the grammar only allows for one unary operator in a
+simple expression, it must apply to the whole simple
+expression, not just the first term.</p>
+<a name="2.7. Statements (section 9)"></a>
+<h2>2.7. Statements (section 9)</h2>
+<a name="2.7.1. Assignments (section 9.1)"></a>
+<h2>2.7.1. Assignments (section 9.1)</h2>
+
+<p>The Report does not define the evaluation order in an
+assignment. Our compiler certainly chooses an evaluation
+order, but it is explicitly left undefined. Therefore,
+programs that depend on it may cease to work later.</p>
+
+<p>The types <tt>INTEGER</tt> and <tt>CARDINAL</tt> are
+assignment-compatible with <tt>LONGINT</tt>, and
+<tt>REAL</tt> is assignment-compatible with
+<tt>LONGREAL</tt>.</p>
+<a name="2.7.2. Case statements (section 9.5)"></a>
+<h2>2.7.2. Case statements (section 9.5)</h2>
+
+<p>The size of the type of the case-expression must be less
+than or equal to the word-size.</p>
+
+<p>The Report does not specify what happens if the value of
+the case-expression does not occur as a label of any case,
+and there is no <tt>ELSE</tt>-part. In our implementation,
+this results in a runtime error.</p>
+<a name="2.7.3. For statements (section 9.8)"></a>
+<h2>2.7.3. For statements (section 9.8)</h2>
+
+<p>The Report does not specify the legal types for a
+control variable. Our implementation allows the basic types
+(except <tt>REAL</tt>), enumeration types, and subranges. A
+runtime warning is generated when the value of the control
+variable is changed by the statement sequence that forms the
+body of the loop, unless runtime checking is disabled.</p>
+<a name="2.7.4. Return and exit statements (section 9.11)"></a>
+<h2>2.7.4. Return and exit statements (section 9.11)</h2>
+
+<p>The Report does not specify which result-types are
+legal. Our implementation allows any result type.</p>
+<a name="2.8. Procedure declarations (section 10)"></a>
+<h2>2.8. Procedure declarations (section 10)</h2>
+
+<p>Function procedures must exit through a RETURN
+statement, or a runtime error occurs.</p>
+<a name="2.8.1. Standard procedures (section 10.2)"></a>
+<h2>2.8.1. Standard procedures (section 10.2)</h2>
+
+<p>Our implementation supports <tt>NEW</tt> and
+<tt>DISPOSE</tt> for backwards compatibility, but issues
+warnings for their use. However, see section 3.</p>
+
+<p>Also, some new standard procedures were added, similar
+to the new standard procedures in Wirth&rsquo;s newest
+compiler:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><tt>LONG</tt> converts an argument of type
+<tt>INTEGER</tt> or <tt>REAL</tt> to the types
+<tt>LONGINT</tt> or <tt>LONGREAL</tt>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><tt>SHORT</tt> performs the inverse transformation,
+without range checks.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><tt>FLOATD</tt> is analogous to <tt>FLOAT</tt>, but
+yields a result of type <tt>LONGREAL</tt>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>&minus;</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><tt>TRUNCD</tt> is analogous to <tt>TRUNC</tt>, but
+yields a result of type <tt>LONGINT</tt>.</p>
+</td>
+</table>
+<a name="2.9. System-dependent facilities (section 12)"></a>
+<h2>2.9. System-dependent facilities (section 12)</h2>
+
+<p>The type <tt>BYTE</tt> is added to the <tt>SYSTEM</tt>
+module. It occupies a storage unit of 8 bits. <tt>ARRAY OF
+BYTE</tt> has a similar effect to <tt>ARRAY OF WORD</tt>,
+but is safer. In some obscure cases the <tt>ARRAY OF
+WORD</tt> mechanism does not quite work properly.</p>
+
+<p>The procedure <tt>IOTRANSFER</tt> is not
+implemented.</p>
+<a name="3. Backwards compatibility"></a>
+<h2>3. Backwards compatibility</h2>
+
+<p>Besides recognizing the language as described in [1],
+the compiler recognizes most of the language described in
+[2], for backwards compatibility. It warns the user for
+old-fashioned constructions (constructions that [1] does not
+allow). If the <i>-Rm2-3</i> option (see [6]) is passed to
+<i>ack</i>, this backwards compatibility feature is
+disabled. Also, it may not be present on some smaller
+machines, like the PDP-11.</p>
+<a name="4. Compile time errors"></a>
+<h2>4. Compile time errors</h2>
+
+<p>The compile time error messages are intended to be
+self-explanatory, and not listed here. The compiler also
+sometimes issues warnings, recognizable by a
+warning-classification between parentheses. Currently, there
+are 3 classifications:</p>
+
+<p>(old-fashioned use)</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>These warnings are given on constructions that are not
+allowed by [1], but are allowed by [2].</p>
+</td>
+</table>
+
+<p>(strict)</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>These warnings are given on constructions that are
+supported by the ACK Modula-2 compiler, but might not be
+supported by others. Examples: functions returning
+structured types, SET types of subranges with negative lower
+bound.</p>
+</td>
+</table>
+
+<p>(warning)</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The other warnings, such as warnings about variables that
+are never assigned, never used, etc.</p></td>
+</table>
+<a name="5. Runtime errors"></a>
+<h2>5. Runtime errors</h2>
+
+<p>The ACK Modula-2 compiler produces code for an EM
+machine as defined in [3]. Therefore, it depends on the
+implementation of the EM machine for detection some of the
+runtime errors that could occur.</p>
+
+<p>The <i>Traps</i> module enables the user to install his
+own runtime error handler. The default one just displays
+what happened and exits. Basically, a trap handler is just a
+procedure that takes an INTEGER as parameter. The INTEGER is
+the trap number. This INTEGER can be one of the EM trap
+numbers, listed in [3], or one of the numbers listed in the
+<i>Traps</i> definition module.</p>
+
+<p>The following runtime errors may occur:</p>
+
+<p>array bound error</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>range bound error</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Range bound errors are always detected, unless runtime
+checks are disabled.</p>
+</td>
+</table>
+
+<p>set bound error</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation. The current implementations detect this
+error.</p>
+</td>
+</table>
+
+<p>integer overflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>cardinal overflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error is detected, unless runtime checks are
+disabled.</p>
+</td>
+</table>
+
+<p>cardinal underflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error is detected, unless runtime checks are
+disabled.</p>
+</td>
+</table>
+
+<p>real overflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>real underflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>divide by 0</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>divide by 0.0</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>undefined integer</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>undefined real</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>conversion error</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error occurs when assigning a negative value of type
+INTEGER to a variable of type CARDINAL, or when assigning a
+value of CARDINAL that is &gt; MAX(INTEGER), to a variable
+of type INTEGER. It is detected, unless runtime checking is
+disabled.</p>
+</td>
+</table>
+
+<p>stack overflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation.</p>
+</td>
+</table>
+
+<p>heap overflow</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>The detection of this error depends on the EM
+implementation. Might happen when ALLOCATE fails.</p>
+</td>
+</table>
+
+<p>case error</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error occurs when non of the cases in a CASE
+statement are selected, and the CASE statement has no ELSE
+part. The detection of this error depends on the EM
+implementation. All current EM implementations detect this
+error.</p>
+</td>
+</table>
+
+<p>stack size of process too large</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This is most likely to happen if the reserved space for a
+coroutine stack is too small. In this case, increase the
+size of the area given to <tt>NEWPROCESS</tt>. It can also
+happen if the stack needed for the main process is too large
+and there are coroutines. In this case, the only fix is to
+reduce the stack size needed by the main process, f.i. by
+avoiding local arrays.</p>
+</td>
+</table>
+
+<p>too many nested traps + handlers</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error can only occur when the user has installed his
+own trap handler. It means that during execution of the trap
+handler another trap has occurred, and that several times.
+In some cases, this is an error because of overflow of some
+internal tables.</p>
+</td>
+</table>
+
+<p>no RETURN from function procedure</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error occurs when a function procedure does not
+return properly (&quot;falls&quot; through).</p>
+</td>
+</table>
+
+<p>illegal instruction</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>This error might occur when floating point operations are
+used on an implementation that does not have floating
+point.</p>
+</td>
+</table>
+
+<p>In addition, some of the library modules may give error
+messages. The <b>Traps</b>-module has a suitable mechanism
+for this.</p>
+<a name="6. Calling the compiler"></a>
+<h2>6. Calling the compiler</h2>
+
+<p>See [4,5,6] for a detailed explanation.</p>
+
+<p>The compiler itself has no version checking mechanism. A
+special linker would be needed to do that. Therefore, a
+makefile generator is included [7].</p>
+<a name="7. The procedure call interface"></a>
+<h2>7. The procedure call interface</h2>
+
+<p>Parameters are pushed on the stack in reversed order, so
+that the EM AB (argument base) register indicates the first
+parameter. For VAR parameters, its address is passed, for
+value parameters its value. The only exception to this rule
+is with conformant arrays. For conformant arrays, the
+address is passed, and an array descriptor is passed. The
+descriptor is an EM array descriptor. It consists of three
+fields: the lower bound (always 0), upper bound - lower
+bound, and the size of the elements. The descriptor is
+pushed first. If the parameter is a value parameter, the
+called routine must make sure that its value is never
+changed, for instance by making its own copy of the array.
+The Modula-2 compiler does exactly this.</p>
+
+<p>When the size of the return value of a function
+procedure is larger than the maximum of
+<tt>SIZE(LONGREAL)</tt> and twice the pointer-size, the
+caller reserves this space on the stack, above the
+parameters. Callee then stores its result there, and returns
+no other value.</p>
+<a name="8. References"></a>
+<h2>8. References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[1]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Niklaus Wirth, <i>Programming in Modula-2, third,
+corrected edition,</i> Springer-Verlag, Berlin (1985)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[2]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>Niklaus Wirth, <i>Programming in Modula-2,</i>
+Stringer-Verlag, Berlin (1983)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[3]</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren,
+E.G.Keizer, <i>Description of a machine architecture for use
+with block structured languages,</i> Informatica rapport
+IR-81, Vrije Universiteit, Amsterdam</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[4]</p>
+</td>
+<td width="4%"></td>
+<td width="36%">
+
+<p>UNIX manual <i>ack</i>(1)</p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[5]</p>
+</td>
+<td width="4%"></td>
+<td width="46%">
+
+<p>UNIX manual <i>modula-2</i>(1)</p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[6]</p>
+</td>
+<td width="4%"></td>
+<td width="40%">
+
+<p>UNIX manual <i>em_m2</i>(6)</p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[7]</p>
+</td>
+<td width="4%"></td>
+<td width="38%">
+
+<p>UNIX manual <i>m2mm</i>(1)</p>
+</td>
+<td width="51%">
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/m2ref.pdf b/doc/tack/m2ref.pdf
new file mode 100644 (file)
index 0000000..7514bd0
Binary files /dev/null and b/doc/tack/m2ref.pdf differ
diff --git a/doc/tack/m68020.html b/doc/tack/m68020.html
new file mode 100644 (file)
index 0000000..74117c0
--- /dev/null
@@ -0,0 +1,1772 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:30 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>A back end table for the Motorola MC68000, MC68010 and MC68020 microprocessors</title>
+</head>
+<body>
+
+<h1 align=center>A back end table for the Motorola MC68000, MC68010 and MC68020 microprocessors</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The MC68000 and MC68020 micro processors">2. The MC68000 and MC68020 micro processors</a><br>
+<a href="#2.1. Registers">2.1. Registers</a><br>
+<a href="#2.2. Addressing modes">2.2. Addressing modes</a><br>
+<a href="#2.2.1. General addressing modes">2.2.1. General addressing modes</a><br>
+<a href="#2.2.1.1. Register Direct Addressing">2.2.1.1. Register Direct Addressing</a><br>
+<a href="#2.2.1.2. Address Register Indirect">2.2.1.2. Address Register Indirect</a><br>
+<a href="#2.2.1.3. Address Register Indirect With Postincrement">2.2.1.3. Address Register Indirect With Postincrement</a><br>
+<a href="#2.2.1.4. Address Register Indirect With Predecrement">2.2.1.4. Address Register Indirect With Predecrement</a><br>
+<a href="#2.2.1.5. Address Register Indirect With Displacement">2.2.1.5. Address Register Indirect With Displacement</a><br>
+<a href="#2.2.1.6. Address Register Indirect With Index">2.2.1.6. Address Register Indirect With Index</a><br>
+<a href="#2.2.1.7. Absolute Data Addressing">2.2.1.7. Absolute Data Addressing</a><br>
+<a href="#2.2.1.8. Program Counter With Displacement.">2.2.1.8. Program Counter With Displacement.</a><br>
+<a href="#2.2.1.9. Program Counter With Index">2.2.1.9. Program Counter With Index</a><br>
+<a href="#2.2.1.10. Immediate Data">2.2.1.10. Immediate Data</a><br>
+<a href="#2.2.2. Extra MC68020 addressing modes">2.2.2. Extra MC68020 addressing modes</a><br>
+<a href="#2.2.2.1. Address Register Indirect With Index (Base Displacement)">2.2.2.1. Address Register Indirect With Index (Base Displacement)</a><br>
+<a href="#2.2.2.2. Memory Indirect Post-Indexed">2.2.2.2. Memory Indirect Post-Indexed</a><br>
+<a href="#2.2.2.3. Memory Indirect Pre-Indexed">2.2.2.3. Memory Indirect Pre-Indexed</a><br>
+<a href="#2.2.3. Addressing modes used in the table">2.2.3. Addressing modes used in the table</a><br>
+<a href="#3. The M68000 and MC68020 back end table">3. The M68000 and MC68020 back end table</a><br>
+<a href="#3.1. Constant Definitions">3.1. Constant Definitions</a><br>
+<a href="#3.2. Properties">3.2. Properties</a><br>
+<a href="#3.3. Registers">3.3. Registers</a><br>
+<a href="#3.4. Tokens">3.4. Tokens</a><br>
+<a href="#3.4.1. Token names">3.4.1. Token names</a><br>
+<a href="#3.4.2. Special tokens for the MC68000">3.4.2. Special tokens for the MC68000</a><br>
+<a href="#3.5. Sets">3.5. Sets</a><br>
+<a href="#3.6. Instructions">3.6. Instructions</a><br>
+<a href="#3.7. Moves">3.7. Moves</a><br>
+<a href="#3.8. Tests">3.8. Tests</a><br>
+<a href="#3.9. Stackingrules">3.9. Stackingrules</a><br>
+<a href="#3.10. Coercions">3.10. Coercions</a><br>
+<a href="#3.11. Patterns">3.11. Patterns</a><br>
+<a href="#3.11.1. Group 0: rules for register variables">3.11.1. Group 0: rules for register variables</a><br>
+<a href="#3.11.2. Groups 1 and 2: load and store instructions">3.11.2. Groups 1 and 2: load and store instructions</a><br>
+<a href="#3.11.3. Groups 3 and 4: integer and unsigned arithmetic">3.11.3. Groups 3 and 4: integer and unsigned arithmetic</a><br>
+<a href="#3.11.4. Group 5: floating point arithmetic">3.11.4. Group 5: floating point arithmetic</a><br>
+<a href="#3.11.5. Group 6: pointer arithmetic">3.11.5. Group 6: pointer arithmetic</a><br>
+<a href="#3.11.6. Group 9: logical instructions">3.11.6. Group 9: logical instructions</a><br>
+<a href="#3.11.7. Group 11: arrays">3.11.7. Group 11: arrays</a><br>
+<a href="#3.11.8. Group 14: procedure calls instructions">3.11.8. Group 14: procedure calls instructions</a><br>
+<a href="#3.11.9. Group 15: miscellaneous instructions">3.11.9. Group 15: miscellaneous instructions</a><br>
+<a href="#3.11.10. Extra group: optimalization">3.11.10. Extra group: optimalization</a><br>
+<a href="#4. The library routines">4. The library routines</a><br>
+<a href="#5. Testing the table">5. Testing the table</a><br>
+<a href="#6. Performance of the back end">6. Performance of the back end</a><br>
+<a href="#7. Some timing results">7. Some timing results</a><br>
+<a href="#8. Some final remarks">8. Some final remarks</a><br>
+<a href="#References">References</a><br>
+
+<hr>
+
+<p align=center><i><small>ABSTRACT</small></i></p>
+
+<p align=center><i><small>Frank Doodeman</small></i></p>
+
+<p><small>A back end table is part of the Amsterdam
+Compiler Kit (ACK). It is used to produce the actual back
+end, a program that translates the intermediate language
+family EM to assembly language for some target machine. The
+table discussed here can be used for two back ends, suitable
+for in total three machines: the MC68000 and MC68010 (the
+difference between these two is so small that one back end
+table can be used for either one), or for the
+MC68020.</small></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><small>To simplify the task of producing portable
+(cross) compilers and interpreters the Vrije Universiteit
+designed an integrated collection of programs, the Amsterdam
+Compiler Kit (ACK) [2]. It is based on the old UNCOL idea
+[1] which attempts to solve the problem of how to make a
+compiler for each of N languages on M different machines
+without having to write N&times;M programs.</small></p>
+
+<p><small>The UNCOL approach is to write N <i>front
+ends,</i> which translate the source language into a common
+intermediate language UNCOL (Universal Computer Oriented
+Language), and M <i>back ends,</i> each of which translates
+programs in UNCOL into a specific machine language. Under
+these conditions only M+N programs must be written to
+provide all N languages on all M machines, instead of
+M&times;N programs.</small></p>
+
+<p><small>The intermediate language for the Amsterdam
+Compiler Kit is the machine language for a simple stack
+machine called EM (Encoding Machine) [3]. So a back end for
+the MC68020 translates EM code into MC68020 assembly
+language. Writing such a table [4] suffices to get the back
+end.</small></p>
+
+<p><small>The back end is a single program that is driven
+by a machine dependent driving table. This table, the back
+end table, defines the mapping of EM code to the MC68000,
+MC68010 or MC68020 assembly language.</small></p>
+<a name="2. The MC68000 and MC68020 micro processors"></a>
+<h2>2. The MC68000 and MC68020 micro processors</h2>
+
+<p><small>In this document the name MC68000 will be used
+for both the MC68000 and the MC68010 micro processors,
+because as far as the back end table is concerned there is
+no difference between them. For a complete and detailed
+description of the MC68020 one is referred to [5]; for the
+MC68000 one might also use [6]. In this section some
+relevant parts will be handled.</small></p>
+<a name="2.1. Registers"></a>
+<h2>2.1. Registers</h2>
+
+<p><small>Both the MC68000 and the MC68020 have eight
+32-bit data registers (D <small><small>0</small></small> -D
+<small><small>7</small></small> ) that can be used for byte
+(8-bit), word (16-bit) and long word (32-bit) data
+operations. They also have seven 32-bit address registers (A
+<small><small>0</small></small> -A
+<small><small>6</small></small> ) that may be used as
+software stack pointers and base address registers; address
+register A <small><small>7</small></small> is used as the
+system stack pointer. Address registers may also be used for
+word and long word address operations.</small></p>
+<a name="2.2. Addressing modes"></a>
+<h2>2.2. Addressing modes</h2>
+
+<p><small>First the MC68000 addressing modes will be
+discussed. Since the MC68020&rsquo;s set of addressing modes
+is an extension of the MC68000&rsquo;s set, of course this
+section also applies to the MC68020.</small></p>
+
+<p><small>In the description we use:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%">
+
+<p><small>A <small><small>n</small></small></small></p>
+</td>
+<td width="6%"></td>
+<td width="42%">
+
+<p><small>for address register;</small></p>
+</td>
+<td width="48%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%">
+
+<p><small>D <small><small>n</small></small></small></p>
+</td>
+<td width="6%"></td>
+<td width="36%">
+
+<p><small>for data register;</small></p>
+</td>
+<td width="54%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%">
+
+<p><small>R <small><small>n</small></small></small></p>
+</td>
+<td width="6%"></td>
+<td width="58%">
+
+<p><small>for address or data register;</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%">
+
+<p><small>X <small><small>n</small></small></small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>for index register (either data or address
+register);</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>PC</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>for program counter;</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%">
+
+<p><small>d <small><small>8</small></small></small></p>
+</td>
+<td width="6%"></td>
+<td width="62%">
+
+<p><small>for 8 bit displacement integer;</small></p>
+</td>
+<td width="28%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>d <small><small>16</small></small></small></p>
+</td>
+<td width="4%"></td>
+<td width="64%">
+
+<p><small>for 16 bit displacement integer;</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>bd</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>for base displacement (may be null, word or
+long);</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>od</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>for outer displacement (may be null, word or
+long).</small></p>
+</td>
+</table>
+<a name="2.2.1. General addressing modes"></a>
+<h2>2.2.1. General addressing modes</h2>
+<a name="2.2.1.1. Register Direct Addressing"></a>
+<h2>2.2.1.1. Register Direct Addressing</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="3%">
+
+<p><small>R <small><small>n</small></small></small></p>
+</td>
+<td width="80%">
+</td>
+</table>
+
+<p><small>This addressing mode (it can be used with either
+a data register or an address register) specifies that the
+operand is in one of the 16 multifunction
+registers.</small></p>
+<a name="2.2.1.2. Address Register Indirect"></a>
+<h2>2.2.1.2. Address Register Indirect</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="7%">
+
+<p><small>(A <small><small>n</small></small> )</small></p>
+</td>
+<td width="76%">
+</td>
+</table>
+
+<p><small>The address of the operand is in the address
+register specified.</small></p>
+<a name="2.2.1.3. Address Register Indirect With Postincrement"></a>
+<h2>2.2.1.3. Address Register Indirect With Postincrement</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="9%">
+
+<p><small>(A <small><small>n</small></small> )+</small></p>
+</td>
+<td width="74%">
+</td>
+</table>
+
+<p><small>The address of the operand is in the address
+register specified. After the operand address is used, the
+address register is incremented by one, two or four
+depending upon whether the size of the operand is byte, word
+or long. If the address register is the stack pointer and
+the operand size is byte, the address register is
+incremented by two rather than one to keep the stack pointer
+on a word boundary.</small></p>
+<a name="2.2.1.4. Address Register Indirect With Predecrement"></a>
+<h2>2.2.1.4. Address Register Indirect With Predecrement</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="9%">
+
+<p><small>&minus;(A <small><small>n</small></small>
+)</small></p>
+</td>
+<td width="74%">
+</td>
+</table>
+
+<p><small>The address of the operand is in the address
+register specified. Before the operand address is used, the
+address register is decremented by one, two or four
+depending upon whether the size of the operand is byte, word
+or long. If the address register is the stack pointer and
+the operand size is byte, the address register is
+decremented by two rather than one to keep the stack pointer
+on a word boundary.</small></p>
+<a name="2.2.1.5. Address Register Indirect With Displacement"></a>
+<h2>2.2.1.5. Address Register Indirect With Displacement</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p><small>d <small><small>16</small></small> (A
+<small><small>n</small></small> ) for the MC68000, (d
+<small><small>16</small></small> ,A
+<small><small>n</small></small> ) for the
+MC68020</small></p>
+</td>
+</table>
+
+<p><small>This address mode requires one word of extension.
+The address of the operand is the sum of the contents of the
+address register and the sign extended 16-bit integer in the
+extension word.</small></p>
+<a name="2.2.1.6. Address Register Indirect With Index"></a>
+<h2>2.2.1.6. Address Register Indirect With Index</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p><small>d <small><small>8</small></small> (A
+<small><small>n</small></small> ,X
+<small><small>n</small></small> .size) for the MC68000, (d
+<small><small>8</small></small> ,A
+<small><small>n</small></small> ,X
+<small><small>n</small></small> .size) for the
+MC68020</small></p>
+</td>
+</table>
+
+<p><small>This address mode requires one word of extension
+according to a certain format, which specifies</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1.</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>which register to use as index
+register;</small></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a flag that indicates whether the index register
+is a data register or an address register;</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a flag that indicates the index size; this is
+<i>word</i> when the low order part of the index register is
+to be used, and <i>long</i> when the whole long value in the
+register is to be used as index;</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>an 8-bit displacement integer (the low order byte
+of the extension word).</small></p>
+</td>
+</table>
+
+<p><small>The address of the operand is the sum of the
+contents of the address register, the possibly sign extended
+contents of index register and the sign extended 8-bit
+displacement.</small></p>
+<a name="2.2.1.7. Absolute Data Addressing"></a>
+<h2>2.2.1.7. Absolute Data Addressing</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p><small>address for the MC68000, (address) for the
+MC68020</small></p>
+</td>
+</table>
+
+<p><small>Two different kinds of this mode are
+available:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Absolute Short Address; this mode requires one
+word of extension. The address of the operand is the sign
+extended 16-bit extension word.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Absolute Long Address; this mode requires two
+words of extension. The address of the operand is developed
+by concatenation of the two extension words; the high order
+part of the address is the first extension word, the low
+order part is the second.</small></p>
+</td>
+</table>
+<a name="2.2.1.8. Program Counter With Displacement."></a>
+<h2>2.2.1.8. Program Counter With Displacement.</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p><small>d <small><small>16</small></small> (PC) for the
+MC68000, (d <small><small>16</small></small> ,PC) for the
+MC68020</small></p>
+</td>
+</table>
+
+<p><small>This mode requires one word of extension. The
+address of the operand is the sum of the address in the
+program counter and the sign extended 16-bit displacement
+integer in the extension word. The value in the program
+counter is the address of the extension word.</small></p>
+<a name="2.2.1.9. Program Counter With Index"></a>
+<h2>2.2.1.9. Program Counter With Index</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p><small>d <small><small>8</small></small> (PC,X
+<small><small>n</small></small> .size) for the MC68000, (d
+<small><small>8</small></small> ,PC,X
+<small><small>n</small></small> .size) for the
+MC68020</small></p>
+</td>
+</table>
+
+<p><small>This mode requires one word of extension as
+described under <i>Address Register Indirect With Index.</i>
+The address of the operand is the sum of the value in the
+program counter, the possibly sign extended index register
+and the sign extended 8-bit displacement integer in the
+extension word. The value in the program counter is the
+address of the extension word.</small></p>
+<a name="2.2.1.10. Immediate Data"></a>
+<h2>2.2.1.10. Immediate Data</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="34%">
+
+<p><small>.if !r0x .nr 0x 0</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+
+<p><small>This addressing mode requires either one or two
+words of extension, depending on the size of the
+operation;</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>byte operation - the operand is in the low order
+byte of extension word;</small></p>
+<!-- INDENTATION -->
+<p><small>word operation - the operand is in the extension
+word;</small></p>
+<!-- INDENTATION -->
+<p><small>long operation - the operand is in the two
+extension words, the high order 16-bits are in the first
+extension word, the low order 16-bits in the
+second.</small></p></td>
+</table>
+<a name="2.2.2. Extra MC68020 addressing modes"></a>
+<h2>2.2.2. Extra MC68020 addressing modes</h2>
+
+<p><small>The MC68020 has three more addressing modes.
+These modes all use a displacement (some even two), an
+address register and an index register. Instead of the
+address register one may also use the program counter. Any
+of these may be omitted. If all addends are omitted the
+processor creates an effective address of zero. All of these
+three modes require at least one extension word, the <i>Full
+Format Extension Word,</i> which specifies:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1.</small></p>
+</td>
+<td width="6%"></td>
+<td width="64%">
+
+<p><small>the index register number (0-7);</small></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>the index register type (address or data
+register);</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>the size of the index (only low order part or the
+whole register)</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a scale factor. This is a number from 0 to 3
+which specifies how many bits the contents of the index
+register is to be shifted to the left before being used as
+an index;</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a flag that specifies whether the base (address)
+register is to be added or to be suppressed;</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>a flag that specifies whether to add or suppress
+the index operand;</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>two bits that specify the size of the base
+displacement (null, word or long);</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>8.</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>three bits that in combination with (6) above
+specify which of the three addressing modes (described
+below) to use and, if used, the size of the outer
+displacement (null, word or long).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>N.B.</small></p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p><small>All modes mentioned above for the MC68000 that
+use an index register may have this register scaled (only
+when using the MC68020).</small></p>
+</td>
+</table>
+
+<p><small>The three extra addressing modes are:</small></p>
+<a name="2.2.2.1. Address Register Indirect With Index (Base Displacement)"></a>
+<h2>2.2.2.1. Address Register Indirect With Index (Base Displacement)</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="70%">
+
+<p><small>(bd,A <small><small>n</small></small> ,X
+<small><small>n</small></small> .size*scale) (MC68020
+only)</small></p>
+</td>
+<td width="13%">
+</td>
+</table>
+
+<p><small>The address of the operand is the sum of the
+contents of the address register, the scaled contents of the
+possibly scaled index register and the possibly sign
+extended base displacement. When the program counter is used
+instead of the address register, the value in the program
+counter is the address of the full format extension word.
+This mode requires one or two more extension words when the
+size of the base displacement is word or long
+respectively.</small></p>
+
+<p><small>Note that without the index operand, this mode is
+an extension of the <i>Address Register Indirect With
+Displacement</i> mode; when using the MC68020 one is no
+longer limited to a 16-bit displacement. Also note that with
+the index operand added, this mode is an extension of the
+<i>Address Register Indirect With Index</i> mode; when using
+the MC68020 one is no longer limited to an 8-bit
+displacement.</small></p>
+<a name="2.2.2.2. Memory Indirect Post-Indexed"></a>
+<h2>2.2.2.2. Memory Indirect Post-Indexed</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p><small>([bd,A <small><small>n</small></small> ],X
+<small><small>n</small></small> .size*scale,od) (MC68020
+only)</small></p>
+</td>
+<td width="3%">
+</td>
+</table>
+
+<p><small>This mode may use an outer displacement. First an
+intermediate memory address is calculated by adding the
+contents of the address register and the possibly sign
+extended base displacement. This address is used for in
+indirect memory access of a long word, followed by adding
+the index operand (scaled and possibly signed extended).
+Finally the outer displacement is added to yield the address
+of the operand. When the program counter is used, the value
+in the program counter is the address of the full format
+extension word.</small></p>
+<a name="2.2.2.3. Memory Indirect Pre-Indexed"></a>
+<h2>2.2.2.3. Memory Indirect Pre-Indexed</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>Syntax:</small></p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p><small>([bd,A <small><small>n</small></small> ,X
+<small><small>n</small></small> .size*scale],od) (MC68020
+only)</small></p>
+</td>
+<td width="3%">
+</td>
+</table>
+
+<p><small>This mode may use an outer displacement. First an
+intermediate memory address is calculated by adding the
+contents of the address register, the scaled contents of the
+possibly sign extended index register and the possibly sign
+extended base displacement. This address is used for an
+indirect memory access of a long word, followed by adding
+the outer displacement to yield the address of the operand.
+When the program counter is used, the value in the program
+counter is the address of the full format extension
+word.</small></p>
+<a name="2.2.3. Addressing modes used in the table"></a>
+<h2>2.2.3. Addressing modes used in the table</h2>
+
+<p><small>Not all addressing modes mentioned above are used
+in code generation. It is clear that none of the modes that
+use the program counter PC can be used, since at code
+generation time nothing is known about the value in PC. Also
+some of the possibilities of the three MC68020 addressing
+modes are not used; e.g. it is possible to use a <i>Data
+Register Indirect</i> mode, which actually is the <i>Address
+Register Indirect With Index</i> mode, with the address
+register and the displacement left out. However such a mode
+would require two extra bytes for the full format extension
+word, and it would also be much slower than using <i>Address
+Register Indirect.</i> For this kind of reasons several
+possible addressing modes are not used in the generation of
+code. In the table address registers are only used for
+holding addresses, and for index registers only data
+registers are used.</small></p>
+<a name="3. The M68000 and MC68020 back end table"></a>
+<h2>3. The M68000 and MC68020 back end table</h2>
+
+<p><small>The table itself has to be run through the C
+preprocessor before it can be used to generate the back end
+(called <i>code generator</i> or <i>cg</i> for short). When
+no flags are given to the preprocessor an MC68020 code
+generator is produced; for the MC68000 code generator one
+has to run the table through the preprocessor using the
+<i>-Dm68k4</i> flag.</small></p>
+
+<p><small>The table is designed as described in [4]. For
+the overall design of a back end table one is referred to
+this document. This section only deals with problems
+encountered in writing the table and other things worth
+noting.</small></p>
+<a name="3.1. Constant Definitions"></a>
+<h2>3.1. Constant Definitions</h2>
+
+<p><small>Wordsize and pointersize (EM_WSIZE and EM_PSIZE
+respectively) are defined as four (bytes). EM_BSIZE, the
+hole between AB (the parameter base) and LB (the local
+base), is eight bytes: only the return address and the
+localbase are saved.</small></p>
+<a name="3.2. Properties"></a>
+<h2>3.2. Properties</h2>
+
+<p><small>Since Hans van Staveren in his document [4]
+clearly states that <i>cg</i> execution time is negatively
+influenced by the number of properties, only four different
+properties have been defined. Besides, since the registers
+really are multifunctional, these four are really all that
+are needed.</small></p>
+<a name="3.3. Registers"></a>
+<h2>3.3. Registers</h2>
+
+<p><small>The table uses register variables: D
+<small><small>3</small></small> - D
+<small><small>7</small></small> are used as general register
+variables, and address registers A
+<small><small>2</small></small> - A
+<small><small>5</small></small> are used as pointer register
+variables. A <small><small>6</small></small> is reserved for
+the localbase.</small></p>
+<a name="3.4. Tokens"></a>
+<h2>3.4. Tokens</h2>
+
+<p><small>At first glance one might wonder about the amount
+of tokens, especially for the MC68020, considering the small
+amount of different addressing modes. However, the last
+three addressing modes mentioned for the MC68020 may omit
+any of the addends, and this leads to a large amount of
+different tokens. I did consider the possibility of
+enlarging the number of tokens and sets even further,
+because there might be assemblers that don&rsquo;t handle
+displacements of zero optimally (they might generate a 2
+byte extension word holding zero). The small profit in bytes
+in the generated code however does not justify the increase
+in size of the token section, the set section and the
+patterns section, so this idea was not developed any
+further.</small></p>
+
+<p><small>The timing cost of the tokens may be incorrect
+for some MC68000 tokens. This is because the MC68000 uses a
+16-bit data bus which causes the need of two separate memory
+accesses for getting 32-bit operands.</small></p>
+<a name="3.4.1. Token names"></a>
+<h2>3.4.1. Token names</h2>
+
+<p><small>The amount of tokens and the limited capability
+of the authors imagination might have caused the names of
+some tokens not to be very clarifying. Some information
+about the names may be in place here.</small></p>
+
+<p><small>Whenever part of a token name is in capitals that
+part is memory indirected (i.e. in square brackets). In
+token names <i>OFF</i> and <i>off</i> mean an offsetted
+address register, so an address register with a displacement
+(either base displacement or outer displacement). <i>IND,
+ind</i> and <i>index</i> stand for indexed, or index
+register. <i>ABS</i> and <i>abs</i> stand for absolute,
+which actually is just a displacement (base or outer). These
+&lsquo;rules&rsquo; only apply to names of tokens that
+represent actual operands. There are also tokens that
+represent addresses of operands. These (with a few
+exceptions) contain <i>regA, regX</i> and <i>con</i> as
+parts of there names, which stand for address register,
+index register and displacement (always base displacement)
+respectively. If the address to which the token refers uses
+memory indirection, that part of the name comes first (in
+small letters), followed by an underscore. The memory
+indirection part follows the &lsquo;rules&rsquo; for operand
+token names.</small></p>
+
+<p><small>Of course there are exceptions to these
+&lsquo;rules&rsquo; but in those cases the names are self
+explanatory.</small></p>
+
+<p><small>Two special cases: <i>ext_regX</i> is the name of
+the token that represents the address of an absolute indexed
+operand, syntax (bd,X <small><small>n</small></small>
+.size*scale); <i>regX</i> does not represent any real mode,
+but is used with EM array instructions and pointer
+arithmetic.</small></p>
+<a name="3.4.2. Special tokens for the MC68000"></a>
+<h2>3.4.2. Special tokens for the MC68000</h2>
+
+<p><small>The MC68000 requires two extra tokens, which are
+called <i>t_regAcon</i> and <i>t_regAregXcon.</i> They are
+necessary because <i>regAcon</i> can only have a 16-bit
+displacement on the MC68000, and <i>regAregXcon</i> uses
+only 8 bits for its displacement. To prevent these
+addressing modes to be used with displacements that are too
+large, the extra tokens are needed. Whenever the
+displacements become too large and they need to be used in
+the generation of assembly code, these tokens are
+transformed into other tokens. To prevent the table from
+becoming too messy I defined <i>t_regAcon</i> and
+<i>t_regAregXcon</i> to be identical to <i>regAcon</i> and
+<i>regAregXcon</i> respectively for the MC68020.</small></p>
+<a name="3.5. Sets"></a>
+<h2>3.5. Sets</h2>
+
+<p><small>Most set names used in the table are self
+explanatory, especially to the reader who is familiar with
+the four addressing categories as mentioned in [5]: <i>data,
+memory, alterable</i> and <i>control.</i> In the sets
+definition part some sets are defined that are not used
+elsewhere in the table, but are only used to be part of the
+definition of some other set. This keeps the set definition
+part from getting too unreadable.</small></p>
+
+<p><small>The sets called <i>imm_cmp</i> consist of all
+tokens that can be used to compare with a
+constant.</small></p>
+<a name="3.6. Instructions"></a>
+<h2>3.6. Instructions</h2>
+
+<p><small>Only the instructions that are used in code
+generation are listed here. The first few instructions are
+meant especially for the use with register variables. The
+operand LOCAL used here refers to a register variable. The
+reader may not conclude that these operations are also
+allowed on ordinary locals. The space and timing cost of
+these instructions have been adapted, but the use of the
+word LOCAL for register variables causes these cost to be
+inaccurate anyway.</small></p>
+
+<p><small>The <i>killreg</i> instruction, which generates a
+comment in the assembly language output and which is meant
+to let <i>cg</i> know that the data register operand has its
+contents destroyed, needs some explaining but this
+explanation is better in place in the discussion of groups 3
+and 4 of the section about patterns.</small></p>
+
+<p><small>The timing cost of the instructions are probably
+not very accurate for the MC68020 because the MC68020 uses
+an instruction cache and prefetch. The cost used in the
+table are the &lsquo;worst case cost&rsquo; as mentioned in
+section 9 of [5].</small></p>
+<a name="3.7. Moves"></a>
+<h2>3.7. Moves</h2>
+
+<p><small>These are all pretty straightforward, except
+perhaps when <i>t_regAcon</i> and <i>t_regAregXcon</i> are
+used. In these cases the size of the displacement has to be
+checked before moving. This also applies to the stacking
+rules and the coercions.</small></p>
+<a name="3.8. Tests"></a>
+<h2>3.8. Tests</h2>
+
+<p><small>These three tests (one fore each operation size)
+could not be more straightforward than they are
+now.</small></p>
+<a name="3.9. Stackingrules"></a>
+<h2>3.9. Stackingrules</h2>
+
+<p><small>The only peculiar stackingrule is the one for
+<i>regX.</i> This token is only used with EM array
+instructions and with pointer arithmetic. Whenever it is put
+on the fake stack, some EM instructions are left in the
+instruction stream to remove this token. Consequently it
+should never have to be stacked. However the <i>code
+generator generator</i> (or <i>cgg</i> for short) complained
+about not having a stackingrule for this token, so it had to
+be added nevertheless.</small></p>
+<a name="3.10. Coercions"></a>
+<h2>3.10. Coercions</h2>
+
+<p><small>These are all straightforward. There are no
+splitting coercions since the fake stack never contains any
+tokens that can be split. There are only two unstacking
+coercions. The rest are all transforming coercions. Almost
+all coercions transform tokens into either a data register
+or an address register, except in the MC68000 part of the
+table the <i>t_regAcon</i> and <i>t_regAregXcon</i> tokens
+are transformed into real <i>regAcon</i> and
+<i>regAregXcon</i> tokens with displacements that are
+properly sized.</small></p>
+<a name="3.11. Patterns"></a>
+<h2>3.11. Patterns</h2>
+
+<p><small>This is the largest part of the table. It is
+subdivided into 17 groups. We will take a closer look at the
+more interesting groups.</small></p>
+<a name="3.11.1. Group 0: rules for register variables"></a>
+<h2>3.11.1. Group 0: rules for register variables</h2>
+
+<p><small>This group makes sure that EM instructions using
+register variables are handled efficiently. This group
+includes: local loads and stores; arithmetic, shifts and
+logical operations on locals and indirect locals and pointer
+handling, where C expressions like <i>*cp++</i> are handled.
+For such an expression there are several EM instruction
+sequences the front end might generate. For an integer
+pointer e.g.:</small></p>
+<pre><small><b>     lol lol adp stl loi $1==$2 &amp;&amp; $1==$4 &amp;&amp; $3==4 &amp;&amp; $5==4
+</b></small></pre>
+
+<p><small>or</small></p>
+<pre><small><b>     lol loi lol adp stl $1==$3 &amp;&amp; $3==$5 &amp;&amp; $2==4 &amp;&amp; $5==4
+</b></small></pre>
+
+<p><small>or perhaps even</small></p>
+<pre><small><b>     lil lol adp stl $1==$2 &amp;&amp; $2==$4 &amp;&amp; $3==4
+</b></small></pre>
+
+<p><small>Each of these is included, since which one is
+generated is is up to the front end. If the front end is
+consistent this will mean that some of these patterns will
+never be used in code generation. This might seem a waist,
+but anyone who thinks that will certainly change his mind
+when his new C front end generates a different EM
+instruction sequence.</small></p>
+<a name="3.11.2. Groups 1 and 2: load and store instructions"></a>
+<h2>3.11.2. Groups 1 and 2: load and store instructions</h2>
+
+<p><small>In these groups <b>lof</b> and <b>stf</b> ,
+<b>loi</b> and <b>sti</b> , <b>ldf</b> and <b>sdf</b> are
+the important instructions. These are the large parts in
+this group, especially the <b>loi</b> and <b>sti</b>
+instructions, because they come in three basic sizes (byte,
+word and long). Note that with these instructions in the
+MC68000 part the <i>exact</i> is omitted in front of
+<i>regAcon</i> and <i>regAregXcon.</i> This makes sure that
+<i>t_regAcon</i> and <i>t_regAregXcon</i> are transformed
+into proper tokens before they are used as
+addresses.</small></p>
+
+<p><small>Also note that the <i>regAregXcon</i> token is
+completely left out from the <b>lof</b>, <b>stf</b>,
+<b>ldf</b> and <b>sdf</b> instruction handling. This is
+because the sum of the token displacement and the offset
+provided in the instruction cannot be checked and is likely
+to exceed 8 bits. Unfortunately <i>cgg</i> does not allow
+the inspection of subregisters of tokens that are on the
+fake stack. This same problem might also occur with the
+<i>regAcon</i> token, but this is less likely because it
+uses 16-bit displacements. Besides if it would have been
+left out the <b>lof</b>, <b>stf</b>, <b>ldf</b> and
+<b>sdf</b> instructions would have been handled considerably
+less efficient.</small></p>
+<a name="3.11.3. Groups 3 and 4: integer and unsigned arithmetic"></a>
+<h2>3.11.3. Groups 3 and 4: integer and unsigned arithmetic</h2>
+
+<p><small>EM instruction <b>sbi</b> also works with address
+registers, because the <b>cmp</b> instruction in group 12 is
+replaced by <b>sbi 4</b>.</small></p>
+
+<p><small>For the MC68000 <b>mli</b>, <b>mlu</b>,
+<b>dvi</b>, <b>dvu</b>, <b>rmi</b> and <b>rmu</b> are
+handled by library routines. This is because the MC68000 has
+only 16-bit multiplications and divisions.</small></p>
+
+<p><small>The MC68020 does have 32-bit multiplications and
+divisions, but for the <b>rmi</b> and <b>rmu</b> EM
+instructions peculiar things happen anyway: they generate
+the <i>killreg</i> instruction. This is necessary because
+the data register that first held the dividend now holds the
+quotient; the original contents are destroyed without
+<i>cg</i> knowing about it (the destruction of the two
+registers that make up the <i>DREG_pair</i> token
+couldn&rsquo;t be noted in the instructions part of the
+table). To let <i>cg</i> know that these contents are
+destroyed, we have to use this &lsquo;pseudo
+instruction&rsquo; from lack of a better
+solution.</small></p>
+<a name="3.11.4. Group 5: floating point arithmetic"></a>
+<h2>3.11.4. Group 5: floating point arithmetic</h2>
+
+<p><small>Since floating point arithmetic is not
+implemented traps will be generated here.</small></p>
+<a name="3.11.5. Group 6: pointer arithmetic"></a>
+<h2>3.11.5. Group 6: pointer arithmetic</h2>
+
+<p><small>This also is a very important group, along with
+groups 1 and 2. The MC68020 has many different addressing
+modes and if possible they should be used in the generation
+of assembly language.</small></p>
+
+<p><small>The <i>regX</i> token is generated here too. It
+is meant to make efficient use of the MC68020 possibility of
+scaling index registers.</small></p>
+
+<p><small>Note that I would have liked one extra pattern to
+handle C-statements like</small></p>
+<pre><small><i>     pointer += expr ? constant1 : constant2;
+</i></small></pre>
+
+<p><small>efficiently. This pattern would have looked
+like:</small></p>
+<pre><small>     pat ads
+     with const
+     leaving adp %1.num
+</small></pre>
+
+<p><small>but when <i>cg</i> is coming to the EM
+replacement part, the constant has already been removed from
+the fake stack, causing <i>%1.num</i> to have a wrong
+value.</small></p>
+<a name="3.11.6. Group 9: logical instructions"></a>
+<h2>3.11.6. Group 9: logical instructions</h2>
+
+<p><small>The EM instructions <b>and</b>, <b>ior</b> and
+<b>xor</b> are so much alike that procedures can be used
+here, except for the <b>xor $1==4</b> instruction, because
+the MC68000 <i>eor</i> instruction does not allow as many
+kinds of operands as <i>and</i> and <i>or.</i></small></p>
+<a name="3.11.7. Group 11: arrays"></a>
+<h2>3.11.7. Group 11: arrays</h2>
+
+<p><small>This group also tries to make efficient use of
+the available addressing modes, but it leaves the actual
+work to group 6 mentioned above.</small></p>
+
+<p><small>The <i>regX</i> token is also generated here. In
+this group this token is very useful for handling array
+instructions for arrays with one, two, four or eight byte
+elements; the array index goes into the index register,
+which can then be scaled appropriately. An offset is used
+when the first array element has an index other than
+zero.</small></p>
+
+<p><small>I would have liked some extra patterns here too
+but they won&rsquo;t work for the same reasons as explained
+in the discussion of group 6.</small></p>
+<a name="3.11.8. Group 14: procedure calls instructions"></a>
+<h2>3.11.8. Group 14: procedure calls instructions</h2>
+
+<p><small>The function return area consists of registers D
+<small><small>0</small></small> and D
+<small><small>1</small></small> .</small></p>
+<a name="3.11.9. Group 15: miscellaneous instructions"></a>
+<h2>3.11.9. Group 15: miscellaneous instructions</h2>
+
+<p><small>In many cases here library routines are called.
+These will be discussed later.</small></p>
+
+<p><small>Two special EM instructions are included here:
+<b>dch</b>, and <b>lpb</b>. I don&rsquo;t know when they are
+generated by a front end, but these instructions were also
+in the back end table for the PDP. In the PDP table these
+instructions were replaced by <b>loi 4</b> and <b>adp 8</b>
+respectively. I included them both, since they
+couldn&rsquo;t do any harm.</small></p>
+<a name="3.11.10. Extra group: optimalization"></a>
+<h2>3.11.10. Extra group: optimalization</h2>
+
+<p><small>This group is handling EM patterns with more than
+one instruction. This group is not absolutely necessary but
+it makes the generation of code more efficient. Among the
+things that are handled here are: arithmetic and logical
+operations on locals, externals and indirect locals;
+shifting of locals, externals and indirect locals by one;
+some pointer arithmetic; tests in combination with logical
+and&rsquo;s and or&rsquo;s or with branches. Finally there
+are sixteen patterns about divisions that could be handled
+more efficiently by right shifts and which I think should be
+handled by the peephole optimizer (since it also handles the
+same patterns with multiplication).</small></p>
+<a name="4. The library routines"></a>
+<h2>4. The library routines</h2>
+
+<p><small>The table is supplied with two separate
+libraries: one for the MC68000 and one for the MC68020. The
+MC68000 uses a couple more routines than the MC68020 because
+it doesn&rsquo;t have 32-bit division and
+multiplication.</small></p>
+
+<p><small>The routines that need to pop their operands
+first store their return address. Routines that need other
+register besides D <small><small>0</small></small> -D
+<small><small>2</small></small> and A
+<small><small>0</small></small> -A
+<small><small>1</small></small> first store the original
+contents of those registers. D
+<small><small>0</small></small> -D
+<small><small>2</small></small> and A
+<small><small>0</small></small> -A
+<small><small>1</small></small> do not have to be saved
+because if they contain anything useful, their contents are
+pushed on the stack before the routine is
+called.</small></p>
+
+<p><small>The <i>.trp</i> routine just prints a message
+stating the trap number and exits (except of course when
+that particular trap number is masked). Usually higher level
+languages use their own trap handling routines.</small></p>
+
+<p><small>The <i>.mon</i> routine doesn&rsquo;t do anything
+useful at all. It just prints a message stating that the
+specified system call is not implemented and then exits.
+Front ends usually generate calls to special routines rather
+than the EM instruction <b>mon</b>. These routines have to
+be supplied in another library. They may be system dependent
+(e.g. the MC68000 machine this table was tested on first
+moves the parameters to registers, then moves the system
+call number to D <small><small>0</small></small> and then
+executes <i>trap #0,</i> whereas the MC68020 machine this
+table was tested on required the parameters to be on the
+stack rather than in registers). Therefor this library is
+not discussed here.</small></p>
+
+<p><small>The <i>.printf</i> routine is included for EM
+diagnostic messages. It can print strings using %s, 16-bit
+decimal numbers using %d and 32-bit hexadecimal numbers
+using %x.</small></p>
+
+<p><small>The <i>.strhp</i> routine stores a new EM heap
+pointer, and sometimes it needs to allocate more heap space.
+This is done by calling the system call routine <i>_brk</i>.
+Chunks of 1K bytes are allocated, but this can easily be
+changed into larger or smaller chunks.</small></p>
+
+<p><small>The MC68000 library also contains a routine to
+handle the EM instruction <b>rck</b>. The MC68020 has an
+instruction <i>cmp2</i> that is specially meant for range
+checking so the MC68020 library can do without that
+routine.</small></p>
+
+<p><small>The MC68000 library has two multiplication
+routines, one for unsigned and the other for signed
+multiplication. The one for signed multiplication first
+tests the sizes of the operands, to see if it can perform
+the 16 bit machine instruction instead of the routine. If
+not, it considers it&rsquo;s two operands being two digit
+numbers in a 65535-radix system. It uses the 16-bit unsigned
+multiply instruction <i>mulu</i> three times (it does not
+calculate the high order result), and adds up the
+intermediary results the proper way. The signed
+multiplication routine calculates the sign of the result,
+calculates the result as it it were an unsigned
+multiplication, and adjusts the sign of the result. Here
+testing the operands for there sizes would be less simple,
+because the operands are signeds; so that is not done
+here.</small></p>
+
+<p><small>The MC68000 library also has two division
+routines. The routine for unsigned division uses the popular
+algorithm, where the divisor is shifted out and the quotient
+shifted in. The signed division routine calculates the sign
+of both the quotient and the remainder, calls the unsigned
+division routine and adjusts the signs for the quotient and
+the remainder.</small></p>
+
+<p><small>The <i>.nop</i> routine is included for testing
+purposes. This routine prints the line number and the value
+in the stack pointer. Calls to this routine are generated by
+the EM instruction <b>nop</b>, which is ordinarily left out
+by the peephole optimizer.</small></p>
+<a name="5. Testing the table"></a>
+<h2>5. Testing the table</h2>
+
+<p><small>There are special test programs available for
+testing back end tables. First there is the EM test set,
+which tests most EM instructions, making good use of the
+<b>nop</b> instruction. Then there are the Pascal and C test
+programs. The Pascal test programs report errors, which
+makes it relatively easy to find out what was wrong in the
+table. The C test programs just generate some output, which
+then has to be compared to the expected output. Differences
+are not only caused by errors but also e.g. by the use of
+four byte integers and unsigneds (which this table does),
+the use of signed characters instead of unsigned characters
+(the C front end I used generated signed characters) or
+because the back end does not support floating point. These
+differences have to be &lsquo;filtered out&rsquo; to reveal
+the differences caused by actual errors in the back end
+table. These errors then have to be found out by examining
+the assembly code, for no proper diagnostic messages are
+generated.</small></p>
+
+<p><small>After these three basic tests there still remain
+a number of patterns that haven&rsquo;t been tested yet.
+Fortunately <i>cgg</i> offers the possibility of generating
+a special <i>cg</i> that can print a list of patterns that
+haven&rsquo;t been used in code generation yet. For these
+patterns the table writer has to write his own test
+programs. This may complicate things a bit because errors
+may now be caused by errors in the back end table as well as
+errors in the test programs. The latter happened quite often
+to me, because I found EM to be an uncomfortable programming
+language (of course it isn&rsquo;t meant to be a programming
+language, but an intermediary language).</small></p>
+
+<p><small>There still remain a couple of patterns in this
+table that haven&rsquo;t been tested yet. However these
+patterns all have very similar cases that have been tested
+(an example of this is mentioned in the section on group 0
+of the patterns section of the table). Some patterns have to
+do with floating point numbers. These EM instructions all
+generate traps, so they didn&rsquo;t all have to be tested.
+The two instructions <b>dch</b> and <b>lpb</b> haven&rsquo;t
+been tested in this table, but since they only use EM
+replacement and they have been tested in the PDP back end
+table, these two should be all right.</small></p>
+<a name="6. Performance of the back end"></a>
+<h2>6. Performance of the back end</h2>
+
+<p><small>To test the performance of the back end I
+gathered a couple of C programs and compiled them on the
+machines I used to test the back ends on. I compiled them
+using the C compiler that was available there and I also
+compiled them using the back end. I then compared the sizes
+of the text segments in the object files. The final results
+of these comparisons are in fig. 1 and fig. 2.</small></p>
+
+
+<p align=center><small><img src="grohtml-105631.png"></small></p>
+
+<p align=center><small>fig 1.</small></p>
+
+
+<p align=center><small><img src="grohtml-105632.png"></small></p>
+
+<p align=center><small>fig 2.</small></p>
+
+<p><small>Fig. 1 also includes results of an old m68k4 back
+end (a back end for the MC68000 with four byte word and
+pointersize). The table for this back end was given to me as
+an example, but I thought it didn&rsquo;t make good use of
+the MC68000&rsquo;s addressing capabilities, it hardly did
+any optimalization, and it sometimes even generated code
+that the assembler would not swallow. This was sufficient
+reason for me to write a completely new table.</small></p>
+
+<p><small>The results from the table may not be taken too
+seriously. The sizes measured are the sizes of the text
+segments of the user programs, i.e. without the inclusion of
+library routines. Of course these segments do contain calls
+to these routines. Another thing is that the <i>rom</i>
+segment may be included in the text segment (this is why the
+results for the MC68000 for <i>compute.c</i> look so
+bad).</small></p>
+
+<p><small>Some other things must be said about these
+results. The quality of EM code generated by the C front end
+is certainly not optimal. The front end uses temporary
+locals (extra locals that are used to evaluate expressions)
+far too quickly: for a simple C expression like</small></p>
+<pre><small><i>     *(pointer) += constant
+</i></small></pre>
+
+<p><small>where <i>pointer</i> is a register variable, the
+C front end generates (for obscure reasons) a temporary
+local that holds the contents of <i>pointer</i>. This way
+the pattern for</small></p>
+<pre><small><b>     loc lil adi sil $2==$4 &amp;&amp; $3==4
+</b></small></pre>
+
+<p><small>for register variables is not used and longer,
+less efficient code is generated. But even in spite of this,
+the back end seems to generate rather compact
+code.</small></p>
+<a name="7. Some timing results"></a>
+<h2>7. Some timing results</h2>
+
+<p><small>In order to measure the performance of the code
+generated by the back end some timing tests were done. The
+reason I chose these particular tests is that they were also
+done for many other back ends; the reader can compare the
+results if he so wishes (of course comparing the results
+only show a global difference in speed of the various
+machines; it doesn&rsquo;t show whether some back end
+generates relatively better code than another).</small></p>
+
+<p><small>On the MC68000 machine the statements were
+executed one million times. On the MC68020 machine the
+statements had to be executed four million times because
+this machine was so fast that timing results would be very
+unreliable if the statements were executed only one million
+times.</small></p>
+
+<p><small>For testing I used the following C test
+program:</small></p>
+<pre><small><i>     main()
+     {
+         int i, j, ...
+         ...
+         for (i=0; i&lt;1000; i++)
+             for (j=0; j&lt;1000; j++)
+</i></small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small><i>STATEMENT;</i></small></p>
+</table>
+
+<p><small><i>}</i></small></p>
+
+<p><small>where <i>STATEMENT</i> is any of the test
+statements or the empty statement. For the MC68020 tests I
+used 2000 instead of 1000. The results of the test with the
+empty statement were used to calculate the execution times
+of the other test statements.</small></p>
+
+<p><small>Figures 3 and 4 show many results. For each
+machine actually two tests were done: one with register
+variables, and the other without them. I noticed that the
+original C compilers on both machines did not generate the
+use of register variables, unless specifically requested.
+The back end uses register variables when and where they are
+profitable, even if the user did not ask for
+them.</small></p>
+
+
+<p align=center><small><img src="grohtml-105633.png"></small></p>
+
+<p align=center><small>Fig. 3</small></p>
+
+
+<p align=center><small><img src="grohtml-105634.png"></small></p>
+
+<p align=center><small>Fig. 4</small></p>
+
+<p><small>The reader may have noticed that on both machines
+the back end seems to generate considerably slower code for
+tests where a &lsquo;condition&rsquo; is used in the rhs of
+an assignment statement. This is in fact not true: it is the
+front end that generates bad code. Two examples: for the C
+statement</small></p>
+<pre><small><i>     int1 = (int2 &lt; 0);
+</i></small></pre>
+
+<p><small>the front end generates the following code for
+the rhs (I used arbitrary labels):</small></p>
+<pre><small><b>     lol -16
+     zlt *10
+     loc 0
+     bra *11
+     10
+     loc 1
+     11
+</b></small></pre>
+
+<p><small>while in this case (to my opinion) it should have
+generated</small></p>
+<pre><small><b>     lol -16
+     tlt
+</b></small></pre>
+
+<p><small>which is much shorter. Another example: for the C
+statement</small></p>
+<pre><small><i>     int1 = (int2 &lt; 3);
+</i></small></pre>
+
+<p><small>the front end generates for the rhs</small></p>
+<pre><small><b>     lol -16
+     loc 3
+     blt *10
+     loc 0
+     bra *11
+     10
+     loc 1
+     11
+</b></small></pre>
+
+<p><small>while a much better translation would
+be</small></p>
+<pre><small><b>     lol -16
+     loc 3
+     cmi 4
+     tlt
+</b></small></pre>
+
+<p><small>Another statement that the back end seems to
+generate slower code for is the C switch statement. This is
+true, but it is also caused by the way these things are done
+in EM. EM uses the <b>csa</b> or <b>csb</b> instruction, and
+for these two I had to use library routines. On larger
+switch statements the <i>.csa</i> routine will perform
+relatively better.</small></p>
+
+<p><small>The back end generates considerably faster code
+for procedure and function calls, especially in the MC68020
+case, and also for the C statement</small></p>
+<pre><small><i>     int1 = int1 + 1;
+</i></small></pre>
+
+<p><small>The original C compilers use the same method for
+this instruction as for</small></p>
+<pre><small><i>     int1 = int2 - 1;
+</i></small></pre>
+
+<p><small>they perform the addition in a scratch register,
+and then store the result. For the former C statement this
+is not necessary, because the MC68000 and MC68020 have an
+instruction that can add constants to almost anything (in
+this case: to locals). The MC68000 and MC68020 back ends do
+use this instruction.</small></p>
+<a name="8. Some final remarks"></a>
+<h2>8. Some final remarks</h2>
+
+<p><small>As mentioned a few times before, the C front end
+compiler does not generate optimal code and as a consequence
+of this the back end does not always generate optimal code.
+This is especially the case with temporary locals, which the
+front end generates much too quickly, and also with
+conditional expressions that are used in the rhs of an
+assignment statement (fortunately this is not needed so
+much).</small></p>
+
+<p><small>If <i>cgg</i> would have been able to accept
+operands separated by any character instead of just by
+commas (in the instruction definitions part), I
+wouldn&rsquo;t have had the need of the <i>killreg</i>
+pseudo instruction. It would also be handy to have
+<i>cgg</i> accept all normal C operators. At the moment
+<i>cgg</i> does not accept binary ands, ors and exors, even
+though in [4] it is stated that <i>cgg</i> does accept all
+normal C operators. As it happens I did not need the binary
+operators, but at some time in developing the table I
+thought I did.</small></p>
+
+<p><small>I would also like <i>cg</i> to do more with the
+condition codes information that is supplied with each
+instruction in the instruction definitions section of the
+table. Sometimes <i>cg</i> generates test instructions which
+actually were not necessary. This of course causes the
+generated programs to be slightly larger and slightly
+slower.</small></p>
+
+<p><small>In spite of the few minor shortcomings mentioned
+above I found <i>cgg</i> a very comfortable tool to
+use.</small></p>
+<a name="References"></a>
+<h2>References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[1]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>T. B. Steel Jr., <i>UNCOL: The myth and the
+Fact,</i> in Ann. Rev. Auto. Prog., R. Goodman (ed.), Vol. 2
+(1969), pp 325 - 344</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[2]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>A. S. Tanenbaum, H. van Staveren, E. G. Keizer,
+J. W. Stevenson, <i>A practical toolkit for making portable
+compilers,</i> Informatica Report 74, Vrije Universiteit,
+Amsterdam, 1983</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[3]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>A. S. Tanenbaum, H. van Staveren, E. G. Keizer,
+J. W. Stevenson, <i>Description of an experimental machine
+architecture for use with block structured languages,</i>
+Informatica Report 81, Vrije Universiteit, Amsterdam,
+1983</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[4]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>H. van Staveren <i>The table driven code
+generator from the Amsterdam Compiler Kit, Second Revised
+Edition,</i> Vrije Universiteit, Amsterdam</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[5]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small><i>MC68020 32-bit Microprocessor User&rsquo;s
+Manual,</i> Second Edition, Motorola Inc., 1985,
+1984</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>[6]</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small><i>MC68000 16-bit Microprocessor User&rsquo;s
+Manual, Preliminary,</i> Motorola Inc., 1979</small></p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/m68020.pdf b/doc/tack/m68020.pdf
new file mode 100644 (file)
index 0000000..428f911
Binary files /dev/null and b/doc/tack/m68020.pdf differ
diff --git a/doc/tack/ncg.html b/doc/tack/ncg.html
new file mode 100644 (file)
index 0000000..017b62e
--- /dev/null
@@ -0,0 +1,6654 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:10 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The table driven code generator</title>
+</head>
+<body>
+
+<h1 align=center>The table driven code generator</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. What has changed since version 1 ?">2. What has changed since version 1 ?</a><br>
+<a href="#3. Global overview of the workings of the code generator.">3. Global overview of the workings of the code generator.</a><br>
+<a href="#4. Register variables">4. Register variables</a><br>
+<a href="#5. Description of the machine table">5. Description of the machine table</a><br>
+<a href="#5.1. Constant section">5.1. Constant section</a><br>
+<a href="#5.2. Property definition">5.2. Property definition</a><br>
+<a href="#5.3. Register definition">5.3. Register definition</a><br>
+<a href="#5.4. Stack token definition">5.4. Stack token definition</a><br>
+<a href="#5.5. Sets">5.5. Sets</a><br>
+<a href="#5.6. Instruction definitions">5.6. Instruction definitions</a><br>
+<a href="#5.7. Expressions">5.7. Expressions</a><br>
+<a href="#5.8. Token descriptions">5.8. Token descriptions</a><br>
+<a href="#5.9. Code rules">5.9. Code rules</a><br>
+<a href="#5.9.1. The EM pattern">5.9.1. The EM pattern</a><br>
+<a href="#5.9.2. The stack pattern">5.9.2. The stack pattern</a><br>
+<a href="#5.9.3. The kills part">5.9.3. The kills part</a><br>
+<a href="#5.9.4. The allocates part">5.9.4. The allocates part</a><br>
+<a href="#5.9.5. The generates part">5.9.5. The generates part</a><br>
+<a href="#5.9.6. Stack replacement">5.9.6. Stack replacement</a><br>
+<a href="#5.9.7. EM replacement">5.9.7. EM replacement</a><br>
+<a href="#5.9.8. Examples">5.9.8. Examples</a><br>
+<a href="#5.10. Code rules using procedures">5.10. Code rules using procedures</a><br>
+<a href="#5.11. Move definitions">5.11. Move definitions</a><br>
+<a href="#5.12. Test definitions">5.12. Test definitions</a><br>
+<a href="#5.13. Some explanation about the rules behind coercions">5.13. Some explanation about the rules behind coercions</a><br>
+<a href="#5.14. Stack definitions">5.14. Stack definitions</a><br>
+<a href="#5.15. Coercions">5.15. Coercions</a><br>
+<a href="#6. The files mach.h and mach.c">6. The files mach.h and mach.c</a><br>
+<a href="#6.1. Types in the code generator">6.1. Types in the code generator</a><br>
+<a href="#6.2. Global variables to work with">6.2. Global variables to work with</a><br>
+<a href="#6.3. Macros in mach.h">6.3. Macros in mach.h</a><br>
+<a href="#6.3.1. Example mach.h for the PDP-11">6.3.1. Example mach.h for the PDP-11</a><br>
+<a href="#6.4. Functions in mach.c">6.4. Functions in mach.c</a><br>
+<a href="#6.4.1. Example mach.c for the PDP-11">6.4.1. Example mach.c for the PDP-11</a><br>
+<a href="#7. Internal workings of the code generator.">7. Internal workings of the code generator.</a><br>
+<a href="#7.1. Description of tables.c and tables.h contents">7.1. Description of tables.c and tables.h contents</a><br>
+<a href="#7.1.1. Tables.c">7.1.1. Tables.c</a><br>
+<a href="#7.1.2. tables.h">7.1.2. tables.h</a><br>
+<a href="#7.2. Other important data structures">7.2. Other important data structures</a><br>
+<a href="#7.3. A tour through the sources">7.3. A tour through the sources</a><br>
+<a href="#7.3.1. codegen.c">7.3.1. codegen.c</a><br>
+<a href="#7.3.1.1. DO_DLINE">7.3.1.1. DO_DLINE</a><br>
+<a href="#7.3.1.2. DO_NEXTEM">7.3.1.2. DO_NEXTEM</a><br>
+<a href="#7.3.1.3. DO_COERC">7.3.1.3. DO_COERC</a><br>
+<a href="#7.3.1.4. DO_XMATCH">7.3.1.4. DO_XMATCH</a><br>
+<a href="#7.3.1.5. DO_MATCH">7.3.1.5. DO_MATCH</a><br>
+<a href="#7.3.1.6. DO_REMOVE">7.3.1.6. DO_REMOVE</a><br>
+<a href="#7.3.1.7. DO_DEALLOCATE">7.3.1.7. DO_DEALLOCATE</a><br>
+<a href="#7.3.1.8. DO_REALLOCATE">7.3.1.8. DO_REALLOCATE</a><br>
+<a href="#7.3.1.9. DO_ALLOCATE">7.3.1.9. DO_ALLOCATE</a><br>
+<a href="#7.3.1.10. DO_INSTR">7.3.1.10. DO_INSTR</a><br>
+<a href="#7.3.1.11. DO_MOVE">7.3.1.11. DO_MOVE</a><br>
+<a href="#7.3.1.12. DO_TEST">7.3.1.12. DO_TEST</a><br>
+<a href="#7.3.1.13. DO_ERASE">7.3.1.13. DO_ERASE</a><br>
+<a href="#7.3.1.14. DO_TOKREPLACE">7.3.1.14. DO_TOKREPLACE</a><br>
+<a href="#7.3.1.15. DO_EMREPLACE">7.3.1.15. DO_EMREPLACE</a><br>
+<a href="#7.3.1.16. DO_COST">7.3.1.16. DO_COST</a><br>
+<a href="#7.3.1.17. DO_RETURN">7.3.1.17. DO_RETURN</a><br>
+<a href="#7.3.1.18. DO_LABDEF">7.3.1.18. DO_LABDEF</a><br>
+<a href="#7.3.2. compute.c">7.3.2. compute.c</a><br>
+<a href="#7.3.3. equiv.c">7.3.3. equiv.c</a><br>
+<a href="#7.3.4. fillem.c">7.3.4. fillem.c</a><br>
+<a href="#7.3.5. gencode.c">7.3.5. gencode.c</a><br>
+<a href="#7.3.6. glosym.c">7.3.6. glosym.c</a><br>
+<a href="#7.3.7. label.c">7.3.7. label.c</a><br>
+<a href="#7.3.8. main.c">7.3.8. main.c</a><br>
+<a href="#7.3.9. move.c">7.3.9. move.c</a><br>
+<a href="#7.3.10. nextem.c">7.3.10. nextem.c</a><br>
+<a href="#7.3.11. reg.c">7.3.11. reg.c</a><br>
+<a href="#7.3.12. salloc.c">7.3.12. salloc.c</a><br>
+<a href="#7.3.13. state.c">7.3.13. state.c</a><br>
+<a href="#7.3.14. subr.c">7.3.14. subr.c</a><br>
+<a href="#7.3.14.1. match">7.3.14.1. match</a><br>
+<a href="#7.3.14.2. instance,cinstance">7.3.14.2. instance,cinstance</a><br>
+<a href="#7.3.14.3. eqtoken">7.3.14.3. eqtoken</a><br>
+<a href="#7.3.14.4. distance">7.3.14.4. distance</a><br>
+<a href="#7.3.14.5. split">7.3.14.5. split</a><br>
+<a href="#7.3.14.6. docoerc">7.3.14.6. docoerc</a><br>
+<a href="#7.3.14.7. stackupto">7.3.14.7. stackupto</a><br>
+<a href="#7.3.14.8. findcoerc">7.3.14.8. findcoerc</a><br>
+<a href="#7.3.15. var.c">7.3.15. var.c</a><br>
+
+<hr>
+
+<p><b>from the<br>
+Amsterdam Compiler Kit<br>
+Second Revised Edition</b></p>
+
+<p align=center><i><small>ABSTRACT</small></i></p>
+
+<p align=center><i><small>Hans van
+Staveren</small></i><small><br>
+Dept. of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</small></p>
+
+<p><small>The Amsterdam Compiler Kit is a collection of
+tools designed to help automate the process of compiler
+building. Part of it is a table driven code generator,
+called <i>cg</i>, and a program to check and translate
+machine description tables called <i>cgg</i>. This document
+provides a description of the internal workings of
+<i>cg</i>, and a description of syntax and semantics of the
+driving table. This is required reading for those wishing to
+write a new table.</small></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><small>Part of the Amsterdam Compiler Kit is a code
+generator system consisting of a code generator generator
+(<i>cgg</i> for short) and some machine independent C code.
+<i>Cgg</i> reads a machine description table and creates two
+files, tables.h and tables.c. These are then used together
+with other C code to produce a code generator for the
+machine at hand.</small></p>
+
+<p><small>This in turn reads compact EM code and produces
+assembly code. The remainder of this document will first
+broadly describe the working of the code generator, then the
+machine table will be described after which some light is
+shed onto the internal workings of the code
+generator.</small></p>
+
+<p><small>The reader is assumed to have at least a vague
+notion about the semantics of the intermediary EM code.
+Someone wishing to write a table for a new machine should be
+thoroughly acquainted with EM code and the assembly code of
+the machine at hand.</small></p>
+<a name="2. What has changed since version 1 ?"></a>
+<h2>2. What has changed since version 1 ?</h2>
+
+<p><small>This section can be skipped by anyone not
+familiar with the first version. It is not needed to
+understand the current version.</small></p>
+
+<p><small>This paper describes the second version of the
+code generator system. Although the code generator itself is
+for the main part unchanged, the table format has been
+drastically redesigned and the opportunities to make faulty
+tables are reduced. The format is now aesthaticly more
+pleasing (according to <i>me</i> that is), mainly because
+the previous version was designed for one line code rules,
+which did not work out that way.</small></p>
+
+<p><small>The &lsquo;SCRATCH&rsquo; property is now
+automatically generated by <i>cgg</i>, <i>erase</i> and
+<i>setcc</i> calls and their ilk are now no longer needed
+(read: can no longer be forgotten) and all this because the
+table now <i>knows</i> what the machine instructions look
+like and what arguments they destroy.</small></p>
+
+<p><small>Checks are now made for register types, so it is
+no longer possible to generate a &lsquo;regind2&rsquo; token
+with a floating point register as a base. In general, if the
+instructions of the machine are correctly defined, it is no
+longer possible to generate code that does not assemble,
+which of course does not mean that it is not possible to
+generate assembly code that does not do what was
+intended!</small></p>
+
+<p><small>Checks are made now for missing moves, tests,
+coercions, etc. There is a form of procedure call now to
+reduce table size: it is no longer necessary to write the
+code for conditional instructions six times.</small></p>
+
+<p><small>The inreg() pseudo-function returns other
+results!!</small></p>
+<a name="3. Global overview of the workings of the code generator."></a>
+<h2>3. Global overview of the workings of the code generator.</h2>
+
+<p><small>The code generator or <i>cg</i> tries to generate
+good code by simulating the stack of the compiled program
+and delaying emission of code as long as possible. It also
+keeps track of register contents, which enables it to
+eliminate redundant moves, and tries to eliminate redundant
+tests by keeping information about condition code status, if
+applicable for the machine.</small></p>
+
+<p><small><i>Cg</i> maintains a &lsquo;fake stack&rsquo;
+containing &lsquo;tokens&rsquo; that are built by executing
+the pseudo code contained in the code rules given by the
+table writer. One can think of the fake stack as a logical
+extension of the real stack the compiled program will have
+when run. Alternatively one can think of the real stack as
+an infinite extension at the bottom of the fake stack. Both
+ways, the concatenation of the real stack and the fake stack
+will be the stack as it would have been on a real EM machine
+(see figure).</small></p>
+
+
+<p align=center><small><img src="grohtml-99451.png"></small></p>
+
+<p><small>During code generation tokens will be kept on the
+fake stack as long as possible but when they are moved to
+the real stack, by generating code for the push, all tokens
+above&dagger;</small></p>
+
+
+<p align=center><small><img src="grohtml-99452.png"></small></p>
+
+<p><small>the pushed tokens will be pushed also, so the
+fake stack will not contain holes.</small></p>
+
+<p><small>The information about the machine that <i>cg</i>
+needs has to be given in a machine description table, with
+as a major part a list of code rules telling <i>cg</i> what
+to do when certain EM-instructions occur with certain tokens
+on the fake stack. Not all possible fake stack possibilities
+have to be given of course, there is a possibility for
+providing rewriting rules, or <i>coercions</i> as they are
+called in this document.</small></p>
+
+<p><small>The main loop of <i>cg</i> is:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>find a pattern of EM instructions starting at the
+current one to generate code for. This pattern will usually
+be of length one but longer patterns can be used. Process
+any pseudo-instructions found.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Select one of the possibly many stack patterns
+that go with this EM pattern on the basis of heuristics,
+look ahead or both. The cost fields provided in the token
+definitions and instruction definitions are used to compute
+costs during look ahead.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Force the current fake stack contents to match
+the pattern. This may involve copying tokens to registers,
+making dummy transformations, e.g. to transform a
+&lsquo;local&rsquo; into an &lsquo;indexed from
+register&rsquo; or might even cause the move of the complete
+fake stack contents to the real stack and then back into
+registers if no suitable coercions were provided by the
+table writer.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Execute the pseudocode associated with the code
+rule just selected, this may cause registers to be
+allocated, code to be emitted etc..</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Put tokens onto the fake stack to reflect the
+result of the operation.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Insert some EM instructions into the stream; this
+is possible but not common.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Account for the cost. The cost is kept in a
+(space, time) vector and look ahead decisions are based on a
+linear combination of these. The code generator calls on
+itself recursively during look ahead, and the recursive
+incarnations return the costs they made. The costs the
+top-level code generator makes is of course
+irrelevant.</small></p>
+</td>
+</table>
+
+<p><small>The table that drives <i>cg</i> is not read in
+every time, but instead is used at compile time of <i>cg</i>
+to set parameters and to load pseudocode tables. A program
+called <i>cgg</i> reads the table and produces large lists
+of numbers that are compiled together with machine
+independent code to produce a code generator for the machine
+at hand.</small></p>
+
+<p><small>Part of the information needed is not easily
+expressed in this table format and must be supplied in two
+separate files, mach.h and mach.c. Their contents are
+described later in this document.</small></p>
+<a name="4. Register variables"></a>
+<h2>4. Register variables</h2>
+
+<p><small>If the machine has more than enough registers to
+generate code with, it is possible to reserve some of them
+for use as register variables. If it has not, this section
+may be skipped and any references to register variables in
+the rest of this document may be ignored.</small></p>
+
+<p><small>The front ends generate messages to the back ends
+telling them which local variables could go into registers.
+The information given is the offset of the local, its size
+and type and a scoring number, roughly the number of times
+it occurs.</small></p>
+
+<p><small>The decision which variable to put in which
+register is taken by the machine independent part of
+<i>cg</i> with the help of a scoring function provided by
+the table writer in mach.c. The types of variables known
+are</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>reg_any</small></p>
+</td>
+<td width="10%"></td>
+<td width="76%">
+
+<p><small>Just a variable of some integer type. Nothing
+special known about it.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>reg_float</small></p>
+</td>
+<td width="6%"></td>
+<td width="52%">
+
+<p><small>A floating point variable.</small></p>
+</td>
+<td width="23%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>reg_loop</small></p>
+</td>
+<td width="8%"></td>
+<td width="48%">
+
+<p><small>A loop control variable.</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>reg_pointer</small></p>
+</td>
+<td width="2%"></td>
+<td width="76%">
+
+<p><small>A pointer variable. Usually they are better
+candidates to put in registers.</small></p>
+</td>
+</table>
+
+<p><small>If register variables are used, more functions
+must be supplied in mach.c. These functions are explained
+later.</small></p>
+<a name="5. Description of the machine table"></a>
+<h2>5. Description of the machine table</h2>
+
+<p><small>The machine description table consists of the
+concatenation of the following sections:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Constant definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Property definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>Register definitions</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p><small>Token definitions</small></p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="30%">
+
+<p><small>Set definitions</small></p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="46%">
+
+<p><small>Instruction definitions</small></p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7)</small></p>
+</td>
+<td width="6%"></td>
+<td width="32%">
+
+<p><small>Move definitions</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>8)</small></p>
+</td>
+<td width="6%"></td>
+<td width="32%">
+
+<p><small>Test definitions</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>9)</small></p>
+</td>
+<td width="6%"></td>
+<td width="34%">
+
+<p><small>Stack definitions</small></p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>10)</small></p>
+</td>
+<td width="4%"></td>
+<td width="18%">
+
+<p><small>Coercions</small></p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>11)</small></p>
+</td>
+<td width="4%"></td>
+<td width="20%">
+
+<p><small>Code rules</small></p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p><small>This is the order in the table but the
+descriptions in this document will use a slightly different
+order. All sections except the first start with an uppercase
+header word. Examples may be given in early stages that use
+knowledge that is explained in a later stage. If something
+is not clear the first time, please read on. All will clear
+up in a couple of pages.</small></p>
+
+<p><small>Input is in free format, white space and newlines
+may be used at will to improve legibility. Identifiers used
+in the table have the same syntax as C identifiers, upper
+and lower case considered different, all characters
+significant. Here is a list of reserved words; all of these
+are unavailable as identifiers.</small></p>
+
+
+<p align=center><small><img src="grohtml-99453.png"></small></p>
+
+<p><small>C style comments are accepted.</small></p>
+<pre><small>     /* this is a comment */
+</small></pre>
+
+<p><small>If the standard constant facility is not enough
+the C-preprocessor can be used to enhance the table
+format.</small></p>
+
+<p><small>Integers in the table have the normal C-style
+syntax. Decimal by default, octal when preceded by a 0 and
+hexadecimal when preceded by 0x.</small></p>
+<a name="5.1. Constant section"></a>
+<h2>5.1. Constant section</h2>
+
+<p><small>In the first part of the table some constants can
+be defined, most with the syntax</small></p>
+<pre><small>     NAME=value
+</small></pre>
+
+<p><small>value being an integer or string. Three constants
+must be defined here:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_WSIZE</small></p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p><small>Number of bytes in a machine word. This is the
+number of bytes a <b>loc</b> instruction will put on the
+stack.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_PSIZE</small></p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p><small>Number of bytes in a pointer. This is the number
+of bytes a <b>lal</b> instruction will put on the
+stack.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>EM_BSIZE</small></p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p><small>Number of bytes in the hole between AB and LB. If
+the calling sequence just saves PC and LB this size will be
+twice the pointersize.</small></p>
+</td>
+</table>
+
+<p><small>EM_WSIZE and EM_PSIZE are checked when a program
+is compiled with the resulting code generator. EM_BSIZE is
+used by <i>cg</i> to add to the offset of instructions
+dealing with locals having positive offsets, i.e.
+parameters.</small></p>
+
+<p><small>Other constants can be defined here to be used as
+mnemonics later in the table.</small></p>
+
+<p><small>Optional is the definition of a printformat for
+integers in the code file. This is given as</small></p>
+<pre><small>     FORMAT = string
+</small></pre>
+
+<p><small>The string must be a valid printf(III) format,
+and defaults to &quot;%ld&quot;. For example on the PDP-11
+one can use</small></p>
+<pre><small>     FORMAT= &quot;0%lo&quot;
+</small></pre>
+
+<p><small>to satisfy the old UNIX assembler that reads
+octal unless followed by a period, and the ACK assembler
+that follows C conventions.</small></p>
+
+<p><small>Tables under control of source code control
+systems like <i>sccs</i> or <i>rcs</i> can put their
+id-string here, for example</small></p>
+<pre><small>     rcsid=&quot;$Header$&quot;
+</small></pre>
+
+<p><small>These strings, like all strings in the table,
+will eventually end up in the binary code generator
+produced.</small></p>
+
+<p><small>Optionally one can give the factors with which
+the size and time parts of the cost vector have to be
+multiplied to ensure they have the same order of magnitude.
+This can be done as</small></p>
+<pre><small>     SIZEFACTOR = C3/C4
+
+
+     TIMEFACTOR = C1/C2
+</small></pre>
+
+<p><small>Above numbers must be read as rational numbers.
+Defaults are 1/1 for both of them. These constants set the
+default size/time tradeoff in the code generator, so if
+TIMEFACTOR and SIZEFACTOR are both 1 the code generator will
+choose at random between two code sequences where one has
+cost (10,4) and the other has cost (8,6). See also the
+description of the cost field below.</small></p>
+<a name="5.2. Property definition"></a>
+<h2>5.2. Property definition</h2>
+
+<p><small>This part of the table defines the list of
+properties that can be used to differentiate between
+register classes. It consists of a list of user-defined
+identifiers optionally followed by the size of the property
+in parentheses, default EM_WSIZE. Example for the
+PDP-11:</small></p>
+
+
+<p align=center><small><img src="grohtml-99454.png"></small></p>
+
+<p><small>Registers are allocated by asking for a property,
+so if for some reason in later parts of the table one
+particular register must be allocated it has to have a
+unique property.</small></p>
+<a name="5.3. Register definition"></a>
+<h2>5.3. Register definition</h2>
+
+<p><small>The next part of the tables describes the various
+registers of the machine and defines identifiers to be used
+in later parts of the tables. Syntax:</small></p>
+<pre><small>     &lt;register definitions&gt; : REGISTERS &lt;list of definitions&gt;
+     &lt;definition&gt; : &lt;registerlist&gt; &rsquo;:&rsquo; &lt;propertylist&gt; &lt;optional regvar&gt; &rsquo;.&rsquo;
+     &lt;register&gt; : ident [ &rsquo;(&rsquo; string &rsquo;)&rsquo; ] [ &rsquo;=&rsquo; ident [ &rsquo;+&rsquo; ident ] ]
+</small></pre>
+
+<p><small>Example for the PDP-11:</small></p>
+
+
+<p align=center><small><img src="grohtml-99455.png"></small></p>
+
+<p><small>The names in the left hand lists are names of
+registers as used in the table. They can optionally be
+followed by a string in parentheses, their name as far as
+the assembler is concerned. The default assembler name is
+the same as the table name. A name can also be followed
+by</small></p>
+<pre><small>     = othername
+</small></pre>
+
+<p><small>or</small></p>
+<pre><small>     = othername + othername
+</small></pre>
+
+<p><small>which says that the register is composed of the
+parts after the &rsquo;=&rsquo; sign. The identifiers at the
+right hand side of the lists are names of properties. The
+end of each register definition is a period.</small></p>
+
+<p><small>It might seem wise to list every property of a
+register, so one might give r0 the extra property MFPTREG
+named after the not too well known MFPT instruction on newer
+PDP-11 types, but this is not a good idea, especially since
+no use can be made of that instruction anyway. Every extra
+property means the register set is more unorthogonal and
+<i>cg</i> execution time is influenced by that, because it
+has to take into account a larger set of registers that are
+not equivalent. So try to keep the number of different
+register classes to a minimum. When faced with the choice
+between two possible code rules for a nonfrequent EM
+sequence, one being elegant but requiring an extra property,
+and the other less elegant, elegance should probably
+loose.</small></p>
+
+<p><small>Tables that implement register variables must
+mark registers to be used for variable storage here by
+following the list of properties by one of the
+following:</small></p>
+<pre><small>     regvar <i>or</i> regvar(reg_any)
+     regvar(reg_loop)
+     regvar(reg_pointer)
+     regvar(reg_float)
+</small></pre>
+
+<p><small>meaning they are candidates for that type of
+variable. All register variables of one type must be of the
+same size, and they may have no subregisters. Such registers
+are not available for normal code generation.</small></p>
+<a name="5.4. Stack token definition"></a>
+<h2>5.4. Stack token definition</h2>
+
+<p><small>The next part describes all possible tokens that
+can reside on the fake stack during code generation.
+Attributes of a token are described as a C struct
+declaration; this is followed by the size of the token in
+bytes, optionally followed by the cost of the token when
+used as an addressing mode and the format to be used on
+output.</small></p>
+
+<p><small>In general, when writing a table, it is not wise
+to try to think of all necessary tokens in advance. While
+writing the necessity or advisability for some token will be
+seen and it can then be added together with the stacking
+rules and coercions needed.</small></p>
+
+<p><small>Tokens should usually be declared for every
+addressing mode of the machine at hand and for every size
+directly usable in a machine instruction. Example for the
+PDP-11 (incomplete):</small></p>
+
+
+<p align=center><small><img src="grohtml-99456.png"></small></p>
+
+<p><small>Types allowed in the struct are ADDR, INT and all
+register properties. The type ADDR means a string and an
+integer, which is output as string+integer, and arithmetic
+on mixed ADDR and INT is possible. This is the right mode
+for anything that can be an assembler address expression.
+The type of the register in the token is strict. At any
+assignment of an expression of type register to a token
+attribute of type register <i>cgg</i> will check if the set
+of possible results from the expression is a subset of the
+set of permissible values for the token
+attribute.</small></p>
+
+<p><small>The cost-field is made up by the word <i>cost</i>
+followed by two numbers in parentheses, the size and
+timecosts of this token when output in the code file. If
+omitted, zero cost is assumed. While generating code,
+<i>cg</i> keeps track of a linear combination of these costs
+together with the costs of the instructions itself which we
+will see later. The coefficients of this linear combination
+are influenced by two things:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>The SIZEFACTOR and TIMEFACTOR constants, as
+mentioned above.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>A run time option to <i>cg</i> that can adjust
+the time/space tradeoff to all positions from 100% time to
+100% space.</small></p>
+</td>
+</table>
+
+<p><small>By supplying different code rules in certain
+situations it is possible to get a code generator that can
+adjust its code to the need of the moment. This is probably
+most useful with small machines, experience has shown that
+on the larger micro&rsquo;s and mini&rsquo;s the difference
+between time-optimal and space-optimal code is often
+small.</small></p>
+
+<p><small>The printformat consists of a list of strings
+intermixed with attributes from the token. Strings are
+output literally, attributes are printed according to their
+type and value. Tokens without a printformat should never be
+output, and <i>cgg</i> checks for this.</small></p>
+
+<p><small>Notice that tokens need not correspond to
+addressing modes; the regconst2 token listed above, meaning
+the sum of the contents of the register and the constant,
+has no corresponding addressing mode on the PDP-11, but is
+included so that a sequence of add constant, load indirect,
+can be handled efficiently. This regconst2 token is needed
+as part of the path</small></p>
+<pre><small>     REG -&gt; regconst2 -&gt; regind2
+</small></pre>
+
+<p><small>of which the first and the last &quot;exist&quot;
+and the middle is needed only as an intermediate
+step.</small></p>
+
+<p><small>Tokens with name &lsquo;LOCAL&rsquo; or
+&lsquo;DLOCAL&rsquo; are a special case when register
+variables are used, this is explained further in the section
+on token descriptions.</small></p>
+<a name="5.5. Sets"></a>
+<h2>5.5. Sets</h2>
+
+<p><small>Usually machines have certain collections of
+addressing modes that can be used with certain instructions.
+The stack patterns in the table are lists of these
+collections and since it is cumbersome to write out these
+long lists every time, there is a section here to give names
+to these collections. Please note that it is not forbidden
+to write out a set in the remainder of the table, but for
+clarity it is usually better not to.</small></p>
+
+<p><small>Example for the PDP-11 (incomplete):</small></p>
+
+
+<p align=center><small><img src="grohtml-99457.png"></small></p>
+
+<p><small>Permissible in the set construction are all the
+usual set operators, i.e.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>+</small></p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p><small>set union</small></p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="28%">
+
+<p><small>set difference</small></p>
+</td>
+<td width="61%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>*</small></p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p><small>set intersection</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+
+<p><small>Normal operator priorities apply, and parentheses
+can be used. Every token identifier is also a set identifier
+denoting the singleton collection of tokens containing just
+itself. Every register property as defined above is also a
+set matching all registers with that property. The standard
+set identifier ALL denotes the collection of all
+tokens.</small></p>
+<a name="5.6. Instruction definitions"></a>
+<h2>5.6. Instruction definitions</h2>
+
+<p><small>In the next part of the table the instructions
+for the machine are declared together with information about
+their operands. Example for the PDP-11(very
+incomplete):</small></p>
+<pre><small>     INSTRUCTIONS
+     /* default cost */
+
+
+     cost(2,600)
+
+
+     /* Normal instructions */
+
+
+     adc dst2:rw:cc .
+     add src2:ro,dst2:rw:cc cost(2,450).
+     ash src2:ro,REG:rw:cc .
+     ashc src2:ro,REGPAIR+ODDREG:rw .
+     asl dst2:rw:cc .
+     asr dst2:rw:cc .
+     bhis &quot;bcc&quot; label .
+
+
+     /* floating point instructions */
+
+
+     movf &quot;ldf&quot; fsrc,freg .
+     movf &quot;stf&quot; freg,fdst .
+</small></pre>
+
+<p><small>As the examples show an instruction definition
+consists of the name of the instruction, optionally followed
+by an assembler mnemonic in quotes-default is the name
+itself-and then a list of operands, optionally followed by
+the cost and then a period. If the cost is omitted the cost
+just after the word INSTRUCTIONS is assumed, if that is also
+omitted the cost is zero. The cost must be known by
+<i>cg</i> of course if it has multiple code generation paths
+to choose from.</small></p>
+
+<p><small>For each operand we have the set of possible
+token values, followed by a qualifier that can
+be</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>:ro</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>signifies that this operand is read only, so it
+can be replaced by a register with the same contents if
+available.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>:rw</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>signifies that the operand is
+read-write</small></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>:wo</small></p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p><small>signifies that the operand is write
+only.</small></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>:cc</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>says that after the instruction is finished, the
+condition codes are set to this operand. If none of the
+operands have the :cc qualifier set, <i>cg</i> will assume
+that condition codes were unaffected (but see
+below).</small></p>
+</td>
+</table>
+
+<p><small>The first three qualifiers are of course mutually
+exclusive. The :ro qualifier does not cause any special
+action in the current implementation, and the :wo and :rw
+qualifiers are treated equal. It must be recommended however
+to be precise in the specifications, since later
+enhancements to the code generator might use
+them.</small></p>
+
+<p><small>As the last examples show it is not necessary to
+give one definition for an instruction. There are machines
+that have very unorthogonal instruction sets, in fact most
+of them do, and it is possible to declare each possible
+combination of operands. The <i>cgg</i> program will check
+all uses of the instruction to find out which one was
+meant.</small></p>
+
+<p><small>Although not in the PDP-11 example above there is
+a possibility to describe instructions that have side
+effects to registers not in the operand list. The only thing
+possible is to say that the instruction is destructive to
+some registers or the condition codes, by following the
+operand list with the word <i>kills</i> and a list of the
+things destroyed. Example for some hypothetic accumulator
+machine:</small></p>
+<pre><small>     add source2:ro kills ACCU :cc .
+</small></pre>
+
+<p><small>The cost fields in the definitions for tokens and
+instructions are added together when generating code. It
+depends on the machine at hand whether the costs are
+orthogonal enough to make use of both these costs, in
+extreme cases every combination of instructions and operands
+can be given in this section, all with their own
+costs.</small></p>
+<a name="5.7. Expressions"></a>
+<h2>5.7. Expressions</h2>
+
+<p><small>Throughout the rest of the table expressions can
+be used in some places. This section will give the syntax
+and semantics of expressions. There are four types of
+expressions: integer, address, register and undefined.
+Really the type register is nonexistent as such, for each
+register expression <i>cgg</i> keeps a set of possible
+values, and this set can be seen as the real
+type.</small></p>
+
+<p><small>Type checking is performed by <i>cgg</i>. An
+operator with at least one undefined operand returns
+undefined except for the defined() function mentioned below.
+An undefined expression is interpreted as FALSE when it is
+needed as a truth value. It is the responsibility of the
+table writer to ensure no undefined expressions are ever
+used as initialisers for token attributes. This is
+unfortunately almost impossible to check for <i>cgg</i> so
+be careful.</small></p>
+
+<p><small>Basic terms in an expression are</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>number</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>A number is a constant of type integer. Also
+usable is an identifier defined to a number in the constant
+definition section.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>&quot;string&quot;</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>A string within double quotes is a constant of
+type address. All the normal C style escapes may be used
+within the string. Also usable is an identifier defined to a
+string in the constant definition section.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>[0-9][bf]</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>This must be read as a grep-pattern. It evaluates
+to a string that is the label name for the temporary label
+meant. More about this in the section on code
+rules.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>REGIDENT</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>The name of a register is a constant of type
+register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>$<i>i</i></small></p>
+</td>
+<td width="28%"></td>
+<td width="68%">
+
+<p><small>A dollarsign followed by a number is the
+representation of the argument of EM instruction . The type
+of the operand is dependent on the instruction, sometimes it
+is integer, sometimes it is address. It is undefined when
+the instruction has no operand. Instructions with
+type-letter w can occur without an operand. This can be
+checked in the code rule with the defined() pseudo
+function.</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="31%"></td>
+<td width="68%">
+<p><small>If it is unimaginable for the operand of the
+instruction ever to be something different from a plain
+integer, the type is integer, otherwise it is address.<br>
+Those who want to know it exactly, the integer instruction
+types are the instructions marked with the type-letters
+c,f,l,n,o,s,r,w,z in the EM manual.<i><br>
+Cg</i> makes all necessary conversions, like adding EM_BSIZE
+to positive arguments of instructions dealing with locals,
+prepending underlines to global names, converting code
+labels into a unique representation etc. Details about this
+can be found in the section about machine dependent C
+code.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>%1</small></p>
+</td>
+<td width="28%"></td>
+<td width="68%">
+
+<p><small>This in general means the token mentioned first
+in the stack pattern. When used inside an expression the
+token must be a simple register. Type of this is
+register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>%1.off</small></p>
+</td>
+<td width="20%"></td>
+<td width="68%">
+
+<p><small>This means attribute &quot;off&quot; of the first
+stack pattern token. Type is the same as that of attribute
+&quot;off&quot;. To use this expression implies a check that
+all tokens in the set used have the same attribute in the
+same place.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>%off</small></p>
+</td>
+<td width="24%"></td>
+<td width="68%">
+
+<p><small>This means attribute &quot;off&quot; in the
+&lsquo;current&rsquo; token. This can only be used when no
+confusion is possible about which token was meant, eg. in
+the optional boolean expressions following token sets in the
+move and test rules, in coercions or in the kills section
+inside the code rules. Same check as above.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>%1.1</small></p>
+</td>
+<td width="24%"></td>
+<td width="68%">
+
+<p><small>This is the first subregister of the first token.
+Previous comments apply.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>%b</small></p>
+</td>
+<td width="28%"></td>
+<td width="68%">
+
+<p><small>A percent sign followed by a lowercase letter
+stands for an allocated register. This is the second
+allocated register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p><small>%a.2</small></p>
+</td>
+<td width="24%"></td>
+<td width="68%">
+
+<p><small>The second subregister of the first allocated
+register.</small></p>
+</td>
+</table>
+
+<p><small>All normal C operators apply to integers, the +
+operator on addresses behaves as one would expect and the
+only operators allowed on register expressions are == and !=
+. Furthermore there are some special
+&lsquo;functions&rsquo;:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>defined(e)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if expression <i>e</i> is defined, 0
+otherwise.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><small>samesign(e1,e2)</small></p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if integer expression <i>e1</i> and
+<i>e2</i> have the same sign.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>sfit(e1,e2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if integer expression <i>e1</i> fits as
+a signed integer into a field of <i>e2</i> bits, 0
+otherwise.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>ufit(e1,e2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Same as above but now for unsigned
+<i>e1</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>rom($a,n)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Integer expression giving word <i>n</i> from the
+<b>rom</b> descriptor pointed at by EM instruction number
+<i>a</i> in the EM-pattern. Undefined if that descriptor
+does not exist.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>is_rom($a)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Integer expression indicating whether EM
+instruction number <i>a</i> in the EM-pattern refers to ROM.
+This may be useful for generating position-independent code
+with the ROM in read-only memory. <i>Is_rom</i> enables one
+to see the difference between ROM references and other data
+references.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>loww($a)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Returns the lower half of the argument of EM
+instruction number <i>a</i>. This is used to split the
+arguments of a <b>ldc</b> instruction.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>highw($a)</small></p>
+</td>
+<td width="14%"></td>
+<td width="40%">
+
+<p><small>Same for upper half.</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+
+<p><small>The next two &lsquo;functions&rsquo; are only
+needed in a table that implements register
+variables.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>inreg(e)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Returns the status of the local variable with
+offset <i>e</i> from the localbase. Value is an integer,
+negative if the local was not allowed as a register
+variable, zero if it was allowed but not assigned to a
+register, and the type of the register if it was assigned to
+a register. This makes it possible to write</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="31%"></td>
+<td width="68%">
+<pre><small>     inreg($1)==reg_pointer
+</small></pre>
+<!-- INDENTATION -->
+<p><small>and similar things.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>regvar(e,t)</small></p>
+</td>
+<td width="10%"></td>
+<td width="68%">
+
+<p><small>Type of this is register. It returns the register
+the local with offset <i>e</i> is assigned to. The table
+writer guarantees the register is one of type <i>t</i>, with
+<i>t</i> one of reg_any, reg_loop, reg_pointer or reg_float.
+If <i>t</i> is omitted reg_any is assumed. Undefined if
+inreg(<i>e</i>)&lt;=0 .</small></p>
+</td>
+</table>
+
+<p><small>The next two &lsquo;functions&rsquo; are only
+needed in a table that uses the top element size
+information.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="28%">
+
+<p><small>topeltsize($a)</small></p>
+</td>
+<td width="4%"></td>
+<td width="68%">
+
+<p><small>Returns the size of the element on top of the
+EM-stack at the label identified by $a. This can be used to
+put the top of the stack in a register at the moment of an
+unconditional jump. At an unconditional jump, the size of
+the top-element will always look 0.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><small>fallthrough($a)</small></p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p><small>Returns 1 if the label identified by $a can be
+reached via fallthrough, 0 otherwise.</small></p>
+</td>
+</table>
+<a name="5.8. Token descriptions"></a>
+<h2>5.8. Token descriptions</h2>
+
+<p><small>Throughout the rest of the table tokens must be
+described, be it as operands of instructions or as
+stack-replacements. In all those cases we will speak about a
+token description. The possibilities for these will be
+described here.</small></p>
+
+<p><small>All expressions of type register are token
+descriptions. The construct %1 means the token matched first
+in the stack pattern. All other token descriptions are those
+that are built on the spot. They look like this:</small></p>
+<pre><small>     { &lt;tokenname&gt; , &lt;list of token attribute initializing expressions&gt; }
+</small></pre>
+
+<p><small>All expressions are type-checked by <i>cgg</i>,
+and the number of initializers is also checked.</small></p>
+
+<p><small>A special case of the last token descriptions
+occurs when the token name is &lsquo;LOCAL&rsquo; or
+&lsquo;DLOCAL&rsquo; and the table uses register variables.
+The first token attribute then must be of type integer and
+the token description is automagically replaced by the
+register chosen if the LOCAL (wordsize) or DLOCAL (twice the
+wordsize) was assigned to a register.</small></p>
+<a name="5.9. Code rules"></a>
+<h2>5.9. Code rules</h2>
+
+<p><small>The largest section of the tables consists of the
+code generation rules. They specify EM patterns, stack
+patterns, code to be generated etc. Broadly the syntax
+is</small></p>
+<pre><small>code rule : EM-part code-part
+EM-part : EM-pattern | procedure-heading
+code-part : code-description | procedure-call
+code-description : stackpattern kills allocates generates yields leaving
+</small></pre>
+
+<p><small>Ignoring the &quot;procedure&quot;-part for now,
+the description for the EM-pattern and the code-description
+follows. Almost everything here is optional, the minimum
+code rule is:</small></p>
+<pre><small>     pat nop
+</small></pre>
+
+<p><small>that will simply throw away <i>nop</i>
+instructions.</small></p>
+<a name="5.9.1. The EM pattern"></a>
+<h2>5.9.1. The EM pattern</h2>
+
+<p><small>The EM pattern consists of a list of EM mnemonics
+preceded by the word <i>pat</i> optionally followed by a
+boolean expression. Examples:</small></p>
+<pre><small>     pat <b>loe
+</b></small></pre>
+
+<p><small>will match a single <b>loe</b>
+instruction,</small></p>
+<pre><small>     pat <b>loc loc cif</b> $1==2 &amp;&amp; $2==8
+</small></pre>
+
+<p><small>is a pattern that will match</small></p>
+<pre><small><b>     loc</b> 2
+<b>     loc</b> 8
+<b>     cif
+</b></small></pre>
+
+<p><small>and</small></p>
+<pre><small>     pat <b>lol inc stl</b> $1==$3
+</small></pre>
+
+<p><small>will match for example</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small><b>lol</b> 6</small></p>
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>lol</b> -2</small></p>
+</td>
+<td width="20%">
+</td>
+<td width="20%">
+
+<p><small><b>lol</b> 4<b><br>
+inc</b></small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>inc</b></small></p>
+</td>
+<td width="20%">
+
+<p><small>but <i>not</i></small></p>
+</td>
+<td width="20%">
+
+<p><small><b>inc<br>
+stl</b> 6</small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="20%">
+
+<p><small><b>stl</b> -2</small></p>
+</td>
+<td width="20%">
+</td>
+<td width="20%">
+
+<p><small><b>stl</b> -4</small></p>
+</td>
+<td width="20%"></td>
+<td width="9%">
+</td>
+</table>
+
+<p><small>A missing boolean expression evaluates to
+TRUE.</small></p>
+
+<p><small>The code generator will match the longest EM
+pattern on every occasion, if two patterns of the same
+length match the first in the table will be chosen, while
+all patterns of length greater than or equal to three are
+considered to be of the same length. This rule of three is
+an unfortunate implementation dependent restriction, but
+patterns longer than three EM instructions are luckily not
+needed too often.</small></p>
+
+<p><small>The EM mnemonic may also be the
+pseudo-instruction <b>lab</b>, which matches a label. Its
+argument can be used in testing on topeltsize and
+fallthrough. When this pattern is specified, the label
+should be defined explicitly with a <i>labeldef</i>
+statement.</small></p>
+
+<p><small>Following the EM-pattern there may be more than
+one code rule, <i>cg</i> will choose using heuristics and
+the cost information provided with the instruction and token
+definitions. Owing to parsing reasons of the table, the word
+<i>with</i> (see below) is mandatory when there are more
+code rules attached to one EM-pattern. The stack pattern may
+be empty however.</small></p>
+<a name="5.9.2. The stack pattern"></a>
+<h2>5.9.2. The stack pattern</h2>
+
+<p><small>The optional stack pattern is a list of token
+sets preceded by the word <i>with</i>. The token sets are
+usually represented by set identifiers for clarity. No
+boolean expression is allowed here. The first expression is
+the one that matches the top of the stack.</small></p>
+
+<p><small>If the pattern is followed by the word STACK it
+only matches if there is nothing else on the fake stack, and
+the code generator will stack everything not matched at the
+start of the rule.</small></p>
+
+<p><small>The pattern can be preceded with the word
+<i>exact</i> following the <i>with</i> that tells the code
+generator not to try to coerce to the pattern but only to
+use it when it is already present on the fake stack. There
+are two reasons for this construction, correctness and
+speed. It is needed for correctness when the pattern
+contains a register that is not transparent when data is
+moved through it.</small></p>
+
+<p><small>Example: on the PDP-11 the shortest code
+for</small></p>
+<pre><small><b>     lae</b> a
+<b>     loi</b> 8
+<b>     lae</b> b
+<b>     sti</b> 8
+</small></pre>
+
+<p><small>is</small></p>
+<pre><small>     movf _a,fr0
+     movf fr0,_b
+</small></pre>
+
+<p><small>if the floating point processor is in double
+precision mode and fr0 is free. Unfortunately this is not
+correct since a trap can occur on certain kinds of data.
+This could happen if there was a stack pattern for
+<b>sti</b> 8 like this:</small></p>
+<pre><small>     with DBLREG
+</small></pre>
+
+<p><small>The code generator would then find that coercing
+the 8-byte global _a to a floating point register and then
+storing it to _b was the cheapest, if the space/time knob
+was turned far enough to space. This can be prevented by
+changing the stack pattern to</small></p>
+<pre><small>     with exact DBLREG
+</small></pre>
+
+<p><small>It is unfortunate that the type information is no
+longer present, since if _a really is a floating point
+number the move could be made without error.</small></p>
+
+<p><small>The second reason for the <i>exact</i> construct
+is speed. When the code generator has a long list of
+possible stack patterns for one EM pattern it can waste much
+time trying to find coercions to all of them, while the mere
+presence of such a long list indicates that the table writer
+has given many special cases. Prepending all the special
+cases by <i>exact</i> will stop the code generator from
+trying to find things that either cannot be done, or are too
+expensive anyway.</small></p>
+
+<p><small>So in general it is wise to prepend all stack
+patterns that cannot be made by coercions with
+<i>exact</i>.</small></p>
+
+<p><small>Using both <i>exact</i> and STACK in the stack
+pattern has the effect that the rule will only be taken if
+there is nothing else on the fake stack.</small></p>
+<a name="5.9.3. The kills part"></a>
+<h2>5.9.3. The kills part</h2>
+
+<p><small>The optional kills part describes certain tokens
+that should neither remain on the fake stack, nor remembered
+as contents of registers. This is usually only required with
+store operations. The entire fake stack, except for the part
+matched in the stack pattern, is searched for tokens
+matching the expression and they are copied to the real
+stack. Every register that contains the token is marked as
+empty.</small></p>
+
+<p><small>Syntax is</small></p>
+<pre><small>     kills &lt;list of things to kill separated by commas&gt;
+     thing to kill : token set optionally followed by boolean expression
+</small></pre>
+
+<p><small>Example:</small></p>
+<pre><small>     kills regind2 %reg != lb || %off == $1
+</small></pre>
+
+<p><small>is a kills part used for example in the
+<b>inl</b> or <b>stl</b> code rule. It removes all register
+offsetted tokens where the register is not the localbase
+plus the local in which the store is done. The necessity for
+this can be seen from the following example:</small></p>
+<pre><small><b>     lol</b> 4
+<b>     inl</b> 4
+<b>     stl</b> 6
+</small></pre>
+
+<p><small>Without a proper kills part in the rule for
+<b>inl</b> code would be generated as here</small></p>
+<pre><small>     inc 4(r5)
+     mov 4(r5),6(r5)
+</small></pre>
+
+<p><small>so local 6 would be given the new value of local
+4 instead of the old as the EM code prescribed.</small></p>
+
+<p><small>When generating code for an EM-instruction like
+<b>sti</b> it is necessary to write a line in the table
+like</small></p>
+<pre><small>     kills all_except_constant_or_register
+</small></pre>
+
+<p><small>where the long identifier is a set containing all
+tokens that can be the destination of some random indirect
+store. These indirect stores are the main reason to prevent
+this <i>kills</i> line to be deduced automatically by
+<i>cgg</i>.</small></p>
+
+<p><small>When generating something like a branch
+instruction it might be needed to empty the fake stack
+completely. This can of course be done with</small></p>
+<pre><small>     kills ALL
+</small></pre>
+
+<p><small>or by ending the stack pattern with the word
+STACK, if the stack pattern does not start with
+<i>exact</i>. The latter does not erase the contents of
+registers.</small></p>
+
+<p><small>It is unfortunate that this part is still present
+in the table but it is too much for now to let the
+<i>cgg</i> program discover what rules ruin what kind of
+tokens. Maybe some day .....</small></p>
+<a name="5.9.4. The allocates part"></a>
+<h2>5.9.4. The allocates part</h2>
+
+<p><small>The optional register allocation part describes
+the registers needed. Syntax is</small></p>
+<pre><small>     uses &lt;list of use elements separated by commas&gt;
+</small></pre>
+
+<p><small>where itemlist is a list of three kinds of
+things:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small><i>reusing</i> &lt; a token description &gt;, for
+example %1.</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will instruct the code generator that all
+registers contained in this token can be reused if they are
+not used in another token on the fakestack, so that they are
+available for allocation in this <i>uses</i> line if they
+were only used in that token. See example below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="40%">
+
+<p><small>a register property.</small></p>
+</td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will allocate a register with that property,
+that is marked as empty at this point. Look ahead can be
+performed if there is more than one register
+available.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p><small>a register property with
+initialization.</small></p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This will allocate the register as in 2) but will
+also initialize it. This eases the task of the code
+generator because it can find a register already filled with
+the right value if it exists.</small></p>
+</td>
+</table>
+
+<p><small>Examples:</small></p>
+<pre><small>     uses ODDREG
+</small></pre>
+
+<p><small>will allocate an odd register, while</small></p>
+<pre><small>     uses REG={regind2,lb,$1}
+</small></pre>
+
+<p><small>will allocate a register while simultaneously
+filling it with the asked value.<br>
+Inside the coercion from xsrc2 to REG in the PDP-11 table
+the following line can be found.</small></p>
+<pre><small>     uses reusing %1, REG=%1
+</small></pre>
+
+<p><small>This tells the code generator that registers
+contained in %1 can be used again and asks to fill the
+register allocated with %1. So if
+%1={regind2,r3,&quot;4&quot;} and r3 is not in use elsewhere
+on the fake stack the following code might be
+generated.</small></p>
+<pre><small>     mov 4(r3),r3
+</small></pre>
+
+<p><small>In the rest of the line the registers allocated
+can be named by %a and %b.1,%b.2, i.e. with lower case
+letters in order of allocation.</small></p>
+<a name="5.9.5. The generates part"></a>
+<h2>5.9.5. The generates part</h2>
+
+<p><small>Code to be generated, also optionally, is
+specified as the word <i>gen</i> followed by a list of items
+of the following kind:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>An instruction name followed by a comma-separated
+list of token descriptions. <i>Cgg</i> will search the
+instruction definitions for the machine to find a suitable
+instruction. At code generation time the assembler name of
+the instruction will be output followed by a space, followed
+by a comma separated list of tokens.</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>In the table an instruction without operands must
+be followed by a period. The author of <i>cgg</i> could not
+get <i>yacc</i> to accept his syntax without it. Sorry about
+this.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="88%">
+
+<p><small>a <i>move</i> call. This has the following
+syntax:</small></p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><small>     move &lt;token description&gt;,&lt;token description&gt;
+</small></pre>
+<!-- INDENTATION -->
+<p><small>Moves are handled specially since that enables the
+code generator to keep track of register contents.
+Example:</small></p>
+<!-- INDENTATION -->
+<pre><small>     move r3,{regind2,lb,$1}
+</small></pre>
+<!-- INDENTATION -->
+<p><small>will generate code to move r3 to $1(r5) except
+when r3 already was a copy of $1(r5). Then the code will be
+omitted. The rules describing how to move things to each
+other can be found in the move definitions section described
+below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>For machines that have condition codes, which
+alas most of them do, there are provisions to remember
+condition code settings and prevent needless testing. To set
+the condition code to a token put in the code the following
+call:</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><small>     test &lt;token description&gt;
+</small></pre>
+<!-- INDENTATION -->
+<p><small>This will generate a test if the condition codes
+were not already set to that token. The rules describing how
+to test things can be found in the test definitions section
+described below. See also the :cc qualifier that can be used
+at instruction definition time.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>The <i>return</i> statement. Only used when
+register variables are in use. This statement causes a call
+to the machine dependent C-routine <i>regreturn</i>.
+Explanation of this must wait for the description of the
+file mach.c below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>The <i>labeldef</i> statement. Its only argument
+should be that of the <i>lab</i> pseudo-instruction. This is
+needed to generate local labels when the top element size
+information is used. It takes the form</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>labeldef $i</small></p>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>A temporary label of the form &lt;digit&gt;: may
+be placed here. Expressions of the form [0-9][bf] in this
+code rule generate the same string as is used for this
+label. The code generator system could probably easily be
+changed to make this work for assemblers that do not support
+this type of label by generating unique labels itself.
+Implementation of this is not contemplated at the
+moment.</small></p>
+</td>
+</table>
+<a name="5.9.6. Stack replacement"></a>
+<h2>5.9.6. Stack replacement</h2>
+
+<p><small>The optional stack replacement is a possibly
+empty list of tokens to be pushed onto the fake stack. It
+start with the word <i>yields</i>, and is followed by a list
+of token descriptions.</small></p>
+
+<p><small>All tokens matched by the stack pattern at the
+beginning of the code rule are first removed and their
+registers deallocated. Items are pushed in the order of
+appearance. This means that the last item will be on the top
+of the stack after the push. So if the stack pattern
+contained two sets and they must be pushed back unchanged,
+they have to be specified as stack replacement</small></p>
+<pre><small>     yields %2 %1
+</small></pre>
+
+<p><small>and not the other way around. This is known to
+cause errors in tables so watch out for this!</small></p>
+<a name="5.9.7. EM replacement"></a>
+<h2>5.9.7. EM replacement</h2>
+
+<p><small>In exceptional cases it might be useful to leave
+part of an EM-pattern undone. For example, a <b>sdl</b>
+instruction might be split into two <b>stl</b> instructions
+when there is no 4-byte quantity on the stack. The EM
+replacement part allows one to express this. It is activated
+by the word <i>leaving</i>.</small></p>
+
+<p><small>Example:</small></p>
+<pre><small>     leaving <b>stl</b> $1 <b>stl</b> $1+2
+</small></pre>
+
+<p><small>The instructions are inserted in the stream so
+that they can match the first part of a pattern in the next
+step. Note that since the code generator traverses the EM
+instructions in a strict linear fashion, it is impossible to
+let the EM replacement match later parts of a pattern. So if
+there is a pattern</small></p>
+<pre><small><b>     loc stl</b> $1==0
+</small></pre>
+
+<p><small>and the input is</small></p>
+<pre><small><b>     loc</b> 0 <b>sdl</b> 4
+</small></pre>
+
+<p><small>the <b>loc</b> 0 will be processed first, then
+the <b>sdl</b> might be split into two <b>stl</b>&rsquo;s
+but the pattern cannot match now.</small></p>
+<a name="5.9.8. Examples"></a>
+<h2>5.9.8. Examples</h2>
+
+<p><small>A list of examples for the PDP-11 is given here.
+Far from being complete it gives examples of most kinds of
+instructions.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>pat loc</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {const2, $1}</small></p>
+
+<p><small>pat ldc</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {const2, loww($1)} {const2,
+highw($1)}</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>These simple patterns just push one or more
+tokens onto the fake stack.</small></p>
+<pre><small>     pat lof
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>with REG</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regind2,%1,$1}<br>
+with exact regconst2</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regind2,%1.reg,$1+%1.off}<br>
+with exact addr_external</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {relative2,$1+%1.off}<br>
+with exact addr_local</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {LOCAL, %1.ind + $1,2}</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>This pattern shows the possibility to do
+different things depending on the fake stack contents, there
+are some rules for some specific cases plus a general rule,
+not preceded by <i>exact</i> that can always be taken after
+a coercion, if necessary.</small></p>
+<pre><small>     pat lxl $1&gt;3
+     uses REG={LOCAL, SL, 2}, REG={const2,$1-1}
+     gen 1:
+         move {regind2,%a, SL},%a
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>sob %b,{label,1b}</small></p>
+<td width="17%"></td>
+<td width="50%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>This rule shows register allocation with
+initialisation, and the use of a temporary label. The
+constant SL used here is defined to be the offset from lb of
+the static link, that is pushed by the Pascal compiler as
+the last argument of a function.</small></p>
+<pre><small>     pat stf
+     with regconst2 xsrc2
+       kills allexeptcon
+       gen move %2,{regind2,%1.reg,$1+%1.off}
+     with addr_external xsrc2
+       kills allexeptcon
+       gen move %2,{relative2,$1+%1.off}
+</small></pre>
+
+<p><small>This rule shows the use of a <i>kills</i> part in
+a store instruction. The set allexeptcon contains all tokens
+that can be the destination of an indirect
+store.</small></p>
+<pre><small>     pat sde
+     with exact FLTREG
+       kills posextern
+       gen move %1,{relative4,$1}
+     with exact ftolong
+       kills posextern
+       gen setl.
+           movfi %1.reg,{relative4,$1}
+           seti.
+     with src2 src2
+       kills posextern
+       gen move %1, {relative2, $1 }
+           move %2, {relative2, $1+2}
+</small></pre>
+
+<p><small>The rule for <b>sde</b> shows the use of the
+<i>exact</i> clause in both qualities, the first is for
+correctness, the second for efficiency. The third rule is
+taken by default, resulting in two separate stores, nothing
+better exists on the PDP-11.</small></p>
+<pre><small>     pat sbi $1==2
+     with src2 REG
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen sub %1,%2</small></p>
+<td width="13%"></td>
+<td width="54%">
+
+<p><small>yields %2</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>with exact REG src2-REG<br>
+gen sub %2,%1</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>neg %1</small></p>
+<td width="21%"></td>
+<td width="46%">
+
+<p><small>yields %1</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>This rule for <i>sbi</i> has a normal first part,
+and a hand optimized special case as its second
+part.</small></p>
+<pre><small>     pat mli $1==2
+     with ODDREG src2
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen mul %2,%1</small></p>
+<td width="13%"></td>
+<td width="54%">
+
+<p><small>yields %1</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>with src2 ODDREG</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen mul %1,%2</small></p>
+<td width="13%"></td>
+<td width="54%">
+
+<p><small>yields %2</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>This shows the general property for rules with
+commutative operators, heuristics or look ahead will have to
+decide which rule is the best.</small></p>
+<pre><small>     pat loc sli $1==1 &amp;&amp; $2==2
+     with REG
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen asl %1</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %1</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>A simple rule involving a longer EM-pattern, to
+make use of a specialized instruction available.</small></p>
+<pre><small>     pat loc loc cii $1==1 &amp;&amp; $2==2
+     with src1or2
+     uses reusing %1,REG
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen movb %1,%a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>A somewhat more complicated example of the same.
+Note the <i>reusing</i> clause.</small></p>
+<pre><small>     pat loc loc loc cii $1&gt;=0 &amp;&amp; $2==2 &amp;&amp; $3==4
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>leaving loc $1 loc 0</small></p>
+</table>
+
+<p><small>Shows a trivial example of EM-replacement. This
+is a rule that could be done by the peephole optimizer, if
+word order in longs was defined in EM. On a
+&lsquo;big-endian&rsquo; machine the two replacement
+instructions would be the other way around.</small></p>
+<pre><small>     pat and $1==2
+     with const2 REG
+       gen bic {const2,~%1.num},%2yields %2
+     with REG const2
+       gen bic {const2,~%2.num},%1yields %1
+     with REG REG
+       gen com %1
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>bic %1,%2</small></p>
+<td width="21%"></td>
+<td width="46%">
+
+<p><small>yields %2</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>Shows the way to handle the absence of an
+<i>and</i>-instruction.</small></p>
+<pre><small>     pat set $1==2
+     with REG
+     uses REG={const2,1}
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen ash %1,%a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>Shows the building of a word-size
+set.</small></p>
+<pre><small>     pat lae aar $2==2 &amp;&amp; rom($1,3)==1 &amp;&amp; rom($1,1)==0
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>leaving adi 2</small></p>
+</table>
+
+<p><small>pat lae aar $2==2 &amp;&amp; rom($1,3)==1
+&amp;&amp; rom($1,1)!=0</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>leaving adi 2 adp 0-rom($1,1)</small></p>
+</table>
+
+<p><small>Two rules showing the use of the rom pseudo
+function, and some array optimalisation.</small></p>
+<pre><small>     pat bra
+     with STACK
+     gen jbr {label, $1}
+</small></pre>
+
+<p><small>A simple jump. The stack pattern guarantees that
+everything will be stacked before the jump is
+taken.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="11" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>pat lab</small></p>
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>topeltsize($1)==2 &amp;&amp; !fallthrough($1)<br>
+gen labeldef $1</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>yields r0</small></p>
+
+<p><small>pat lab</small></p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>topeltsize($1)==2 &amp;&amp;
+fallthrough($1)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+</table>
+
+<p><small>with src2<br>
+gen move %1,r0</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="9" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>labeldef $1</small></p>
+<td width="17%"></td>
+<td width="2%">
+</td>
+<td width="30%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>yields r0</small></p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+</table>
+
+<p><small>pat lab topeltsize($1)!=2<br>
+with STACK<br>
+kills all<br>
+gen labeldef $1</small></p>
+
+<p><small>pat bra topeltsize($1)==2<br>
+with src2 STACK<br>
+gen move %1,d0</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>jbr {label, $1}</small></p>
+</table>
+
+<p><small>pat bra topeltsize($1)!=2<br>
+with STACK<br>
+gen jbr {label, $1}</small></p>
+
+<p><small>The combination of these patterns make sure that
+the top of the EM-stack will be in register r0 whenever
+necessary. The top element size mechanism will also show a
+size of 0 whenever a conditional branch to a label occurs.
+This saves a lot of patterns and hardly decreases
+performance. When the same register is used to return
+function results, this can save many moves to and from the
+stack.</small></p>
+<pre><small>     pat cal
+     with STACK
+     gen jsr pc,{label, $1}
+</small></pre>
+
+<p><small>A simple call. Same comments as previous
+rule.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>pat lfr $1==2</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields r0<br>
+pat lfr $1==4</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields r1 r0</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>Shows the return area conventions of the PDP-11
+table. At this point a reminder: the <b>asp</b> instruction,
+and some other instructions must leave the function return
+area intact. See the defining document for EM for exact
+information.</small></p>
+<pre><small>     pat ret $1==0
+     with STACK
+     gen mov lb,sp
+         rts pc
+</small></pre>
+
+<p><small>This shows a rule for <b>ret</b> in a table not
+using register variables. In a table with register variables
+the <i>gen</i> part would just contain
+<i>return</i>.</small></p>
+<pre><small>     pat blm
+     with REG REG
+     uses REG={const2,$1/2}
+     gen 1:
+         mov {autoinc,%2},{autoinc,%1}
+         sob %a,{label,1b}
+</small></pre>
+
+<p><small>This rule for <b>blm</b> already uses three
+registers of the same type. <i>Cgg</i> contains code to
+check all rules to see if they can be applied from an empty
+fakestack. It uses the marriage thesis from Hall, a thesis
+from combinatorial mathematics, to accomplish
+this.</small></p>
+<pre><small>     pat exg $1==2
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>with src2 src2</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %1 %2</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>This rule shows the exchanging of two elements on
+the fake stack.</small></p>
+<a name="5.10. Code rules using procedures"></a>
+<h2>5.10. Code rules using procedures</h2>
+
+<p><small>To start this section it must be admitted at once
+that the word procedure is chosen here mainly for its
+advertising value. It more resembles a glorified goto but
+this of course can not be admitted in the glossy brochures.
+This document will continue to use the word
+procedure.</small></p>
+
+<p><small>The need for procedures was felt after the first
+version of the code generator system was made, mainly
+because of conditional instructions. Often the code
+sequences for <b>tlt</b>, <b>tle</b>, <b>teq</b>,
+<b>tne</b>, <b>tge</b> and <b>tgt</b> were identical apart
+from one opcode in the code rule. The code sequence had to
+be written out six times however. Not only did this increase
+the table size and bore the table writer, it also led to
+errors when changing the table since it happened now and
+then that five out of six rules were changed.</small></p>
+
+<p><small>In general the procedures in this table format
+are used to keep one copy instead of six of the code rules
+for all sorts of conditionals and one out of two for things
+like increment/decrement.</small></p>
+
+<p><small>And now the syntax, first the procedure
+definition, which must indeed be defined before the call
+because <i>cgg</i> is one-pass. The procedure heading
+replaces the EM-pattern in a code rule and looks like
+this:</small></p>
+<pre><small>     proc &lt;identifier&gt; &lt;optional example&gt;
+</small></pre>
+
+<p><small>The identifier is used in later calls and the
+example must be used if expressions like $1 are used in the
+code rule.</small></p>
+<pre><small>     &lt;optional example&gt; : example &lt;list of EM-instructions&gt;
+</small></pre>
+
+<p><small>so an example looks just like an EM-pattern, but
+without the optional boolean expression. The example is
+needed to know the types of $1 expressions. The current
+version of <i>cgg</i> does not check correctness of the
+example, so be careful.</small></p>
+
+<p><small>A procedure is called with string-parameters,
+that are assembler opcodes. They can be accessed by
+appending the string &lsquo;[&lt;number&gt;]&rsquo; to a
+table opcode, where &lt;number&gt; is the parameter number.
+The string &lsquo;*&rsquo; can be used as an equivalent for
+&lsquo;[1]&rsquo;. Just in case this is not clear, here is
+an example for a procedure to increment/decrement a
+register.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>incop REG:rw:cc .</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>/* in the INSTRUCTIONS part of course
+*/</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>proc incdec<br>
+with REG</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen incop* %1</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %1</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>The procedure is called with parameter
+&quot;inc&quot; or &quot;dec&quot;.</small></p>
+
+<p><small>The procedure call is given instead of the
+code-part of the code rule and looks like this</small></p>
+<pre><small>     call &lt;identifier&gt; &rsquo;(&rsquo; &lt;comma-separated list of strings&gt; &rsquo;)&rsquo;
+</small></pre>
+
+<p><small>which leads to the following large
+example:</small></p>
+<pre><small>     proc bxx example beq
+     with src2 src2 STACK
+     gen cmp %2,%1
+         jxx* {label, $1}
+
+
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>pat blt</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jlt&quot;)<br>
+pat ble</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jle&quot;)<br>
+pat beq</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jeq&quot;)<br>
+pat bne</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jne&quot;)<br>
+pat bgt</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jgt&quot;)<br>
+pat bge</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>call bxx(&quot;jge&quot;)</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+<a name="5.11. Move definitions"></a>
+<h2>5.11. Move definitions</h2>
+
+<p><small>We now jump back to near the beginning of the
+table where the move definitions are found. The move
+definitions directly follow the instruction
+definitions.</small></p>
+
+<p><small>In certain cases a move is called for, either
+explicitly when a <i>move</i> instruction is used in a code
+rule, or implicitly in a register initialization. The
+different code rules possible to move data from one spot to
+another are described here. Example for the
+PDP-11:</small></p>
+<pre><small>     MOVES
+
+
+     from const2 %num==0 to dst2
+     gen clr %2
+
+
+     from src2 to dst2
+     gen mov %1,%2
+
+
+     from FLTREG to longf4-FLTREG
+     gen movfo %1,%2
+
+
+     from longf4-FLTREG to FLTREG
+     gen movof %1,%2
+</small></pre>
+
+<p><small>The example shows that the syntax is
+just</small></p>
+<pre><small>     from &lt;source&gt; to &lt;destination&gt; gen &lt;list of instructions&gt;
+</small></pre>
+
+<p><small>Source and destination are a token set,
+optionally followed by a boolean expression. The code
+generator will take the first move that matches, whenever a
+move is necessary. <i>Cgg</i> checks whether all moves
+called for in the table are present.</small></p>
+<a name="5.12. Test definitions"></a>
+<h2>5.12. Test definitions</h2>
+
+<p><small>This part describes the instructions necessary to
+set the condition codes to a certain token. These rules are
+needed when the <i>test</i> instruction is used in code
+rules. Example for the PDP-11:</small></p>
+<pre><small>     TESTS
+
+
+     to test src2
+     gen tst %1
+</small></pre>
+
+<p><small>So syntax is just</small></p>
+<pre><small>     to test &lt;source&gt; gen &lt;instruction list&gt;
+</small></pre>
+
+<p><small>Source is the same thing as in the move
+definition. <i>Cgg</i> checks whether all tests called for
+in the table are present.</small></p>
+<a name="5.13. Some explanation about the rules behind coercions"></a>
+<h2>5.13. Some explanation about the rules behind coercions</h2>
+
+<p><small>A central part in code generation is taken by the
+<i>coercions</i>. It is the responsibility of the table
+writer to provide all necessary coercions so that code
+generation can continue. The minimal set of coercions are
+the coercions to unstack every token expression, in
+combination with the rules to stack every token. It should
+not be possible to smuggle a table through <i>cgg</i>
+without these basic set available.</small></p>
+
+<p><small>If these are present the code generator can
+always make the necessary transformations by stacking and
+unstacking. Of course for code quality it is usually best to
+provide extra coercions to prevent this stacking to take
+place. <i>Cg</i> discriminates three types of
+coercions:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Unstacking coercions. This category can use the
+<i>uses</i> clause in its code.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Splitting coercions, these are the coercions that
+split larger tokens into smaller ones.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Transforming coercions, these are the coercions
+that transform a token into another of the same size. This
+category can use the <i>uses</i> clause in its
+code.</small></p>
+</td>
+</table>
+
+<p><small>When a stack configuration does not match the
+stack pattern <i>coercions</i> are searched for in the
+following order:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>First tokens are split if necessary to get their
+sizes right.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Then transforming coercions are found that will
+make the pattern match.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Finally if the stack pattern is longer than the
+fake stack contents unstacking coercions will be used to
+fill up the pattern.</small></p>
+</td>
+</table>
+
+<p><small>At any point, when coercions are missing so code
+generation could not continue, the offending tokens are
+stacked.</small></p>
+<a name="5.14. Stack definitions"></a>
+<h2>5.14. Stack definitions</h2>
+
+<p><small>The next part of the table defines the stacking
+rules for the machine. Each token that may reside on the
+fake stack must have a rule attached to put it on the real
+stack. Example for the PDP-11:</small></p>
+<pre><small>     STACKINGRULES
+
+
+     from const2 %num==0 to STACK
+     gen clr {autodec,sp}
+
+
+     from src2 to STACK
+     gen mov %1,{autodec,sp}
+
+
+     from regconst2 to STACK
+     gen mov %1.reg,{autodec,sp}
+         add {addr_external, %1.off},{regdef2,sp}
+
+
+     from DBLREG to STACK
+     gen movf %1,{autodec,sp}
+
+
+     from FLTREG  to STACK
+     gen movfo %1,{autodec,sp}
+
+
+     from regind8 to STACK
+     uses REG
+     gen move %1.reg,%a
+         add {addr_external, 8+%1.off},%a
+         mov {autodec, %a},{autodec,sp}
+         mov {autodec, %a},{autodec,sp}
+         mov {autodec, %a},{autodec,sp}
+         mov {autodec, %a},{autodec,sp}
+</small></pre>
+
+<p><small>These examples should be self-explanatory, except
+maybe for the last one. It is possible inside a
+stacking-rule to use a register. Since however the stacking
+might also take place at a moment when no registers are
+free, it is mandatory that for each token there is one
+stackingrule that does not use a register. The code
+generator uses the first rule possible.</small></p>
+<a name="5.15. Coercions"></a>
+<h2>5.15. Coercions</h2>
+
+<p><small>The next part of the table defines the coercions
+that are possible on the defined tokens. Example for the
+PDP-11:</small></p>
+<pre><small>     COERCIONS
+
+
+     from STACK
+     uses REG
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen mov {autoinc,sp},%a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from STACK<br>
+uses DBLREG</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen movf {autoinc,sp},%a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from STACK<br>
+uses REGPAIR<br>
+gen mov {autoinc,sp},%a.1</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>mov {autoinc,sp},%a.2</small></p>
+<td width="17%"></td>
+<td width="50%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>These three coercions just deliver a certain type
+of register by popping it from the real stack.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>from LOCAL</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regind2,lb,%1.ind}</small></p>
+
+<p><small>from DLOCAL</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regind4,lb,%1.ind}</small></p>
+
+<p><small>from REG</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regconst2, %1, 0}</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>These three are zero-cost rewriting
+rules.</small></p>
+<pre><small>     from regconst2 %1.off==1
+     uses reusing %1,REG=%1.reg
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen inc %a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from regconst2<br>
+uses reusing %1,REG=%1.reg<br>
+gen add {addr_external, %1.off},%ayields %a</small></p>
+
+<p><small>from addr_local<br>
+uses REG<br>
+gen mov lb,%a</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>add {const2, %1.ind},%a</small></p>
+<td width="17%"></td>
+<td width="50%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>The last three are three different cases of the
+coercion register+constant to register. Only in the last
+case is it always necessary to allocate an extra register,
+since arithmetic on the localbase is
+unthinkable.</small></p>
+<pre><small>     from xsrc2
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>uses reusing %1, REG=%1</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from longf4</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>uses FLTREG=%1</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from double8</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>uses DBLREG=%1</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>from src1<br>
+uses REG={const2,0}</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>gen bisb %1,%a</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %a</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>These examples show the coercion of different
+tokens to a register of the needed type. The last one shows
+the trouble needed on a PDP-11 to ensure bytes are not
+sign-extended. In EM it is defined that the result of a
+<b>loi</b> 1 instruction is an integer in the range
+0..255.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>from REGPAIR</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields %1.2 %1.1</small></p>
+
+<p><small>from regind4</small></p>
+</td>
+<td width="32%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {regind2,%1.reg,2+%1.off}</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>{regind2,%1.reg,%1.off}</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><small>from relative4</small></p>
+<td width="9%"></td>
+<td width="58%">
+
+<p><small>yields {relative2,2+%1.off}</small></p>
+</td>
+<td width="32%">
+</td>
+</table>
+
+<p><small>{relative2,%1.off}</small></p>
+
+<p><small>The last examples are splitting
+rules.</small></p>
+
+<p><small>The examples show that all coercions change one
+token on the fake stack into one or more others, possibly
+generating code. The STACK token is supposed to be on the
+fake stack when it is really empty, and can only be changed
+into one other token.</small></p>
+<a name="6. The files mach.h and mach.c"></a>
+<h2>6. The files mach.h and mach.c</h2>
+
+<p><small>The table writer must also supply two files
+containing machine dependent declarations and C code. These
+files are mach.h and mach.c.</small></p>
+<a name="6.1. Types in the code generator"></a>
+<h2>6.1. Types in the code generator</h2>
+
+<p><small>Three different types of integer coexist in the
+code generator and their range depends on the machine at
+hand. They are defined depending on the Target EM_WSIZE, or
+TEM_WSIZE, and TEM_PSIZE. The type &rsquo;int&rsquo; is used
+for things like counters that won&rsquo;t require more than
+16 bits precision. The type &rsquo;word&rsquo; is used among
+others to assemble datawords and is of type
+&rsquo;long&rsquo;. The type &rsquo;full&rsquo; is used for
+addresses and is of type &rsquo;long&rsquo; if
+TEM_WSIZE&gt;2 or TEM_PSIZE&gt;2.</small></p>
+
+<p><small>In macro and function definitions in later
+paragraphs implicit typing will be used for parameters, that
+is parameters starting with an &rsquo;s&rsquo; will be of
+type string, and the letters
+&rsquo;i&rsquo;,&rsquo;w&rsquo;,&rsquo;f&rsquo; will stand
+for int, word and full respectively.</small></p>
+<a name="6.2. Global variables to work with"></a>
+<h2>6.2. Global variables to work with</h2>
+
+<p><small>Some global variables are present in the code
+generator that can be manipulated by the routines in mach.h
+and mach.c.</small></p>
+
+<p><small>The declarations are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>FILE *codefile;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* code is emitted on this stream */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>word part_word;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* words to be output are put together here
+*/</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>int part_size;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* number of bytes already put in part_word
+*/</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>char str[];</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* Last string read in */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="40%">
+
+<p><small>long argval;</small></p>
+</td>
+<td width="60%">
+
+<p><small>/* Last int read and kept */</small></p>
+</td>
+</table>
+<a name="6.3. Macros in mach.h"></a>
+<h2>6.3. Macros in mach.h</h2>
+
+<p><small>In the file mach.h a collection of macros is
+defined that have to do with formatting of assembly code for
+the machine at hand. Some of these macros can of course be
+left undefined in which case the macro calls are left in the
+source and will be treated as function calls. These
+functions can then be defined in <i>mach.c</i>.</small></p>
+
+<p><small>The macros to be defined are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>ex_ap(s)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must print the magic incantations that will mark
+the symbol to be exported to other modules. This is the
+translation of the EM <b>exa</b> and <b>exp</b>
+instructions.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>in_ap(s)</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Same to import the symbol. Translation of
+<b>ina</b> and <b>inp</b>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newplb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of procedure label
+<i>s</i>. If left undefined the newilb() macro is used
+instead.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newilb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of instruction label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>newdlb(s)</small></p>
+</td>
+<td width="14%"></td>
+<td width="68%">
+
+<p><small>Must print the definition of data label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p><small>dlbdlb(s1,s2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><small>Must define data label <i>s1</i> to be equal to
+<i>s2</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p><small>newlbss(s,f)</small></p>
+</td>
+<td width="8%"></td>
+<td width="68%">
+
+<p><small>Must declare a piece of memory initialized to
+BSS_INIT(see below) of length <i>f</i> and with label
+<i>s</i>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>cst_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used when converting constant
+arguments of EM instructions to string. Argument to be
+formatted will be &rsquo;full&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>off_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for integer part of
+label+constant, argument will be
+&rsquo;full&rsquo;.</small></p>
+</td>
+</table>
+
+<p><small>fmt_ilb(ip,il,s)</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="31%"></td>
+<td width="68%">
+<p><small>Must use the numbers <i>ip</i> and <i>il</i> that
+are a procedure number and a label number respectively and
+copy a string to <i>s</i> that must be unique for that
+combination. This procedure is optional, if it is not given
+ilb_fmt must be defined as below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>ilb_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for creation of unique
+instruction labels. Arguments will be a unique procedure
+number (int) and the label number (int).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>dlb_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for printing numeric data
+labels. Argument will be &rsquo;int&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>hol_fmt</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for generation of labels for
+space generated by a <b>hol</b> pseudo. Argument will be
+&rsquo;int&rsquo;.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>hol_off</small></p>
+</td>
+<td width="18%"></td>
+<td width="68%">
+
+<p><small>Format to be used for printing of the address of
+an element in <b>hol</b> space. Arguments will be the offset
+in the <b>hol</b> block (word) and the number of the
+<b>hol</b> (int).</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_cst(w)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will assemble into one
+machine word.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_ilb(s)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will put the address of
+the instruction label into the datastream.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><small>con_dlb(s)</small></p>
+</td>
+<td width="12%"></td>
+<td width="68%">
+
+<p><small>Must generate output that will put the address of
+the data label into the datastream.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p><small>fmt_id(sf,st)</small></p>
+</td>
+<td width="6%"></td>
+<td width="68%">
+
+<p><small>Must take the string in <i>sf</i> that is a
+nonnumeric global label, and transform it into a copy made
+to <i>st</i> that will not collide with reserved assembler
+words and system labels. This procedure is optional, if it
+is not given the id_first macro is used as defined
+below.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>id_first</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must be a character. This is prepended to all
+nonnumeric global labels if their length is shorter than the
+maximum allowed(currently 8) or if they already start with
+that character. This is to avoid conflicts of user labels
+with system labels.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>BSS_INIT</small></p>
+</td>
+<td width="16%"></td>
+<td width="68%">
+
+<p><small>Must be a constant. This is the value filled in
+all the words not initialized explicitly. This is loader and
+system dependent. If omitted no initialization is
+assumed.</small></p>
+</td>
+</table>
+<a name="6.3.1. Example mach.h for the PDP-11"></a>
+<h2>6.3.1. Example mach.h for the PDP-11</h2>
+<pre><small>#define ex_ap(y)fprintf(codefile,&quot;\t.globl %s\n&quot;,y)
+#define in_ap(y)/* nothing */
+
+
+#define newplb(x)fprintf(codefile,&quot;%s:\n&quot;,x)
+#define newilb(x)fprintf(codefile,&quot;%s:\n&quot;,x)
+#define newdlb(x)fprintf(codefile,&quot;%s:\n&quot;,x)
+#define dlbdlb(x,y)fprintf(codefile,&quot;%s=%s\n&quot;,x,y)
+#define newlbss(l,x)fprintf(codefile,&quot;%s:.=.+%d.\n&quot;,l,x);
+
+
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define cst_fmt</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;$%d.&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define off_fmt</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;%d.&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define ilb_fmt</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;I%x_%x&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define dlb_fmt</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;_%d&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define hol_fmt</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;hol%d&quot;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="32%">
+
+<p><small>#define hol_off</small></p>
+</td>
+<td width="68%">
+
+<p><small>&quot;%ld.+hol%d&quot;</small></p>
+</td>
+</table>
+
+<p><small>#define
+con_cst(x)fprintf(codefile,&quot;%ld.\n&quot;,x)<br>
+#define con_ilb(x)fprintf(codefile,&quot;%s\n&quot;,x)<br>
+#define
+con_dlb(x)fprintf(codefile,&quot;%s\n&quot;,x)</small></p>
+
+<p><small>#define id_first&rsquo;_&rsquo;<br>
+#define BSS_INIT0</small></p>
+<a name="6.4. Functions in mach.c"></a>
+<h2>6.4. Functions in mach.c</h2>
+
+<p><small>In mach.c some functions must be supplied, mostly
+manipulating data resulting from pseudoinstructions. The
+specifications are given here, implicit typing of parameters
+as above.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="36%">
+
+<p><small>con_part(isz,word)</small></p>
+</td>
+<td width="53%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function must manipulate the globals
+part_word and part_size to append the isz bytes contained in
+word to the output stream. If part_word is full, i.e.
+part_size==TEM_WSIZE the function part_flush() may be called
+to empty the buffer. This is the function that must go
+through the trouble of doing byte order in words
+correct.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="32%">
+
+<p><small>con_mult(w_size)</small></p>
+</td>
+<td width="57%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function must take the string str[] and
+create an integer from the string of size w_size and
+generate code to assemble global data for that integer. Only
+the sizes for which arithmetic is implemented need be
+handled, so if 200-byte integer division is not implemented,
+200-byte integer global data don&rsquo;t have to be
+implemented. Here one must take care of word order in long
+integers.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p><small>con_float()</small></p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function must generate code to assemble a
+floating point number of which the size is contained in
+argval and the ASCII representation in str[].</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="34%">
+
+<p><small>prolog(f_nlocals)</small></p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function is called at the start of every
+procedure. Function prolog code must be generated, and room
+made for local variables for a total of f_nlocals
+bytes.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="24%">
+
+<p><small>mes(w_mesno)</small></p>
+</td>
+<td width="65%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function is called when a <b>mes</b> pseudo
+is seen that is not handled by the machine independent part.
+The example below shows all one probably have to know about
+that.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="18%">
+
+<p><small>segname[]</small></p>
+</td>
+<td width="71%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This is not a function, but an array of four
+strings. These strings are put out whenever the code
+generator switches segments. Segments are SEGTXT, SEGCON,
+SEGROM and SEGBSS in that order.</small></p>
+</td>
+</table>
+
+<p><small>If register variables are used in a table, the
+program <i>cgg</i> will define the word REGVARS during
+compilation of the sources. So the following functions
+described here should be bracketed by #ifdef REGVARS and
+#endif.</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p><small>regscore(off,size,typ,freq,totyp) long
+off;</small></p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function should assign a score to a register
+variable, the score should preferably be the estimated
+number of bytes gained when it is put in a register. Off and
+size are the offset and size of the variable, typ is the
+type, that is reg_any, reg_pointer, reg_loop or reg_float.
+Freq is the count of static occurrences, and totyp is the
+type of the register it is planned to go into.<br>
+Keep in mind that the gain should be net, that is the cost
+for register save/restore sequences and the cost of
+initialisation in the case of parameters should already be
+included.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p><small>i_regsave()</small></p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function is called at the start of a
+procedure, just before register saves are done. It can be
+used to initialise some variables if needed.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p><small>f_regsave()</small></p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>This function is called at end of the register
+save sequence. It can be used to do the real saving if
+multiple register move instructions are
+available.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>regsave(regstr,off,size) char *regstr; long
+off;</small></p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Should either do the real saving or set up a table
+to have it done by f_regsave. Note that initialisation of
+parameters should also be done, or planned here.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="22%">
+
+<p><small>regreturn()</small></p>
+</td>
+<td width="67%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>Should restore saved registers and return. The
+function result is already in the function return area by
+now.</small></p></td>
+</table>
+<a name="6.4.1. Example mach.c for the PDP-11"></a>
+<h2>6.4.1. Example mach.c for the PDP-11</h2>
+
+<p><small>As an example of the sort of code expected, the
+mach.c for the PDP-11 is presented here.</small></p>
+<pre><small>/*
+ * machine dependent back end routines for the PDP-11
+ */
+
+
+con_part(sz,w) register sz; word w; {
+
+
+</small></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>while (part_size % sz)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>part_size++;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>if (part_size == 2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>part_flush();</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>if (sz == 1) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>w &amp;= 0xFF;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>if (part_size)</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>w &lt;&lt;= 8;</small></p>
+</td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>part_word |= w;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>} else {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>assert(sz == 2);</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>part_word = w;</small></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p><small>part_size += sz;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>con_mult(sz) word sz; {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>long l;</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (sz != 4)</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fatal(&quot;bad icon/ucon
+size&quot;);</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>l = atol(str);</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o\n&quot;,(int)(l&gt;&gt;16),(int)l);</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>con_float() {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>double f;</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>register short *p,i;</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>/*</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>* This code is correct only when the code
+generator is</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>* run on a PDP-11 or VAX-11 since it assumes
+native</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>* floating point format is PDP-11
+format.</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>*/</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (argval != 4 &amp;&amp; argval !=
+8)</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fatal(&quot;bad fcon size&quot;);</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>f = atof(str);</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>p = (short *) &amp;f;</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>i = *p++;</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (argval == 8) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o;&quot;,i,*p++);</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>i = *p++;</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+
+<p><small>fprintf(codefile,&quot;\t%o;%o\n&quot;,i,*p++);</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>#ifdef REGVARS</small></p>
+
+<p><small>char Rstring[10];<br>
+full lbytes;<br>
+struct regadm {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>char *ra_str;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>long ra_off;</small></p>
+</td>
+</table>
+
+<p><small>} regadm[2];<br>
+int n_regvars;</small></p>
+
+<p><small>regscore(off,size,typ,score,totyp) long off;
+{</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="9" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>/*</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>* This function is full of magic
+constants.</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>* They are a result of
+experimentation.</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>*/</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (size != 2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>return(-1);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>score -= 1;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>/* allow for save/restore */</small></p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (off&gt;=0)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>score -= 2;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (typ==reg_pointer)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>score *= 17;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>else if (typ==reg_loop)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>score = 10*score+50;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%">
+
+<p><small>/* Guestimate */</small></p>
+</td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>else</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>score *= 10;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>return(score);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><small>/* 10 * estimated # of words of profit
+*/</small></p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="19%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>i_regsave() {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>Rstring[0] = 0;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>n_regvars=0;</small></p>
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>f_regsave() {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="9" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>register i;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (n_regvars==0 || lbytes==0) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;mov r5,-(sp)\nmov
+sp,r5\n&quot;);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>if (lbytes == 2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;tst
+-(sp)\n&quot;);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>else if (lbytes!=0)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;sub
+$0%o,sp\n&quot;,lbytes);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>for (i=0;i&lt;n_regvars;i++)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;mov
+%s,-(sp)\n&quot;,regadm[i].ra_str);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>} else {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>if (lbytes&gt;6) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;mov
+$0%o,r0\n&quot;,lbytes);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;jsr
+r5,PR%s\n&quot;,Rstring);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>} else {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;jsr
+r5,PR%d%s\n&quot;,lbytes,Rstring);</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>for (i=0;i&lt;n_regvars;i++)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>if (regadm[i].ra_off&gt;=0)</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;mov
+0%lo(r5),%s\n&quot;,regadm[i].ra_off,</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>regadm[i].ra_str);</small></p>
+</td>
+<td width="29%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>regsave(regstr,off,size) char *regstr; long off;
+{</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>fprintf(codefile,&quot;/ Local %ld into
+%s\n&quot;,off,regstr);</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>strcat(Rstring,regstr);</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>regadm[n_regvars].ra_str = regstr;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>regadm[n_regvars].ra_off = off;</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>n_regvars++;</small></p>
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>regreturn() {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>fprintf(codefile,&quot;jmp
+RT%s\n&quot;,Rstring);</small></p>
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>#endif</small></p>
+
+<p><small>prolog(nlocals) full nlocals; {</small></p>
+
+<p><small>#ifndef REGVARS</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;mov r5,-(sp)\nmov
+sp,r5\n&quot;);</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (nlocals == 0)</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>return;</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>if (nlocals == 2)</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;tst
+-(sp)\n&quot;);</small></p>
+</td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>else</small></p>
+</td>
+<td width="10%"></td>
+<td width="69%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;sub
+$0%o,sp\n&quot;,nlocals);</small></p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p><small>#else</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>lbytes = nlocals;</small></p>
+</td>
+</table>
+
+<p><small>#endif<br>
+}</small></p>
+
+<p><small>mes(type) word type; {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>int argt ;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>switch ( (int)type ) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>case ms_ext :</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>for (;;) {</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>switch ( argt=getarg(</small></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) )
+{</small></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>case sp_cend :</small></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>return ;</small></p>
+</td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>default:</small></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>strarg(argt) ;</small></p>
+</td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>fprintf(codefile,&quot;.globl %s\n&quot;,argstr)
+;</small></p>
+</td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>break ;</small></p>
+</td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>default :</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>while ( getarg(any_ptyp) != sp_cend )
+;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><small>break ;</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p><small>}</small></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+
+<p><small>}</small></p>
+
+<p><small>char *segname[] = {</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;.text&quot;, /* SEGTXT */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;.data&quot;, /* SEGCON */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;.data&quot;, /* SEGROM */</small></p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p><small>&quot;.bss&quot; /* SEGBSS */</small></p>
+</td>
+</table>
+
+<p><small>};</small></p>
+<a name="7. Internal workings of the code generator."></a>
+<h2>7. Internal workings of the code generator.</h2>
+<a name="7.1. Description of tables.c and tables.h contents"></a>
+<h2>7.1. Description of tables.c and tables.h contents</h2>
+
+<p><small>In this section the intermediate files will be
+described that are produced by <i>cgg</i> and compiled with
+machine independent code to produce a code
+generator.</small></p>
+<a name="7.1.1. Tables.c"></a>
+<h2>7.1.1. Tables.c</h2>
+
+<p><small>Tables.c contains a large number of initialized
+array&rsquo;s of all sorts. Description of each
+follows:</small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>byte coderules[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Pseudo code interpreted by the code generator.
+Always starts with some opcode followed by operands
+depending on the opcode. Some of the opcodes have an
+argument encoded in the upper three bits of the opcode byte.
+Integers in this table are between 0 and 32767 and have a
+one byte encoding if between 0 and 127.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>char wrd_fmt[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>The format used for output of
+words.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>char stregclass[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Number of computed static register class per
+register. Two registers are in the same class if they have
+the same properties and don&rsquo;t share a common
+subregister.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>struct reginfo machregs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Info per register. Initialized with representation
+string, size, members of the register and set of registers
+affected when this one is changed. Also contains room for
+run time information, like contents and reference
+count.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>tkdef_t tokens[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Information per tokentype. Initialized with size,
+cost, type of operands and formatstring.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>node_t enodes[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of triples representing expressions for the
+code generator.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>string codestrings[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of strings. All strings are put in a list and
+checked for duplication, so only one copy per string will
+reside here.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>set_t machsets[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of token expression sets. Bit 0 of the set is
+used for the SCRATCH property of registers, bit 1 upto NREG
+are for the corresponding registers and bit NREG+1 upto the
+end are for corresponding tokens.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>inst_t tokeninstances[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of descriptions for building tokens. Contains
+type of rule for building one, plus operands depending on
+the type.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>move_t moves[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of move rules. Contains token expressions for
+source and destination plus index for code
+rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>test_t tests[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of test rules. Contains token expressions for
+source plus index for code rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>byte pattern[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>EM patterns. This is structured internally as
+chains of patterns, each chain pointed at by pathash[].
+After each pattern the list of possible code rules is
+given.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>int pathash[256]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>Indices into pattern[] for all patterns with a
+certain low order byte of the hashing
+function.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c1_t c1coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of rules to stack tokens. Contains token
+expressions, register needed, cost and code
+rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c2_t c2coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of splitting coercions. Token expressions,
+split factor, replacements and code rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>c3_t c3coercs[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of one to one coercions. Token expressions,
+register needed, replacement and code rule.</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>struct reginfo **reglist[]</small></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p><small>List of lists of pointers to register information.
+For every property the list is here to find the registers
+corresponding to it.</small></p></td>
+</table>
+<a name="7.1.2. tables.h"></a>
+<h2>7.1.2. tables.h</h2>
+
+<p><small>In tables.h various derived constants for the
+tables are given. They are then used to determine array
+sizes in the actual code generator, plus loop termination in
+some cases.</small></p>
+<a name="7.2. Other important data structures"></a>
+<h2>7.2. Other important data structures</h2>
+
+<p><small>During code generation some other data structures
+are used and here is a short description of some of the
+important ones.</small></p>
+
+<p><small>Tokens are kept in the code generator as a struct
+consisting of one integer <i>t_token</i> which is -1 if the
+token is a register, and the number of the token otherwise,
+plus an array of <i>TOKENSIZE</i> unions <i>t_att</i> of
+which the first is the register number in case of a
+register.</small></p>
+
+<p><small>The fakestack is an array of these tokens, there
+is a global variable <i>stackheight</i>.</small></p>
+
+<p><small>The results of expressions are kept in a struct
+<i>result</i> with elements <i>e_typ</i>, giving the type of
+the expression: <i>EV_INT</i>, <i>EV_REG</i> or
+<i>EV_ADDR</i>, and a union <i>e_v</i> which contains the
+real result.</small></p>
+<a name="7.3. A tour through the sources"></a>
+<h2>7.3. A tour through the sources</h2>
+<a name="7.3.1. codegen.c"></a>
+<h2>7.3.1. codegen.c</h2>
+
+<p><small>The file codegen.c contains one large function
+consisting of one giant switch statement. It is the
+interpreter for the code generator pseudo code as contained
+in code rules[]. This function can call itself recursively
+when doing look ahead. Arguments are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p><small>codep</small></p>
+</td>
+<td width="10%"></td>
+<td width="80%">
+
+<p><small>Pointer into code rules, pseudo program
+counter.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>ply</small></p>
+</td>
+<td width="14%"></td>
+<td width="80%">
+
+<p><small>Number of EM pattern look ahead
+allowed.</small></p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>toplevel</small></p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p><small>Boolean telling whether this is the toplevel
+codegen() or a deeper incarnation.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>costlimit</small></p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p><small>A cutoff value to limit searches. If the cost
+crosses costlimit the incarnation can terminate.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p><small>forced</small></p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p><small>A register number if nonzero. This is used inside
+coercions to force the allocate() call to allocate a
+register determined by earlier look ahead.</small></p>
+</td>
+</table>
+
+<p><small>The instructions inplemented in the
+switch:</small></p>
+<a name="7.3.1.1. DO_DLINE"></a>
+<h2>7.3.1.1. DO_DLINE</h2>
+
+<p><small>Prints debugging information if the code
+generator runs in debug mode. This information is only
+generated if <i>cgg</i> was called with the -d
+flag.</small></p>
+<a name="7.3.1.2. DO_NEXTEM"></a>
+<h2>7.3.1.2. DO_NEXTEM</h2>
+
+<p><small>Matches the next EM pattern and does look ahead
+if necessary to find the best code rule associated with this
+pattern. Heuristics are used to determine best code rule
+when possible. This is done by calling the distance()
+function. It can also handle the procedure
+mechanism.</small></p>
+<a name="7.3.1.3. DO_COERC"></a>
+<h2>7.3.1.3. DO_COERC</h2>
+
+<p><small>This sets the code generator in the state to do a
+from stack coercion.</small></p>
+<a name="7.3.1.4. DO_XMATCH"></a>
+<h2>7.3.1.4. DO_XMATCH</h2>
+
+<p><small>This is done when a match no longer has to be
+checked. Used when the nocoercions: trick is used in the
+table.</small></p>
+<a name="7.3.1.5. DO_MATCH"></a>
+<h2>7.3.1.5. DO_MATCH</h2>
+
+<p><small>This is the big one inside this function. It has
+the task to transform the contents of the current fake stack
+to match the pattern given after it.</small></p>
+
+<p><small>Since the code generator does not know combining
+coercions, i.e. there is no way to make a big token out of
+two smaller ones, the first thing done is to stack every
+token that is too small. After that all tokens too big are
+split if possible to the right size.</small></p>
+
+<p><small>Next the coercions are sought that would
+transform tokens in place to the right one, plus the
+coercions that would pop tokens of the stack. Each of those
+might need a register, so a list of registers is generated
+and at the end of looking for coercions the function
+<i>tuples()</i> is called to generate the list of all
+possible <i>n</i>-tuples, where <i>n</i> equals the number
+of registers needed.</small></p>
+
+<p><small>Look ahead is now performed if the number of
+tuples is greater than one. If no possibility is found
+within the costlimit, the fake stack is made smaller by
+pushing the bottom token, and this process is repeated until
+either a way is found or the fake stack is completely empty
+and there is still no way to make the match.</small></p>
+
+<p><small>If there is a way the corresponding coercions are
+executed and the code is finished.</small></p>
+<a name="7.3.1.6. DO_REMOVE"></a>
+<h2>7.3.1.6. DO_REMOVE</h2>
+
+<p><small>Here the kills clause is executed, all tokens
+matched by the token expression plus boolean expression are
+pushed. In the current implementation there is no attempt to
+move those tokens to registers, but that is a possible
+future extension.</small></p>
+<a name="7.3.1.7. DO_DEALLOCATE"></a>
+<h2>7.3.1.7. DO_DEALLOCATE</h2>
+
+<p><small>This one temporarily decrements by one the
+reference count of all registers contained in the token
+given as argument.</small></p>
+<a name="7.3.1.8. DO_REALLOCATE"></a>
+<h2>7.3.1.8. DO_REALLOCATE</h2>
+
+<p><small>Here all temporary deallocates are made
+undone.</small></p>
+<a name="7.3.1.9. DO_ALLOCATE"></a>
+<h2>7.3.1.9. DO_ALLOCATE</h2>
+
+<p><small>This is the part that allocates a register and
+decides which one to use. If the <i>forced</i> argument was
+given its task is simple, otherwise some work must be done.
+First the list of possible registers is scanned, all free
+registers noted and it is noted whether any of those
+registers is already containing the initialization. If no
+registers are available some fakestack token is stacked and
+the process is repeated.</small></p>
+
+<p><small>After that if an exact match was found, the list
+of registers is reduced to one register matching exactly out
+of every register class. Now look ahead is performed if
+necessary and the register chosen. If an initialization was
+given the corresponding move is performed, otherwise the
+register is marked empty.</small></p>
+<a name="7.3.1.10. DO_INSTR"></a>
+<h2>7.3.1.10. DO_INSTR</h2>
+
+<p><small>This prints an instruction and its operands. Only
+done on toplevel.</small></p>
+<a name="7.3.1.11. DO_MOVE"></a>
+<h2>7.3.1.11. DO_MOVE</h2>
+
+<p><small>Calls the move() function in the code generator
+to implement the move instruction in the table.</small></p>
+<a name="7.3.1.12. DO_TEST"></a>
+<h2>7.3.1.12. DO_TEST</h2>
+
+<p><small>Calls the test() function in the code generator
+to implement the test instruction in the table.</small></p>
+<a name="7.3.1.13. DO_ERASE"></a>
+<h2>7.3.1.13. DO_ERASE</h2>
+
+<p><small>Marks the register that is its argument as
+empty.</small></p>
+<a name="7.3.1.14. DO_TOKREPLACE"></a>
+<h2>7.3.1.14. DO_TOKREPLACE</h2>
+
+<p><small>This is the token replacement part. It is also
+called if there is no token replacement because it has some
+other functions as well.</small></p>
+
+<p><small>First the tokens that will be pushed on the fake
+stack are computed and stored in a temporary array. Then the
+tokens that were matched in this rule are popped and their
+embedded registers have their reference count decremented.
+After that the replacement tokens are pushed.</small></p>
+
+<p><small>Finally all registers allocated in this rule have
+their reference count decremented. If they were not pushed
+on the fake stack they will be available again in the next
+code rule.</small></p>
+<a name="7.3.1.15. DO_EMREPLACE"></a>
+<h2>7.3.1.15. DO_EMREPLACE</h2>
+
+<p><small>Places replacement EM instructions back into the
+instruction stream.</small></p>
+<a name="7.3.1.16. DO_COST"></a>
+<h2>7.3.1.16. DO_COST</h2>
+
+<p><small>Accounts for cost as given in the code
+rule.</small></p>
+<a name="7.3.1.17. DO_RETURN"></a>
+<h2>7.3.1.17. DO_RETURN</h2>
+
+<p><small>Returns from this level of codegen(). Is used at
+the end of coercions, move rules etc..</small></p>
+<a name="7.3.1.18. DO_LABDEF"></a>
+<h2>7.3.1.18. DO_LABDEF</h2>
+
+<p><small>This prints a label when the top element size
+mechanism is used. Only done on toplevel.</small></p>
+<a name="7.3.2. compute.c"></a>
+<h2>7.3.2. compute.c</h2>
+
+<p><small>This module computes the various expressions as
+given in the enodes[] array. Nothing very special happens
+here, it is just a recursive function computing leaves of
+expressions and applying the operator.</small></p>
+<a name="7.3.3. equiv.c"></a>
+<h2>7.3.3. equiv.c</h2>
+
+<p><small>In this module the tuples() function is
+implemented. It is given the number of registers needed and
+a list of register lists and it constructs a list of tuples
+where the <i>n</i>&rsquo;th register comes from the
+<i>n</i>&rsquo;th list. Before the list is constructed
+however the dynamic register classes are computed. Two
+registers are in the same dynamic class if they are in the
+same static class and their contents is the
+same.</small></p>
+
+<p><small>After that the permute() recursive function is
+called to generate the list of tuples. After construction a
+generated tuple is added to the list if it is not already
+pairwise in the same class or if the register relations are
+not the same, i.e. if the first and second register share a
+common subregister in one tuple and not in the other they
+are considered different.</small></p>
+<a name="7.3.4. fillem.c"></a>
+<h2>7.3.4. fillem.c</h2>
+
+<p><small>This is the routine that does the reading of EM
+instructions and the handling of pseudos. The mach.c module
+provided by the table writer is included at the end of this
+module. The routine fillemlines() is called by nextem() at
+toplevel to make sure there are enough instruction to match.
+It fills the EM instruction buffer up to 5 places from the
+end to keep room for EM replacement instructions, or up to a
+pseudo.</small></p>
+
+<p><small>The dopseudo() function performs the function of
+the pseudo last encountered. If the pseudo is a <b>rom</b>
+the corresponding label is saved with the contents of the
+<b>rom</b> to be available to the code generator later. The
+rest of the routines are small service routines for either
+input or data output.</small></p>
+<a name="7.3.5. gencode.c"></a>
+<h2>7.3.5. gencode.c</h2>
+
+<p><small>This module contains routines called by codegen()
+to generate the real code to the codefile. The function
+genstr() gets a string as argument and copies it to
+codefile. The prtoken() function interprets the tokenformat
+as given in the tokens[] array.</small></p>
+<a name="7.3.6. glosym.c"></a>
+<h2>7.3.6. glosym.c</h2>
+
+<p><small>This module maintains a list of global symbols
+that have a <b>rom</b> pseudo associated. There are
+functions to enter a symbol and to find a
+symbol.</small></p>
+<a name="7.3.7. label.c"></a>
+<h2>7.3.7. label.c</h2>
+
+<p><small>This module contains routines to handle the top
+element size messages.</small></p>
+<a name="7.3.8. main.c"></a>
+<h2>7.3.8. main.c</h2>
+
+<p><small>Main routine of the code generator. Processes
+arguments and flags. Flags available are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>-d</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Sets debug mode if the code generator was not
+compiled with the NDEBUG macro defined. The flag can be
+followed by a digit specifying the amount of debugging
+wanted, and by @labelname giving the start of debugging.
+Debug mode gives very long output on stderr indicating all
+steps of the code generation process including nesting of
+the codegen() function.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>-p<i>n</i></small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Sets the look ahead depth to <i>n</i>, the
+<i>p</i> stands for ply, a well known word in chess playing
+programs.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>-w<i>n</i></small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Sets the weight percentage for size in the cost
+function to <i>n</i> percent. Uses Euclides algorithm to
+simplify rationals.</small></p>
+</td>
+</table>
+<a name="7.3.9. move.c"></a>
+<h2>7.3.9. move.c</h2>
+
+<p><small>Function to implement the move instruction in the
+tables, register initialization and the test instruction and
+associated bookkeeping. First tests are made to try to
+prevent the move from really happening. After that, if there
+is an after that, the move rule is found and the code
+executed.</small></p>
+<a name="7.3.10. nextem.c"></a>
+<h2>7.3.10. nextem.c</h2>
+
+<p><small>The entry point of this module is nextem(). It
+hashes the next three EM instructions, and uses the low
+order byte of the hash as an index into the array pathash[],
+to find a chain of patterns in the array pattern[], that are
+all tried for a match.</small></p>
+
+<p><small>The function trypat() does most of the work
+checking patterns. When a pattern is found to match all
+instructions the operands of the instruction are placed into
+the dollar[] array. Then the boolean expression is tried. If
+it matches the function can return, leaving the operands
+still in the dollar[] array, so later in the code rule they
+can still be used.</small></p>
+<a name="7.3.11. reg.c"></a>
+<h2>7.3.11. reg.c</h2>
+
+<p><small>Collection of routines to handle registers.
+Reference count routines are here, chrefcount() and
+getrefcount(), plus routines to erase a single register or
+all of them, erasereg() and cleanregs().</small></p>
+
+<p><small>If NDEBUG hasn&rsquo;t been defined, here is also
+the routine that checks if the reference count kept with the
+register information is in agreement with the number of
+times it occurs on the fake stack.</small></p>
+<a name="7.3.12. salloc.c"></a>
+<h2>7.3.12. salloc.c</h2>
+
+<p><small>Module for string allocation and garbage
+collection. Contains entry points myalloc(), a routine
+calling malloc() and checking whether room is left,
+myfree(), just free(), popstr() a function called from
+state.c to free all strings made since the last saved
+status. Furthermore there is salloc() which has the size of
+the string as parameter and returns a pointer to the
+allocated space, while keeping a copy of the pointer for
+garbage allocation purposes.</small></p>
+
+<p><small>The function garbage_collect is called from
+codegen() at toplevel every now and then, and checks all
+places where strings may reside to mark strings as being in
+use. Strings not in use are returned to the pool of free
+space.</small></p>
+<a name="7.3.13. state.c"></a>
+<h2>7.3.13. state.c</h2>
+
+<p><small>Set of routines called to save current status and
+restore a previous saved state.</small></p>
+<a name="7.3.14. subr.c"></a>
+<h2>7.3.14. subr.c</h2>
+
+<p><small>Random set of leftover routines.</small></p>
+<a name="7.3.14.1. match"></a>
+<h2>7.3.14.1. match</h2>
+
+<p><small>Computes whether a certain token matches a
+certain token expression. Just computes a bitnumber
+according to the algorithm explained with machsets[], and
+tests the bit and the boolean expression if it is
+there.</small></p>
+<a name="7.3.14.2. instance,cinstance"></a>
+<h2>7.3.14.2. instance,cinstance</h2>
+
+<p><small>These two functions compute a token from a
+description. They differ very slight, cinstance() is used to
+compute the result of a coercion in a certain context and
+therefore has more arguments, which it uses instead of the
+global information instance() works on.</small></p>
+<a name="7.3.14.3. eqtoken"></a>
+<h2>7.3.14.3. eqtoken</h2>
+
+<p><small>eqtoken computes whether two tokens can be
+considered identical. Used to check register contents during
+moves mainly.</small></p>
+<a name="7.3.14.4. distance"></a>
+<h2>7.3.14.4. distance</h2>
+
+<p><small>This is the heuristic function that computes a
+distance from the current fake stack contents to the token
+pattern in the table. It likes exact matches most, then
+matches where at least the sizes are correct and if the
+sizes are not correct it likes too large sizes more than too
+small, since splitting a token is easier than combining
+one.</small></p>
+<a name="7.3.14.5. split"></a>
+<h2>7.3.14.5. split</h2>
+
+<p><small>This function tries to find a splitting coercion
+and executes it immediately when found. The fake stack is
+shuffled thoroughly when this happens, so pieces below the
+token that must be split are saved first.</small></p>
+<a name="7.3.14.6. docoerc"></a>
+<h2>7.3.14.6. docoerc</h2>
+
+<p><small>This function executes a coercion that was found.
+The same shuffling is done, so the top of the stack is again
+saved.</small></p>
+<a name="7.3.14.7. stackupto"></a>
+<h2>7.3.14.7. stackupto</h2>
+
+<p><small>This function gets a pointer into the fake stack
+and must stack every token including the one pointed at up
+to the bottom of the fake stack. The first stacking rule
+possible is used, so rules using registers must come
+first.</small></p>
+<a name="7.3.14.8. findcoerc"></a>
+<h2>7.3.14.8. findcoerc</h2>
+
+<p><small>Looks for a one to one coercion, if found it
+returns a pointer to it and leaves a list of possible
+registers to use in the global variable curreglist. This is
+used by codegen().</small></p>
+<a name="7.3.15. var.c"></a>
+<h2>7.3.15. var.c</h2>
+
+<p><small>Global variables used by more than one module.
+External definitions are in extern.h.</small></p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/ncg.pdf b/doc/tack/ncg.pdf
new file mode 100644 (file)
index 0000000..826a805
Binary files /dev/null and b/doc/tack/ncg.pdf differ
diff --git a/doc/tack/nopt.html b/doc/tack/nopt.html
new file mode 100644 (file)
index 0000000..0f2e172
--- /dev/null
@@ -0,0 +1,1527 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:36 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>A Tour of the New Peephole Optimizer</title>
+</head>
+<body>
+
+<h1 align=center>A Tour of the New Peephole Optimizer</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The optimization table">2. The optimization table</a><br>
+<a href="#3. Incompatibilities with Previous Optimizer">3. Incompatibilities with Previous Optimizer</a><br>
+<a href="#4. The Parser">4. The Parser</a><br>
+<a href="#5. Structure of the Resulting Library">5. Structure of the Resulting Library</a><br>
+<a href="#6. Miscellaneous Issues">6. Miscellaneous Issues</a><br>
+
+<hr>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>The peephole optimizer consists of four major parts:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>a)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>the table describing the optimization to be
+performed</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>b)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>a program to parse these tables and build input and
+output routines to interface to the library and a dfa based
+routine to recognize patterns and make the requested
+replacements.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>c)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>common routines for the library that are independent of
+the table of a)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>d)</p>
+</td>
+<td width="6%"></td>
+<td width="78%">
+
+<p>a stand alone version of the optimizer.</p>
+</td>
+<td width="11%">
+</td>
+</table>
+
+<p>The library conforms to the <i>EM_CODE(3)</i> module
+interface but with routine names of the form
+<b><i>C_</i></b>xxx replaced by names like
+<b><i>O_</i></b>xxx. Furthermore there is also no routine
+<i>O_getid</i> and no variable <i>O_tmpdir</i> in the
+module. The library module results in calls to the usual
+<i>EM_CODE(3)</i> module. It is possible to write a front
+end so that it can call either the normal <i>EM_CODE(3)</i>
+module or this new module by adding <b>#define PEEPHOLE</b>
+before the line <b>#include &lt;em.h&gt;</b> This will map
+all calls to the routine <b><i>C_</i></b>xxx into a call to
+the routine <b><i>O_</i></b>xxx.</p>
+
+<p>We shall now describe each of these major parts in some
+detail.</p>
+<a name="2. The optimization table"></a>
+<h2>2. The optimization table</h2>
+
+<p>The file <i>patterns</i> contains the patterns of EM
+instructions to be recognized by the optimizer and the EM
+instructions to replace them. Each pattern may have an
+optional restriction that must be satisfied before the
+replacement is made. The syntax of the table will be
+described using extended BNF notation used by <i>LLGen</i>
+where:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>[...]</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>- are used to group items<br>
+|</i></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>- is used to separate alternatives<br>
+;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>- terminates a rule<br>
+?</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>- indicates item is optional<br>
+*</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>- indicates item is repeated zero or more times<br>
++</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>- indicates item is repeated one or more
+times</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+
+<p>The format of each rule in the table is:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>rule</i></p>
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>: pattern global_restriction? &rsquo;:&rsquo;
+replacement</i></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="59%">
+</td>
+</table>
+
+<p>Each rule must be on a single line except that it may be
+broken after the colon if the next line begins with a tab
+character. The pattern has the syntax:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>pattern</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: [ EM_mnem [ local_restriction ]? ]+</i></p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>;<br>
+EM-mnem : &quot;An EM instruction mnemonic&quot;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;lab&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+
+<p>and consists of a sequence of one or more EM
+instructions or <i>lab</i> which stands for a defined
+instruction label. Each EM-mnem may optionally be followed
+by a local restriction on the argument of the mnemonic and
+take one of the following forms depending on the type of the
+EM instruction it follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>local_restriction</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: normal_restriction</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| opt_arg_restriction</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| ext_arg_restriction</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p>A normal restriction is used after all types of EM
+instruction except for those that allow an optional
+argument, (such as <i>adi</i> ) or those involving external
+names, (such as <i>lae</i> ) and takes the form:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>normal_restriction</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: [ rel_op ]? expression</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;<br>
+rel_op</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: &rsquo;==&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;!=&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;&lt;=&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;&lt;&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;&gt;=&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>| &rsquo;&gt;&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p>If the rel_op is missing, the equality <i>==</i>
+operator is assumed. The general form of expression is
+defined later but basically it involves simple constants,
+references to EM_mnem arguments that appear earlier in the
+pattern and expressions similar to those used in C
+expressions.</p>
+
+<p>The form of the restriction after those EM instructions
+like <i>adi</i> whose arguments are optional takes the
+form:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>opt_arg_restriction</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: normal_restriction</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;defined&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;undefined&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p>The <i>defined</i> and <i>undefined</i> indicate that
+the argument is present or absent respectively. The normal
+restriction form implies that the argument is present and
+satisfies the restriction.</p>
+
+<p>The form of the restriction after those EM instructions
+like <i>lae</i> whose arguments refer to external object
+take the form:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>ext_arg_restriction</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: patarg offset_part?</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;<br>
+offset_part</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>: [ &rsquo;+&rsquo; | &rsquo;-&rsquo; ]
+expression</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p>Such an argument has one of three forms: a offset with
+no name, an offset form a name or an offset from a label.
+With no offset part the restriction requires the argument to
+be identical to a previous external argument. With an offset
+part it requires an identical name part, (either empty, same
+name or same label) and supplies a relationship among the
+offset parts. It is possible to refer to test for the same
+external argument, the same name or to obtain the offset
+part of an external argument using the <i>sameext</i> ,
+<i>samenam</i> and <i>offset</i> functions given below.</p>
+
+<p>The general form of an expression is:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>expression</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: expression binop expression</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| unaryop expression</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;(&rsquo; expression &rsquo;)&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| bin_function &rsquo;(&rsquo; expression
+&rsquo;,&rsquo; expression &rsquo;)&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| ext_function &rsquo;(&rsquo; patarg &rsquo;,&rsquo;
+patarg &rsquo;)&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;offset&rsquo; &rsquo;(&rsquo; patarg
+&rsquo;)&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| patarg</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;p&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;w2&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;w&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| INTEGER</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>bin_function</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: &rsquo;sfit&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;ufit&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;samesign&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;rotate&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="6" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>ext_function</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: &rsquo;samenam&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>| &rsquo;sameext&rsquo;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;<br>
+patarg</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>: &rsquo;$&rsquo; INTEGER</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;<br>
+binop</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>: &quot;As for C language&quot;<br>
+unaryop</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>: &quot;As for C language&quot;</i></p>
+</td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+</table>
+
+<p>The INTEGER in the <i>patarg</i> refers to the first,
+second, etc. argument in the pattern and it is required to
+refer to a pattern that appears earlier in the pattern The
+<i>w</i> and <i>p</i> refer to the word size and pointer
+size (in bytes) respectively. The <i>w2</i> refers to twice
+the word size. The various function test for:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>sfit</p>
+</td>
+<td width="12%"></td>
+<td width="80%">
+
+<p>the first argument fits as a signed value of the number
+of bit specified by the second argument.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>ufit</p>
+</td>
+<td width="12%"></td>
+<td width="72%">
+
+<p>as for sfit but for unsigned values.</p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>samesign</p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p>the first argument has the same sign as the second.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>rotate</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>the value of the first argument rotated by the number of
+bit specified by the second argument.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>samenam</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>both arguments refer to externals and have either no
+name, the same name or same label.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>sameext</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>both arguments refer to the same external.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>offset</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>the argument is an external and this yields it offset
+part.</p>
+</td>
+</table>
+
+<p>The global restriction takes the form:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>global_restriction</i></p>
+<td width="19%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+
+<p><i>: &rsquo;?&rsquo; expression</i></p>
+</td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><i>;</i></p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="29%">
+</td>
+</table>
+
+<p>and is used to express restrictions that cannot be
+expressed as simple restrictions on a single argument or are
+can be expressed in a more readable fashion as a global
+restriction. An example of such a rule is:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>dup w ldl stf ? p==2*w : ldl $2 stf $3 ldl $2 lof
+$3</i></p>
+</table>
+
+<p>which says that this rule only applies if the pointer
+size is twice the word size.</p>
+<a name="3. Incompatibilities with Previous Optimizer"></a>
+<h2>3. Incompatibilities with Previous Optimizer</h2>
+
+<p>The current table format is not compatible with previous
+versions of the peephole optimizer tables. In particular the
+previous table had no provision for local restrictions and
+only the equivalent of the global restriction. This meant
+that our <i>&rsquo;?&rsquo;</i> character that announces the
+presence of the optional global restriction was not
+required. The previous optimizer performed a number of other
+tasks that were unrelated to optimization that were possible
+because the old optimizer read the EM code for a complete
+procedure at a time. This included tasks such as register
+variable reference counting and moving the information
+regarding the number of bytes of local storage required by a
+procedure from it <i>end</i> pseudo instruction to
+it&rsquo;s <i>pro</i> pseudo instruction. These tasks are no
+longer done by this module but have been moved to other
+modules or programs in the pipeline. The register variable
+reference counting is now performed by the front end. The
+reordering of code, such as the moving of mes instructions
+and the local storage requirements from the end to beginning
+of procedures, is now performed using the insertpart
+mechanism in the <i>EM_CODE</i> (or <i>EM_OPT</i> ) module.
+The removal of dead code is performed by the global
+optimizer. Various <i>ext_functions</i> available in the old
+tables are no longer available as they rely on information
+that is not available to the current program. These are the
+<i>notreg</i> and the <i>rom</i> functions. The previous
+optimizer allowed the use of <i>LLP, LEP, SLP</i> and
+<i>SEP</i> in patterns. For example <i>LLP</i> stood for
+either <i>lol</i> if the pointer size was the same as the
+word size, or for <i>ldl</i> if the pointer size was twice
+the word size. In the current optimizer it is necessary to
+include two patterns for each such single pattern in the old
+table. For example for a pattern containing <i>LLP</i> there
+would be one pattern with <i>lol</i> and with a global
+restriction of the form <i>p=w</i> and another pattern with
+ldl and a global restriction of the form <i>p=2*w.</i></p>
+<a name="4. The Parser"></a>
+<h2>4. The Parser</h2>
+
+<p>The program to parse the tables and build the pattern
+table dependent dfa routines is built from the files:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>parser.h</p>
+</td>
+<td width="14%"></td>
+<td width="22%">
+
+<p>header file</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>parser.g</p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>LLGen source file defining syntax of table</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>syntax.l</p>
+</td>
+<td width="14%"></td>
+<td width="70%">
+
+<p>Lex sources file defining form of tokens in table.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>initlex.c</p>
+</td>
+<td width="12%"></td>
+<td width="70%">
+
+<p>Uses the data in the library <i>em_data.a</i> to
+initialize the lexical analyzer to recognize EM instruction
+mnemonics.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>outputdfa.c</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>Routines to output the dfa when it has been constructed.
+It outputs the files <i>dfa.c</i> and <i>trans.c</i></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>outcalls.c</p>
+</td>
+<td width="10%"></td>
+<td width="70%">
+
+<p>Routines to output the file <i>incalls.r</i> defined in
+the next section.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p>findworst.c</p>
+</td>
+<td width="8%"></td>
+<td width="70%">
+
+<p>Routines to analyze patterns to find how to continue
+matching after a successful replacement or failed match.</p>
+</td>
+</table>
+
+<p>The parser checks that the tables conform to the syntax
+outlined in the previous section and also makes a number of
+semantic checks on their validity. Further versions could
+make further checks such as looking for cycles in the rules
+or checking that each replacement leaves the same number of
+bytes on the stack as the pattern it replaces. The parser
+builds an internal dfa representation of the rules by
+combining rules with common prefixes. All local and global
+restrictions are combined into a single test to be performed
+are a complete pattern has been detected in the input. The
+idea is to build a structure so that each of the patterns
+can be matched and then the corresponding tests made and the
+first that succeeds is replaced. If two rules have the same
+pattern and both their tests also succeed the one that
+appears first in the tables file will be done. Somewhat less
+obvious is that if one pattern is a proper prefix of a
+longer pattern and its test succeeds then the second pattern
+will not be checked for.</p>
+
+<p>A major task of the parser if to decide on the action to
+take when a rule has been partially matched or when a
+pattern has been completely matched but its test does not
+succeed. This requires a search of all patterns to see if
+any part of the part matched could be part of some other
+pattern. for example given the two patterns:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>loc adi w loc adi w : loc $1+$3 adi w<br>
+loc adi w loc sbi w : loc $1-$3 adi w</i></p>
+</table>
+
+<p>If the first pattern fails after seeing the input:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>loc adi loc</i></p>
+</table>
+
+<p>the parser will still need to check whether the second
+pattern matches. This requires a decision on how to fix up
+any internal data structures in the dfa matcher, such as
+moving some instructions from the pattern to the output
+queue and moving the pattern along and then deciding what
+state it should continue from. Similar decisions are
+requires after a pattern has been replaced. For example if
+the replacement is empty it is necessary to backup
+<i>n-1</i> instructions where <i>n</i> is the length of the
+longest pattern in the tables.</p>
+<a name="5. Structure of the Resulting Library"></a>
+<h2>5. Structure of the Resulting Library</h2>
+
+<p>The major data structures maintained by the library
+consist of three queues; an <i>output</i> queue of
+instructions awaiting output, a <i>pattern</i> queue
+containing instructions that match the current prefix, and a
+<i>backup</i> queue of instructions that have been backed up
+over and need to be reparsed for further pattern matches.
+These three queues are maintained in a single fixed size
+buffer as explained in more detail in the next section.
+Also, after a successful match, a replacement queue is
+constructed.</p>
+
+<p>If no errors are detected by the parser in the tables it
+output the following files if they have changed from the
+existing version of the file:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>dfa.c</p>
+</td>
+<td width="10%"></td>
+<td width="80%">
+
+<p>this contains the dfa encoded into a number of arrays
+using the technique of row displacement for compacted sparse
+matricies. Given an opcode and the current state, the value
+of <i>OO_base[OO_state]</i> is consulted to obtain a pointer
+into the array <i>OO_checknext.</i> If this pointer in zero
+or the <i>check</i> field of the addressed structure does
+not correspond to the curerent state then it is known there
+is no entry for this opcode/state pair and the
+<i>OO_default</i> array is consulted instead. If the check
+field does match then the <i>next</i> field contains the new
+state. After each transition the array <i>OO_ftrans</i> is
+consulted to see if this state corresponds to a final state
+(i.e. a complete pattern) and if so the corresponding
+function is called.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p>trans.c</p>
+</td>
+<td width="6%"></td>
+<td width="80%">
+
+<p>this contains external declarations of transition
+routines with names like <b>OO_xxxdotrans</b> (where
+<i>xxx</i> is a small integer). These are called when there
+a transition to state <i>xxx</i> that corresponds to a
+complete pattern. Any tests are performed if necessary to
+confirm that the pattern matches and then the replacement
+instructions are placed on the output queue and the routine
+<i>OO_mkrepl</i> is called to make the replacement and if
+backup the amount required. If there are a number of
+patterns with the same instructions but different tests,
+these will all appear in the same routine and the tests
+performed in the order they appear in the original
+<i>patterns</i> file.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>incalls.r</p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p>this contains an entry for every EM instruction (plus
+<i>lab</i> ) giving information on how to build a routine
+with the name <b><i>O_</i></b>xxx for the library version of
+the module. If the EM instruction does not appear in the
+tables patterns at all then the dfa routine is called to
+flush any current queued output and the the output
+<b><i>C_</i></b>xxx routine is called. If the EM instruction
+does appear in a pattern then the instruction data structure
+fields are initialized and it is added onto the end of the
+pattern queue. The dfa routines are then called to attempted
+to make a transition. This file is input to the <i>awk</i>
+program <i>makefuns.awk.</i></p>
+</td>
+</table>
+
+<p>The following files contain code that is independent of
+the pattern tables:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>main.c</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>this is used only in the stand alone version of the
+optimizer and consists of code to open the input file, read
+the input using the <i>READ_EM(3)</i> module and call the
+dfa routines. This version does not require the routines
+constructed from the incalls.r file described above.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>nopt.c</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>general routines to initialize, and maintain the data
+structures. The file handling routines <i>O_open</i> etc are
+defined here. Also defined are routines for flushing the
+output queue by calling the <i>EM_mkcalls</i> routine from
+the <i>READ_EM(3)</i> module and moving instructions from
+the output to the backup queue. Routines to free the strings
+stored in instructions with types of <i>sof_ptyp, pro_ptyp,
+str_ptyp, ico_ptyp, uco_ptyp,</i> and also<i>fco_ptyp</i>are
+is extended by <i>Realloc</i> if it overflows. The strings
+can be thrown away on any flush that occurs when the backup
+queue is empty.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p>mkstrct.c</p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p>contains routines to build the data structure from the
+input <b><i>C_</i></b>xxx routines and place the structure
+on the pattern queue. These routines are also used to build
+the data structures when a replacement is constructed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>aux.c</p>
+</td>
+<td width="10%"></td>
+<td width="80%">
+
+<p>routines to implement the external functions used in the
+pattern table.</p>
+</td>
+</table>
+
+<p>The following files are also used in building the module
+library:</p>
+
+<p>makefuns.awk</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="80%">
+<p>this <i>awk</i> program is used to produce individual C
+files with names like <b><i>O_</i></b>xxx.c each containing
+a single function definition and then call the <i>cc</i>
+compiler to produce a single output file. This enables the
+loader to only load those routines that are actually needed
+when the library is loaded.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p>pseudo.r</p>
+</td>
+<td width="4%"></td>
+<td width="80%">
+
+<p>this file is like the <i>incalls.r</i> file produced by
+the parser but is built by hand and handles the pseudo EM
+instructions. It is also processed by
+<i>makefuns.awk.</i></p>
+</td>
+</table>
+<a name="6. Miscellaneous Issues"></a>
+<h2>6. Miscellaneous Issues</h2>
+
+<p>The output, pattern and backup queues are maintained in
+fixed length array, <i>OO_buffer</i> allocated of size
+<i>MAXBUFFER</i> (a constant declared in nopt.h) at run
+time. It consists of an array of the <i>e_instr</i> data
+structure used by the <i>READ_EM(3)</i> module. At any time
+the pointers <i>OO_patternqueue</i> and <i>OO_nxtpatt</i>
+point to the beginning and end of the current pattern prefix
+that corresponds to the current state. Any instructions on
+the backup queue are between <i>OO_nxtpatt</i> and
+<i>OO_endbackup.</i> If there are no instructions on the
+backup queue then <i>OO_endbackup</i> will be 0 (zero). The
+size of the replacement queue is set to the length of the
+maximum replacement length by the tables output by the
+parser.</p>
+
+<p>The fixed size of the buffer causes no difficulty in
+practice and can only result in some potential optimizations
+being missed. When space for a new instruction is required
+and the buffer is full the routine <i>OO_halfflush</i> is
+called to flush half the buffer and move all the data
+structures left. It should be noted that it is not possible
+to statically determine the maximum possible size for these
+queues as they need to be unbounded in the worst case. A
+study of the rule</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p><i>inc dec :</i></p>
+</table>
+
+<p>with the input consisting of <i>N inc</i> and then <i>N
+dec</i> instructions requires an output queue length of
+<i>N-1</i> to find all possible replacements.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/nopt.pdf b/doc/tack/nopt.pdf
new file mode 100644 (file)
index 0000000..9737f66
Binary files /dev/null and b/doc/tack/nopt.pdf differ
diff --git a/doc/tack/occam.html b/doc/tack/occam.html
new file mode 100644 (file)
index 0000000..51627c7
--- /dev/null
@@ -0,0 +1,445 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:31 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>An Occam Compiler</title>
+</head>
+<body>
+
+<h1 align=center>An Occam Compiler</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The Compiler">2. The Compiler</a><br>
+<a href="#2.1. The LLgen Parser Generator">2.1. The LLgen Parser Generator</a><br>
+<a href="#2.2. Indentation">2.2. Indentation</a><br>
+<a href="#3. Implementation">3. Implementation</a><br>
+<a href="#3.1. Channels">3.1. Channels</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Kees Bot<br>
+Edwin Scheffer</i><br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</p>
+
+<p>This document describes the implementation of an
+<b>Occam</b> to <b>EM</b> compiler. The lexical analysis is
+done using <b>Lex</b>. For the semantic analysis the
+extended LL(1) parser generator <b>LLgen</b> is used. To
+handle the Occam-specific features as channels and
+parallelism some library routines are required.</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>Occam [1] is a programming language which is based on
+the concepts of concurrency and communication. These
+concepts enable today&rsquo;s applications of
+microprocessors and computers to be implemented more
+effectively.</p>
+
+<p>An Occam program consists of a (dynamically determined)
+number of processes communicating through channels. To
+communicate with the outside world some predefined channels
+are needed. A channel has only one writer and one reader; it
+carries machine words and bytes, at the
+reader/writer&rsquo;s discretion. The process with its
+communication in Occam replaces the procedure with
+parameters in other languages (there are no procedures in
+Occam).</p>
+
+<p>In addition to the normal assignment statement, Occam
+has two more information-transfer statements, the input and
+the output:</p>
+<pre>          chan1 ? x        -- reads a value from chan1 into x
+          chan2 ! x        -- writes the value of x onto chan2
+</pre>
+
+<p>Both the outputting and the inputting processes wait
+until the other is there. Channels are declared and given
+names.</p>
+
+<p><b>2</b></p>
+
+<p>Arrays of channels are possible.</p>
+
+<p>Processes come in 5 varieties: sequential, parallel,
+alternative, conditional and repetitive. A process starts
+with a reserved word telling its nature, followed by an
+indented list of other processes. (Indentation is used to
+indicate block structure.) It may be preceded by
+declarations. The processes in a sequential/parallel process
+are executed sequentially/in parallel. The processes in an
+alternative process have guards based on the availability of
+input; the first to be ready is executed (this is waiting
+for multiple input). The conditional and repetitive
+processes are normal <b>IF</b>s and <b>WHILE</b>s.</p>
+
+<p><i>Producer-consumer example:</i></p>
+<pre>     CHAN buffer:                    -- declares the channel buffer
+     PAR
+       WHILE TRUE                    -- the producer
+         VAR x:                      -- a local variable
+         SEQ
+           produce(x)                -- in some way
+           buffer ! x                -- and send it
+       WHILE TRUE                    -- the consumer
+         VAR x:
+         SEQ
+           buffer ? x                -- get a value
+           consume(x)                -- in some way
+</pre>
+
+<p><b>3</b></p>
+
+<p>Processes can be replicated from a given template; this
+combines with arrays of variables and/or channels.</p>
+
+<p><i>Example: 20 window-sorters in series:</i></p>
+<pre>     CHAN s[20]:                     -- 20 channels
+     PAR i = [ 0 FOR 19 ]            -- 19 processes
+       WHILE TRUE
+         VAR v1, v2:
+         SEQ
+           s[i] ? v1; v2             -- wait for 2 variables from s[i]
+           IF
+             v1 &lt;= v2                -- ok
+               s[i+1] ! v1; v2
+             v1 &gt; v2                 -- reorder
+               s[i+1] ! v2; v1
+</pre>
+
+<p>A process may wait for a condition, which must include a
+comparison with <b>NOW</b>, the present clock value.</p>
+
+<p>Processes may be distributed over several processors;
+all processes under a <b>VAR</b> declaration must run on the
+same processor. Concurrency can be improved by avoiding
+<b>VAR</b> declarations, and replacing them by <b>CHAN</b>
+declarations. Processes can be allocated explicitly on named
+processors and channels can be connected to physical
+ports.</p>
+<a name="2. The Compiler"></a>
+<h2>2. The Compiler</h2>
+
+<p>The compiler is written in <b>C</b> using LLgen and Lex
+and compiles Occam programs to EM code, using the procedural
+interface as defined for EM. In the following sub-sections
+we describe the LLgen parser generator and the aspect of
+indentation.</p>
+<a name="2.1. The LLgen Parser Generator"></a>
+<h2>2.1. The LLgen Parser Generator</h2>
+
+<p>LLgen accepts a Context Free syntax extended with the
+operators &lsquo;<tt>*</tt>&rsquo;, &lsquo;<tt>?</tt>&rsquo;
+and &lsquo;<tt>+</tt>&rsquo; that have effects similar to
+those in regular expressions. The &lsquo;<tt>*</tt>&rsquo;
+is the closure set operator without an upperbound;
+&lsquo;<tt>+</tt>&rsquo; is the positive closure operator
+without an upperbound; &lsquo;<tt>?</tt>&rsquo; is the
+optional operator; &lsquo;<tt>[</tt>&rsquo; and
+&lsquo;<tt>]</tt>&rsquo; can be used for grouping. For
+example, a comma-separated list of expressions can be</p>
+
+<p><b>4</b></p>
+
+<p>described as:</p>
+<pre>          expression_list:
+                 expression [ &rsquo;,&rsquo; expression ]*
+               ;
+</pre>
+
+<p>Alternatives must be separated by
+&lsquo;<tt>|</tt>&rsquo;. C code
+(&lsquo;&lsquo;actions&rsquo;&rsquo;) can be inserted at all
+points between the colon and the semicolon. Variables global
+to the complete rule can be declared just in front of the
+colon enclosed in the brackets &lsquo;<tt>{</tt>&rsquo; and
+&lsquo;<tt>}</tt>&rsquo;. All other declarations are local
+to their actions. Nonterminals can have parameters to pass
+information. A more mature version of the above example
+would be:</p>
+<pre>            expression_list(expr *e;)       {     expr e1, e2;   } :
+                     expression(&amp;e1)
+                     [ &rsquo;,&rsquo; expression(&amp;e2)
+                                            {     e1=append(e1, e2);  }
+                     ]*
+                                            {     *e=e1;    }
+                   ;
+</pre>
+
+<p>As LLgen generates a recursive-descent parser with no
+backtrack, it must at all times be able to determine what to
+do, based on the current input symbol. Unfortunately, this
+cannot be done for all grammars. Two kinds of conflicts are
+possible, viz. the <b>alternation</b> and <b>repetition</b>
+conflict. An alternation confict arises if two sides of an
+alternation can start with the same symbol. E.g.</p>
+
+<p><b>5</b></p>
+<pre>          plus:     &rsquo;+&rsquo; | &rsquo;+&rsquo; ;
+</pre>
+
+<p>The parser doesn&rsquo;t know which
+&lsquo;<tt>+</tt>&rsquo; to choose (neither do we). Such a
+conflict can be resolved by putting an <b>if-condition</b>
+in front of the first conflicting production. It consists of
+a <b>&lsquo;&lsquo;%if&rsquo;&rsquo;</b> followed by a
+C-expression between parentheses. If a conflict occurs (and
+only if it does) the C-expression is evaluated and parsing
+continues along this path if non-zero. Example:</p>
+<pre>          plus:
+                 %if (some_plusses_are_more_equal_than_others())
+                 &rsquo;+&rsquo;
+               |
+                 &rsquo;+&rsquo;
+               ;
+</pre>
+
+<p>A repetition conflict arises when the parser cannot
+decide whether
+&lsquo;&lsquo;<tt>productionrule</tt>&rsquo;&rsquo; in e.g.
+&lsquo;&lsquo;<tt>[ productionrule ]*</tt>&rsquo;&rsquo;
+must be chosen once more, or that it should continue. This
+kind of conflicts can be resolved by putting a
+<b>while-condition</b> right after the opening parentheses.
+It consists of a <b>&lsquo;&lsquo;%while&rsquo;&rsquo;</b>
+followed by a C-expression between parentheses. As an
+example, we can look at the <b>comma-expression</b> in C.
+The comma may only be used for the comma-expression if the
+total expression is not part of another comma-separated
+list:</p>
+<pre>          comma_expression:
+                 sub_expression
+                 [ %while (not_part_of_comma_separated_list())
+                      &rsquo;,&rsquo; sub_expression
+                 ]*
+</pre>
+
+<p><b>6</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p><tt>;</tt></p>
+</td>
+<td width="69%">
+</td>
+</table>
+
+<p>Again, the <b>&lsquo;&lsquo;%while&rsquo;&rsquo;</b> is
+only used in case of a conflict.</p>
+
+<p>Error recovery is done almost completely automatically.
+All the LLgen-user has to do is write a routine called
+<i>LLmessage</i> to give the necessary error messages and
+supply information about terminals found missing.</p>
+<a name="2.2. Indentation"></a>
+<h2>2.2. Indentation</h2>
+
+<p>The way conflicts can be resolved are of great use to
+Occam. The use of indentation, to group statements, leads to
+many conflicts because the spaces used for indentation are
+just token separators to the lexical analyzer, i.e.
+&lsquo;&lsquo;white space&rsquo;&rsquo;. The lexical
+analyzer can be instructed to generate &lsquo;BEGIN&rsquo;
+and &lsquo;END&rsquo; tokens at each indentation change, but
+that leads to great difficulties as expressions may occupy
+several lines, thus leading to indentation changes at the
+strangest moments. So we decided to resolve the conflicts by
+looking at the indentation ourselves. The lexical analyzer
+puts the current indentation level in the global variable
+<i>ind</i> for use by the parser. The best example is the
+<b>SEQ</b> construct, which exists in two flavors, one with
+a replicator and one process:</p>
+<pre>          seq i = [ 1 for str[byte 0] ]
+               out ! str[byte i]
+</pre>
+
+<p>and one without a replicator and several processes:</p>
+<pre>          seq
+               in ? c
+               out ! c
+</pre>
+
+<p><b>7</b></p>
+
+<p>The LLgen skeleton grammar to handle these two is:</p>
+<pre>          SEQ            {    line=yylineno; oind=ind; }
+          [      %if (line==yylineno)
+                 replicator
+                 process
+               |
+                 [ %while (ind&gt;oind) process ]*
+          ]
+</pre>
+
+<p>This shows clearly that, a replicator must be on the
+same line as the <b>SEQ</b>, and new processes are collected
+as long as the indentation level of each process is greater
+than the indentation level of <b>SEQ</b> (with appropriate
+checks on this identation).</p>
+
+<p>Different indentation styles are accepted, as long as
+the same amount of spaces is used for each indentation
+shift. The ascii tab character sets the indentation level to
+an eight space boundary. The first indentation level found
+in a file is used to compare all other indentation levels
+to.</p>
+<a name="3. Implementation"></a>
+<h2>3. Implementation</h2>
+
+<p>It is now time to describe the implementation of some of
+the occam-specific features such as channels and <b>NOW</b>.
+Also the way communication with UNIX&dagger; is performed
+must be described.</p>
+
+<p align=center><img src="grohtml-106061.png"></p>
+
+<p>For a thorough description of the library routines to
+simulate parallelism, which are e.g. used by the channel
+routines and by the <b>PAR</b> construct in Appendix B, see
+[6].</p>
+<a name="3.1. Channels"></a>
+<h2>3.1. Channels</h2>
+
+<p>There are currently two types of channels (see Figure
+1.) indicated by the type field of a channel variable:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>An interprocess communication channel with two
+additional fields:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>A synchronization field to hold the state of an
+interprocess communication channel.</p>
+</td>
+</table>
+
+<p><b>8</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>An integer variable to hold the value to be send.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p>An outside world communication channel. This is a member
+of an array of channels connected to UNIX files. Its
+additional fields are:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>A flags field holding a readahead flag and a flag that
+tells if this channel variable is currently connected to a
+file.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>A preread character, if readahead is done.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="8%"></td>
+<td width="80%">
+
+<p>An index field to find the corresponding UNIX file.</p>
+</td>
+</table>
+
+<p align=center><img src="grohtml-106062.png"></p>
+
+<p align=center><i>Figure 1. Interprocess and outside world
+communication channels</i></p>
+
+<p>The basic channel handling is done by <tt>chan_in</tt>
+and <tt>chan_out</tt>. All other routines are based on them.
+The routine <tt>chan_any</tt> only checks if there&rsquo;s a
+value available on a given channel. (It does not read this
+value!) <tt>C_init</tt> initializes an array of interprocess
+communication channels.</p>
+
+<p><b>9</b></p>
+
+<p>The following table shows Occam statements paired with
+the routines used to execute them.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/occam.pdf b/doc/tack/occam.pdf
new file mode 100644 (file)
index 0000000..852d984
Binary files /dev/null and b/doc/tack/occam.pdf differ
diff --git a/doc/tack/pascal.html b/doc/tack/pascal.html
new file mode 100644 (file)
index 0000000..242c129
--- /dev/null
@@ -0,0 +1,4088 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:13 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The ACK Pascal Compiler</title>
+</head>
+<body>
+
+<h1 align=center>The ACK Pascal Compiler</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. The compiler">2. The compiler</a><br>
+<a href="#2.1. Lexical Analysis">2.1. Lexical Analysis</a><br>
+<a href="#2.2. Syntax Analysis">2.2. Syntax Analysis</a><br>
+<a href="#2.2.1. Alternation conflict">2.2.1. Alternation conflict</a><br>
+<a href="#2.2.2. Repetition conflict">2.2.2. Repetition conflict</a><br>
+<a href="#2.3. Semantic Analysis">2.3. Semantic Analysis</a><br>
+<a href="#2.4. Code Generation">2.4. Code Generation</a><br>
+<a href="#2.5. Error Handling">2.5. Error Handling</a><br>
+<a href="#2.6. Memory Allocation and Garbage Collection">2.6. Memory Allocation and Garbage Collection</a><br>
+<a href="#3. Translation of Pascal to EM code">3. Translation of Pascal to EM code</a><br>
+<a href="#3.1. Global Variables">3.1. Global Variables</a><br>
+<a href="#3.2. Expressions">3.2. Expressions</a><br>
+<a href="#3.3. Statements">3.3. Statements</a><br>
+<a href="#3.3.1. Assignment Statement">3.3.1. Assignment Statement</a><br>
+<a href="#3.3.2. Goto Statement">3.3.2. Goto Statement</a><br>
+<a href="#3.3.3. If Statement">3.3.3. If Statement</a><br>
+<a href="#3.3.4. Repeat Statement">3.3.4. Repeat Statement</a><br>
+<a href="#3.3.5. While Statement">3.3.5. While Statement</a><br>
+<a href="#3.3.6. Case Statement">3.3.6. Case Statement</a><br>
+<a href="#3.3.7. For Statement">3.3.7. For Statement</a><br>
+<a href="#3.3.8. With Statement">3.3.8. With Statement</a><br>
+<a href="#3.4. Procedure and Function Calls">3.4. Procedure and Function Calls</a><br>
+<a href="#3.5. Register Messages">3.5. Register Messages</a><br>
+<a href="#3.6. Compile-time optimizations">3.6. Compile-time optimizations</a><br>
+<a href="#4. Conformant Arrays">4. Conformant Arrays</a><br>
+<a href="#4.1. Variable conformant array parameters">4.1. Variable conformant array parameters</a><br>
+<a href="#4.2. Value conformant array parameters">4.2. Value conformant array parameters</a><br>
+<a href="#5. Compiler options">5. Compiler options</a><br>
+<a href="#5.1. Compile time options">5.1. Compile time options</a><br>
+<a href="#5.2. Run time options">5.2. Run time options</a><br>
+<a href="#6. Extensions to Pascal as specified by ISO 7185">6. Extensions to Pascal as specified by ISO 7185</a><br>
+<a href="#7. Deviations from the standard">7. Deviations from the standard</a><br>
+<a href="#8. Hints to change the standard">8. Hints to change the standard</a><br>
+<a href="#9. Testing the compiler">9. Testing the compiler</a><br>
+<a href="#10. Comparison with the Pascal-VU compiler">10. Comparison with the Pascal-VU compiler</a><br>
+<a href="#10.1. Deviations">10.1. Deviations</a><br>
+<a href="#10.2. Extensions">10.2. Extensions</a><br>
+<a href="#10.3. Compiler options">10.3. Compiler options</a><br>
+<a href="#11. Improvements to the compiler">11. Improvements to the compiler</a><br>
+<a href="#12. History &amp; Acknowledgements">12. History &amp; Acknowledgements</a><br>
+<a href="#13. References">13. References</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Aad Geudeke<br>
+Frans Hofmeester</i><br>
+Dept. of Mathematics and Computer Science<br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</p>
+
+<p>This document describes the implementation of a Pascal
+to EM compiler. The compiler is written in C. The lexical
+analysis is done using a hand-written lexical analyzer.
+Semantic analysis makes use of the extended LL(1) parser
+generator LLgen. Several EM utility modules are used in the
+compiler.</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>The Pascal front end of the Amsterdam Compiler Kit (ACK)
+complies with the requirements of the international standard
+published by the International Organization for
+Standardization (ISO) [ISO]. An informal description, which
+unfortunately is not conforming to the standard, of the
+programming language Pascal is given in [JEN].</p>
+
+<p>The main reason for rewriting the Pascal compiler was
+that the old Pascal compiler was written in Pascal itself,
+and a disadvantage of it was its lack of flexibility. The
+compiler did not meet the needs of the current
+ACK-framework, which makes use of modern parsing techniques
+and utility modules. In this framework it is, for example,
+possible to use a fast back end. Such a back end translates
+directly to object code [ACK]. Our compiler is written in C
+and it is designed similar to the current C and Modula-2
+compiler of ACK.</p>
+
+<p>Chapter 2 describes the basic structure of the compiler.
+Chapter 3 discusses the code generation of the main Pascal
+constructs. Chapter 4 covers one of the major components of
+Pascal, viz. the conformant array. In Chapter 5 the various
+compiler options that can be used are enumerated. The
+extensions to the standard and the deviations from the
+standard are listed in Chapter 6 and 7. Chapter 8 presents
+some ideas to improve the standard. Chapter 9 gives a short
+overview of testing the compiler. The major differences
+between the old and new compiler can be found in Chapter 10.
+Suggestions to improve the compiler are described in Chapter
+11. The appendices contain the grammar of Pascal and the
+changes made to the ACK Pascal run time library. A
+translation of a Pascal program to EM code as example is
+presented.</p>
+<a name="2. The compiler"></a>
+<h2>2. The compiler</h2>
+
+<p>The compiler can be divided roughly into four
+modules:</p>
+
+<p>&bull; lexical analysis<br>
+&bull; syntax analysis<br>
+&bull; semantic analysis<br>
+&bull; code generation</p>
+
+<p>The four modules are grouped into one pass. The activity
+of these modules is interleaved during the pass.<br>
+The lexical analyzer, some expression handling routines and
+various datastructures from the Modula-2 compiler
+contributed to the project.</p>
+<a name="2.1. Lexical Analysis"></a>
+<h2>2.1. Lexical Analysis</h2>
+
+<p>The first module of the compiler is the lexical
+analyzer. In this module, the stream of input characters
+making up the source program is grouped into <i>tokens</i>,
+as defined in <b>ISO 6.1</b>. The analyzer is hand-written,
+because the lexical analyzer generator, which was at our
+disposal, <i>Lex</i> [LEX], produces much slower analyzers.
+A character table, in the file <i>char.c</i>, is created
+using the program <i>tab</i> which takes as input the file
+<i>char.tab</i>. In this table each character is placed into
+a particular class. The classes, as defined in the file
+<i>class.h</i>, represent a set of tokens. The strategy of
+the analyzer is as follows: the first character of a new
+token is used in a multiway branch to eliminate as many
+candidate tokens as possible. Then the remaining characters
+of the token are read. The constant INP_NPUSHBACK, defined
+in the file <i>input.h</i>, specifies the maximum number of
+characters the analyzer looks ahead. The value has to be at
+least 3, to handle input sequences such as:<br>
+1e+4 (which is a real number)<br>
+1e+a (which is the integer 1, followed by the identifier
+&quot;e&quot;, a plus, and the identifier &quot;a&quot;)</p>
+
+<p>Another aspect of this module is the insertion and
+deletion of tokens required by the parser for the recovery
+of syntactic errors (see also section 2.2). A generic input
+module [ACK] is used to avoid the burden of I/O.</p>
+<a name="2.2. Syntax Analysis"></a>
+<h2>2.2. Syntax Analysis</h2>
+
+<p>The second module of the compiler is the parser, which
+is the central part of the compiler. It invokes the routines
+of the other modules. The tokens obtained from the lexical
+analyzer are grouped into grammatical phrases. These phrases
+are stored as parse trees and handed over to the next part.
+The parser is generated using <i>LLgen</i>[LL], a tool for
+generating an efficient recursive descent parser with no</p>
+
+<p>backtrack from an Extended Context Free Syntax.<br>
+An error recovery mechanism is generated almost completely
+automatically. A routine called <i>LLmessage</i> had to be
+written, which gives the necessary error messages and deals
+with the insertion and deletion of tokens. The routine
+<i>LLmessage</i> must accept one parameter, whose value is a
+token number, zero or -1. A zero parameter indicates that
+the current token (the one in the external variable
+<i>LLsymb</i>) is deleted. A -1 parameter indicates that the
+parser expected end of file, but did not get it. The parser
+will then skip tokens until end of file is detected. A
+parameter that is a token number (a positive parameter)
+indicates that this token is to be inserted in front of the
+token currently in <i>LLsymb</i>. Also, care must be taken,
+that the token currently in <i>LLsymb</i> is again returned
+by the <b>next</b> call to the lexical analyzer, with the
+proper attributes. So, the lexical analyzer must have a
+facility to push back one token.<br>
+Calls to the two standard procedures <i>write</i> and
+<i>writeln</i> can be different from calls to other
+procedures. The syntax of a write-parameter is different
+from the syntax of an actual-parameter. We decided to
+include them, together with <i>read</i> and <i>readln</i>,
+in the grammar. An alternate solution would be to make the
+syntax of an actual-parameter identical to the syntax of a
+write-parameter. Afterwards the parameter has to be checked
+to see whether it is used properly or not.</p>
+
+<p>As the parser is LL(1), it must always be able to
+determine what to do, based on the last token read
+(<i>LLsymb</i>). Unfortunately, this was not the case with
+the grammar as specified in [ISO]. Two kinds of problems
+appeared, viz. the <b>alternation</b> and <b>repetition</b>
+conflict. The examples given in the following paragraphs are
+taken from the grammar.</p>
+<a name="2.2.1. Alternation conflict"></a>
+<h2>2.2.1. Alternation conflict</h2>
+
+<p>An alternation conflict arises when the parser can not
+decide which production to choose.<b><br>
+Example:</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<pre>procedure-declaration    : procedure-heading <b>&rsquo;;&rsquo;</b> directive |
+                           procedure-identification <b>&rsquo;;&rsquo;</b> procedure-block |
+                           procedure-heading <b>&rsquo;;&rsquo;</b> procedure-block ;
+procedure-heading        : <b>procedure</b> identifier [ formal-parameter-list ]? ;
+procedure-identification : <b>procedure</b> procedure-identifier ;
+</pre>
+</td>
+</table>
+
+<p>A sentence that starts with the terminal
+<b>procedure</b> is derived from the three alternative
+productions. This conflict can be resolved in two ways:
+adjusting the grammar, usually some rules are replaced by
+one rule and more work has to be done in the semantic
+analysis; using the LLgen conflict resolver,
+&quot;<b>%if</b> (C-expression)&quot;, if the C-expression
+evaluates to non-zero, the production in question is chosen,
+otherwise one of the remaining rules is chosen. The grammar
+rules were rewritten to solve this conflict. The new rules
+are given below. For more details see the file
+<i>declar.g</i>.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<pre>procedure-declaration : procedure-heading <b>&rsquo;;&rsquo;</b> ( directive | procedure-block ) ;
+procedure-heading     : <b>procedure</b> identifier [ formal-parameter-list ]? ;
+</pre>
+</td>
+</table>
+
+<p>A special case of an alternation conflict, which is
+common to many block structured languages, is the
+<i>&quot;dangling-else&quot;</i> ambiguity.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<pre>if-statement : <b>if</b> boolean-expression <b>then</b> statement [ else-part ]? ;
+else-part    : <b>else</b> statement ;
+</pre>
+</td>
+</table>
+
+<p>The following statement that can be derived from the
+rules above is ambiguous:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p><b>if</b> <tt>boolean-expr-1</tt> <b>then if</b>
+<tt>boolean-expr-2</tt> <b>then</b> <tt>statement-1</tt>
+<b>else</b> <tt>statement-2</tt></p>
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-100601.png"></small></p>
+
+<p><small>(a) (b)</small></p>
+
+<p align=center><small>Two parse trees showing the
+<i>dangling-else</i> ambiguity</small></p>
+
+<p><small>According to the standard, <b>else</b> is matched
+with the nearest preceding unmatched <b>then</b>, i.e. parse
+tree (a) is valid (<b>ISO 6.8.3.4</b>). This conflict is
+statically resolved in LLgen by using
+&quot;<b>%prefer</b>&quot;, which is equivalent in behaviour
+to &quot;<b>%if</b>(1)&quot;.</small></p>
+<a name="2.2.2. Repetition conflict"></a>
+<h2>2.2.2. Repetition conflict</h2>
+
+<p>A repetition conflict arises when the parser can not
+decide whether to choose a production once more, or
+not.<b><br>
+Example:</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<pre>field-list : [ ( fixed-part [ <b>&rsquo;;&rsquo;</b> variant-part ]? | variantpart ) [;]? ]? ;
+fixed-part : record-section [ <b>&rsquo;;&rsquo;</b> record-section ]* ;
+</pre>
+</td>
+</table>
+
+<p>When the parser sees the semicolon, it can not decide
+whether another record-section or a variant-part follows.
+This conflict can be resolved in two ways: adjusting the
+grammar or using the conflict resolver, &quot;<b>%while</b>
+(C-expression)&quot;. The grammar rules that deal with this
+conflict were completely rewritten. For more details, the
+reader is referred to the file <i>declar.g</i>.</p>
+<a name="2.3. Semantic Analysis"></a>
+<h2>2.3. Semantic Analysis</h2>
+
+<p>The third module of the compiler is the checking of
+semantic conventions of ISO-Pascal. To check the program
+being parsed, actions have been used in LLgen. An action
+consists of several C-statements, enclosed in brackets
+&quot;{&quot; and &quot;}&quot;. In order to facilitate
+communication between the actions and <i>LLparse</i>, the
+parsing routines can be given C-like parameters and local
+variables. An important part of the semantic analyzer is the
+symbol table. This table stores all information concerning
+identifiers and their definitions. Symbol-table lookup and
+hashing is done by a generic namelist module [ACK]. The
+parser turns each program construction into a parse tree,
+which is the major datastructure in the compiler. This parse
+tree is used to exchange information between various
+routines.</p>
+<a name="2.4. Code Generation"></a>
+<h2>2.4. Code Generation</h2>
+
+<p>The final module in the compiler is that of code
+generation. The information stored in the parse trees is
+used to generate the EM code [EM]. EM code is generated with
+the help of a procedural EM-code interface [ACK]. The use of
+static exchanges is not desired, since the fast back end can
+not cope with static code exchanges, hence the EM
+pseudoinstruction <b>exc</b> is never generated.<br>
+Chapter 3 discusses the code generation in more detail.</p>
+<a name="2.5. Error Handling"></a>
+<h2>2.5. Error Handling</h2>
+
+<p>The first three modules have in common that they can
+detect errors in the Pascal program being compiled. If this
+is the</p>
+
+<p>case, a proper message is given and some action is
+performed. If code generation has to be aborted, an error
+message is given, otherwise a warning is given. The constant
+MAXERR_LINE, defined in the file <i>errout.h</i>, specifies
+the maximum number of messages given per line. This can be
+used to avoid long lists of error messages caused by, for
+example, the omission of a &rsquo;;&rsquo;. Three kinds of
+errors can be distinguished: the lexical error, the
+syntactic error, and the semantic error. Examples of these
+errors are respectively, nested comments, an expression with
+unbalanced parentheses, and the addition of two
+characters.</p>
+<a name="2.6. Memory Allocation and Garbage Collection"></a>
+<h2>2.6. Memory Allocation and Garbage Collection</h2>
+
+<p>The routines <i>st_alloc</i> and <i>st_free</i> provide
+a mechanism for maintaining free lists of structures, whose
+first field is a pointer called <b>next</b>. This field is
+used to chain free structures together. Each structure,
+suppose the tag of the structure is ST, has a free list
+pointed by h_ST. Associated with this list are the
+operations: <i>new_ST()</i>, an allocating mechanism which
+supplies the space for a new ST struct; and
+<i>free_ST()</i>, a garbage collecting mechanism which links
+the specified structure into the free list.</p>
+<a name="3. Translation of Pascal to EM code"></a>
+<h2>3. Translation of Pascal to EM code</h2>
+
+<p>A short description of the translation of Pascal
+constructs to EM code is given in the following paragraphs.
+The EM instructions and Pascal terminal symbols are printed
+in <b>boldface</b>. A sentence in <i>italics</i> is a
+description of a group of EM (pseudo)instructions.</p>
+<a name="3.1. Global Variables"></a>
+<h2>3.1. Global Variables</h2>
+
+<p>For every global variable, a <b>bss</b> block is
+reserved. To enhance the readability of the EM-code
+generated, the variable-identifier is used as a data label
+to address the block.</p>
+<a name="3.2. Expressions"></a>
+<h2>3.2. Expressions</h2>
+
+<p>Operands are always evaluated, so the execution of</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>if</b> ( p &lt;&gt; nil ) <b>and</b> ( p^.value
+&lt;&gt; 0 ) <b>then</b> .....</p></td>
+</table>
+
+<p>might cause a run-time error, if p is equal to nil.</p>
+
+<p>The left-hand operand of a dyadic operator is almost
+always evaluated before the right-hand side. Peculiar
+evaluations exist for the following cases:</p>
+
+<p>the expression: set1 &lt;= set2, is evaluated as follows
+:</p>
+<pre>- evaluate set2
+- evaluate set1
+- compute set2+set1
+- test set2 and set2+set1 for equality
+</pre>
+
+<p>the expression: set1 &gt;= set2, is evaluated as follows
+:</p>
+<pre>- evaluate set1
+- evaluate set2
+- compute set1+set2
+- test set1 and set1+set2 for equality
+</pre>
+
+<p>Where allowed, according to the standard, constant
+integral expressions are compile-time evaluated while an
+effort is made to report overflow on target machine basis.
+The integral expressions are evaluated in the type
+<i>arith</i>. The size of an arith is assumed to be at least
+the size of the integer type on the target machine. If the
+target machine&rsquo;s integer size is less than the size of
+an arith, overflow can be detected at compile-time. However,
+the following call to the standard procedure new, <i>new(p,
+3+5)</i>, is illegal, because the second parameter is not a
+constant according to the grammar.</p>
+
+<p>Constant floating expressions are not compile-time
+evaluated, because the precision on the target machine and
+the precision on the machine on which the compiler runs
+could be different. The boolean expression <i>(1.0 + 1.0) =
+2.0</i> could evaluate to false.</p>
+<a name="3.3. Statements"></a>
+<h2>3.3. Statements</h2>
+<a name="3.3.1. Assignment Statement"></a>
+<h2>3.3.1. Assignment Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><tt>(variable-access | function-identifier)</tt>
+<b>:=</b> <tt>expression</tt></p>
+<!-- INDENTATION -->
+<p>EM :</p>
+<!-- INDENTATION -->
+<p><i>evaluate expression<br>
+store in variable-access or function-identifier</i></p>
+<!-- INDENTATION -->
+<p>In case of a function-identifier, a hidden temporary
+variable is used to keep the function result.</p>
+</td>
+</table>
+<a name="3.3.2. Goto Statement"></a>
+<h2>3.3.2. Goto Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>GOTO</b> <tt>label</tt></p>
+<!-- INDENTATION -->
+<p>EM : Two cases can be distinguished :</p></td>
+</table>
+
+<p>- local goto,</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>in which a <b>bra</b> is generated.</p>
+<!-- INDENTATION -->
+<p>- non-local goto, a goto_descriptor is build, containing
+the ProgramCounter of the instruction jumped to and an
+offset in the target procedure frame which contains the
+value of the StackPointer after the jump. The code for the
+jump itself is to load the address of the goto_descriptor,
+followed by a push of the LocalBase of the target procedure
+and a <b>cal</b> $_gto. A message is generated to indicate
+that a procedure or function contains a statement which is
+the target of a non-local goto.</p></td>
+</table>
+<a name="3.3.3. If Statement"></a>
+<h2>3.3.3. If Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>IF</b> <tt>boolean-expression</tt> <b>THEN</b>
+<tt>statement</tt></p>
+</td>
+</table>
+
+<p>EM :</p>
+<pre><i>    evaluation boolean-expression
+</i><b>    zeq</b> *exit_label
+<i>    code statement
+</i>   exit_label
+</pre>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>IF</b> <tt>boolean-expression</tt> <b>THEN</b>
+<tt>statement-1</tt> <b>ELSE</b> <tt>statement-2</tt></p>
+</td>
+</table>
+
+<p>EM :</p>
+<pre><i>    evaluation boolean-expression
+</i><b>    zeq</b> *else_label
+<i>    code statement-1
+</i><b>    bra</b> *exit_label
+   else_label
+<i>    code statement-2
+</i>   exit_label
+</pre>
+<a name="3.3.4. Repeat Statement"></a>
+<h2>3.3.4. Repeat Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>REPEAT</b> <tt>statement-sequence</tt> <b>UNTIL</b>
+<tt>boolean-expression</tt></p>
+</td>
+</table>
+
+<p>EM :</p>
+<pre>   repeat_label
+</pre>
+
+<p><i>code statement-sequence evaluation
+boolean-expression</i> <b>zeq</b> *repeat_label</p>
+<a name="3.3.5. While Statement"></a>
+<h2>3.3.5. While Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>WHILE</b> <tt>boolean-expression</tt> <b>DO</b>
+<tt>statement</tt></p>
+</td>
+</table>
+
+<p>EM :</p>
+<pre>   while_label
+<i>    evaluation boolean-expression
+</i><b>    zeq</b> *exit_label
+<i>    code statement
+</i><b>    bra</b> *while_label
+   exit_label
+</pre>
+<a name="3.3.6. Case Statement"></a>
+<h2>3.3.6. Case Statement</h2>
+
+<p>The case-statement is implemented using the <b>csa</b>
+and <b>csb</b> instructions.</p>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>CASE</b> <tt>case-expression</tt> <b>OF</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p><tt>case-constant-list-1</tt> <b>:</b>
+<tt>statement-1</tt> <b>;</b><tt><br>
+case-constant-list-2</tt> <b>:</b> <tt>statement-2</tt>
+<b>;</b><tt><br>
+.<br>
+.<br>
+case-constant-list-n</tt> <b>:</b> <tt>statement-n
+[</tt><b>;</b><tt>]</tt></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>END</b></p></td>
+</table>
+
+<p>The <b>csa</b> instruction is used if the range of the
+case-expression value is dense, i.e.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><tt>( upperbound &minus; lowerbound ) /
+number_of_cases</tt></p></td>
+</table>
+
+<p>is less than the constant DENSITY, defined in the file
+<i>density.h</i>.</p>
+
+<p>If the range is sparse, a <b>csb</b> instruction is
+used.</p>
+
+<p>EM :</p>
+<pre><i>    evaluation case-expression
+</i><b>    bra</b> *l1
+   c1
+<i>    code statement-1
+</i><b>    bra *</b>exit_label
+   c2
+<i>    code statement-2
+</i><b>    bra *</b>exit_label
+    .
+    .
+   cn
+<i>    code statement-n
+</i><b>    bra *</b>exit_label
+   .case_descriptor
+<i>    generation case_descriptor
+</i>   l1
+<b>    lae</b> .case_descriptor
+<b>    csa</b> size of (case-expression)
+   exit_label
+</pre>
+<a name="3.3.7. For Statement"></a>
+<h2>3.3.7. For Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>FOR</b> <tt>control-variable</tt> <b>:=</b>
+<tt>initial-value (</tt><b>TO</b> <tt>|</tt>
+<b>DOWNTO</b><tt>) final-value</tt> <b>DO</b>
+<tt>statement</tt></p>
+</td>
+</table>
+
+<p>The initial-value and final-value are evaluated at the
+beginning of the loop. If the values are not constant, they
+are evaluated once and stored in a temporary.</p>
+
+<p>EM :</p>
+<pre><i>    load initial-value
+    load final-value
+</i><b>    bgt</b> exit-label            (* DOWNTO : <b>blt</b> <i>exit-label</i> *)
+<i>    load initial-value
+</i>   l1
+<i>    store in control-variable
+    code statement
+    load control-variable
+</i><b>    dup</b> <i>control-variable
+    load final-value
+</i><b>    beq</b> exit_label
+<b>    inc</b> <i>control-variable</i>    (* DOWNTO : <b>dec</b> <i>control-variable</i> *)
+<b>    bra *</b>l1
+   exit_label
+</pre>
+
+<p>Note: testing must be done before
+incrementing(decrementing) the control-variable,<br>
+because wraparound could occur, which could lead to an
+infinite loop.</p>
+<a name="3.3.8. With Statement"></a>
+<h2>3.3.8. With Statement</h2>
+
+<p>PASCAL :</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>WITH</b> <tt>record-variable-list</tt> <b>DO</b>
+<tt>statement</tt></p>
+<!-- INDENTATION -->
+<p>The statement <b>WITH</b> r
+<small><small>1</small></small> , r
+<small><small>2</small></small> , ..., r
+<small><small>n</small></small> <b>DO</b>
+<tt>statement</tt></p>
+<!-- INDENTATION -->
+<p>is equivalent to <b>WITH</b> r
+<small><small>1</small></small> <b>DO WITH</b> r
+<small><small>2</small></small> <b>DO</b> ... <b>WITH</b> r
+<small><small>n</small></small> <b>DO</b>
+<tt>statement</tt></p>
+</td>
+</table>
+
+<p>The translation of</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>WITH</b> r <small><small>1</small></small> <b>DO</b>
+<tt>statement</tt></p></td>
+</table>
+
+<p>is</p>
+<pre><i>   push address of r<small><small>1
+</small></small>   store address in temporary
+   code statement
+</i></pre>
+
+<p>An occurrence of a field is translated into:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><i>load temporary<br>
+add field-offset</i></p></td>
+</table>
+<a name="3.4. Procedure and Function Calls"></a>
+<h2>3.4. Procedure and Function Calls</h2>
+
+<p>In general, the call</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>p(a <small><small>1</small></small> , a
+<small><small>2</small></small> , ...., a
+<small><small>n</small></small> )</p></td>
+</table>
+
+<p>is translated into the sequence:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><i>evaluate a<small><small>n
+</small></small>.
+.
+evaluate a<small><small>2
+</small></small>evaluate a<small><small>1
+</small></small>push localbase
+</i><b>cal</b> $p
+<i>pop parameters
+</i></pre>
+</td>
+</table>
+
+<p>i.e. the order of evaluation and binding of the
+actual-parameters is from right to left. In general, a copy
+of the actual-parameter is made when the formal-parameter is
+a value-parameter. If the formal-parameter is a
+variable-parameter, a pointer to the actual-parameter is
+pushed.</p>
+
+<p>In case of a function call, a <b>lfr</b> is generated,
+which pushes the function result on top of the stack.</p>
+<a name="3.5. Register Messages"></a>
+<h2>3.5. Register Messages</h2>
+
+<p>A register message can be generated to indicate that a
+local variable is never referenced indirectly. This implies
+that a register can be used for a variable. We distinguish
+the following classes, given in decreasing priority:</p>
+
+<p>&bull; control-variable and final-value of a
+for-statement</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>to speed up testing, and execution of the body of the
+for-statement</p>
+<!-- INDENTATION -->
+<p>&bull; record-variable of a with-statement</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>to improve the field selection of a record</p>
+<!-- INDENTATION -->
+<p>&bull; remaining local variables and parameters</p>
+</td>
+</table>
+<a name="3.6. Compile-time optimizations"></a>
+<h2>3.6. Compile-time optimizations</h2>
+
+<p>The only optimization that is performed is the
+evaluation of constant integral expressions. The
+optimization of constructs like</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><b>if</b> <tt>false</tt> <b>then</b>
+<tt>statement</tt>,</p></td>
+</table>
+
+<p>is left to either the peephole optimizer, or a global
+optimizer.</p>
+<a name="4. Conformant Arrays"></a>
+<h2>4. Conformant Arrays</h2>
+
+<p>A fifth kind of parameter, besides the value, variable,
+procedure, and function parameter, is the conformant array
+parameter (<b>ISO 6.6.3.7</b>). This parameter, undoubtedly
+the major addition to Pascal from the compiler
+writer&rsquo;s point of view, has been implemented. With
+this kind of parameter, the required bounds of the
+index-type of an actual parameter are not fixed, but are
+restricted to a specified range of values. Two types of
+conformant array parameters can be distinguished: variable
+conformant array parameters and value conformant array
+parameters.</p>
+<a name="4.1. Variable conformant array parameters"></a>
+<h2>4.1. Variable conformant array parameters</h2>
+
+<p>The treatment of variable conformant array parameters is
+comparable with the normal variable parameter. Both have in
+common that the parameter mechanism used is <i>call by
+reference</i>.<br>
+An example is:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>to sort variable length arrays of integers, the following
+Pascal procedure could be used:</p>
+<!-- INDENTATION -->
+<pre><b>procedure</b> bubblesort(<b>var</b> A : <b>array</b>[low..high : integer] <b>of</b> integer);
+<b>var</b> i, j : integer;
+<b>begin
+        for</b> j := high - 1 <b>downto</b> low <b>do
+                for</b> i := low <b>to</b> j <b>do
+                        if</b> A[i+1] &lt; A[i] <b>then</b> <i>interchange A[i] and A[i+1]
+</i><b>end</b>;
+</pre>
+</td>
+</table>
+
+<p>For every actual parameter, the base address of the
+array is pushed on the stack and for every
+index-type-specification, exactly one array descriptor is
+pushed.</p>
+<a name="4.2. Value conformant array parameters"></a>
+<h2>4.2. Value conformant array parameters</h2>
+
+<p>The treatment of value conformant array parameters is
+more complex than its variable counterpart.<br>
+An example is:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>an unpacked array of characters could be printed as a
+string with the following program part:</p>
+<!-- INDENTATION -->
+<pre><b>procedure</b> WriteAsString( A : <b>array</b>[low..high : integer] <b>of</b> char);
+<b>var</b> i : integer;
+<b>begin
+        for</b> i := low <b>to</b> high <b>do</b> write(A[i]);
+<b>end</b>;
+</pre>
+</td>
+</table>
+
+<p>The calling procedure pushes the base address of the
+actual parameter and the array descriptors belonging to it
+on the stack. Subsequently the procedure using the
+conformant array parameter is called. Because it is a
+<i>call by value</i>, the called procedure has to create a
+copy of the actual</p>
+
+<p>parameter. This implies that the calling procedure knows
+how much space on the stack must be reserved for the
+parameters. If the actual-parameter is a conformant array,
+the called procedure keeps track of the size of the
+activation record. Hence the restrictions on the use of
+value conformant array parameters, as specified in <b>ISO
+6.6.3.7.2</b>, are dropped.</p>
+
+<p>A description of the EM code generated by the compiler
+is:</p>
+<pre><i>load the stack adjustment sofar
+load base address of array parameter
+compute the size in bytes of the array
+add this size to the stack adjustment
+copy the array
+remember the new address of the array
+</i></pre>
+<a name="5. Compiler options"></a>
+<h2>5. Compiler options</h2>
+
+<p>There are some options available to control the
+behaviour of the compiler. Two types of options can be
+distinguished: compile-time options and run-time
+options.</p>
+<a name="5.1. Compile time options"></a>
+<h2>5.1. Compile time options</h2>
+
+<p>There are some options that can be set when the compiler
+is installed. Those options can be found in the file
+<i>Parameters</i>. To set a parameter just modify its
+definition in the file <i>Parameters</i>. The shell script
+in the file <i>make.hfiles</i> creates for each parameter a
+separate .h file. This mechanism is derived from the C
+compiler in ACK.</p>
+
+<p><b>IDFSIZE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>The maximum number of characters that are significant in
+an identifier. This value has to be at least the value of
+<b>MINIDFSIZE</b>, defined in the file <i>options.c</i>. A
+compile-time check is included to see if the value of
+<b>MINIDFSIZE</b> is legal. The compiler will not recognize
+some keywords if <b>IDFSIZE</b> is too small.</p></td>
+</table>
+
+<p><b>ISTRSIZE</b>, <b>RSTRSIZE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>The lexical analyzer uses these two values for the
+allocation of memory needed to store a string.
+<b>ISTRSIZE</b> is the initial number of bytes allocated.
+<b>RSTRSIZE</b> is the step size used for enlarging the
+memory needed.</p></td>
+</table>
+
+<p><b>NUMSIZE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>The maximum length of a numeric constant recognized by
+the lexical analyzer. It is an error if this length is
+exceeded.</p></td>
+</table>
+
+<p><b>ERROUT</b>, <b>MAXERR_LINE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>Used for error messages. <b>ERROUT</b> defines the file
+on which the messages are written. <b>MAXERR_LINE</b> is the
+maximum number of error messages given per line.</p></td>
+</table>
+
+<p><b>SZ_CHAR</b>, <b>AL_CHAR</b>, etc</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>The default values of the target machine sizes and
+alignments. The values can be overruled with the &minus;V
+option.</p></td>
+</table>
+
+<p><b>MAXSIZE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>This value must be set to the maximum of the values of
+the target machine sizes. This parameter is used in overflow
+detection (see also section 3.2).</p></td>
+</table>
+
+<p><b>DENSITY</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>This parameter is used to decide what EM instruction has
+to be generated for a case-statement. If the range of the
+index value is sparse, i.e.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="84%">
+<p>(upperbound - lowerbound) / number_of_cases</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>is more than some threshold (<b>DENSITY</b>) the
+<b>csb</b> instruction is chosen. If the range is dense a
+jump table is generated (<b>csa</b>). This uses more space.
+Reasonable values are 2, 3 or 4.<br>
+Higher values might also be reasonable on machines, which
+have lots of address space and memory (see also section
+3.3.3).</p></td>
+</table>
+
+<p><b>INP_READ_IN_ONE</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>Used by the generic input module. It can either be
+defined or not defined. Defining it has the effect that
+files will be read completely into memory using only one
+read-system call. This should be used only on machines with
+lots of memory.</p></td>
+</table>
+
+<p><b>DEBUG</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<pre>If this parameter is defined some built-in compiler-debugging tools can be used:
+  &bull; only lexical analyzing is done, if the &minus;l option is given.
+  &bull; if the &minus;I option is turned on, the allocated number of structures is printed.
+  &bull; the routine debug can be used to print miscellaneous information.
+  &bull; the routine PrNode prints a tree of nodes.
+  &bull; the routine DumpType prints information about a type structure.
+  &bull; the macro DO_DEBUG(x,y) defined as ((x) &amp;&amp; (y)) can be used to perform
+    several actions.
+
+
+</pre>
+</td>
+</table>
+<a name="5.2. Run time options"></a>
+<h2>5.2. Run time options</h2>
+
+<p>The run time options can be given in the command line
+when the compiler is called.<br>
+They all have the form: &minus;&lt;character&gt;<br>
+Depending on the option, a character string has to be
+specified. The following options are currently
+available:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>C</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>The lower case and upper case letters are treated
+different (<b>ISO 6.1.1</b>).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>u</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>The character &rsquo;_&rsquo; is treated like a letter,
+so it is allowed to use the underscore in identifiers.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="64%">
+<p>Note: identifiers starting with an underscore may cause
+problems, because<br>
+most identifiers in library routines start with an
+underscore.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>n</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>This option suppresses the generation of register
+messages.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>r</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>With this option rangechecks are generated where
+necessary.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>L</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>Do not generate EM <b>lin</b> and <b>fil</b>
+instructions. These instructions are used only for
+profiling.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>&minus;<b>M</b>&lt;number&gt;</p>
+</td>
+<td width="16%"></td>
+<td width="64%">
+
+<p>Set the number of characters that are significant in an
+identifier to &lt;number&gt;. The maximum significant
+identifier length depends on the constant IDFSIZE, defined
+in <i>idfsize.h</i>.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p>&minus;<b>i</b>&lt;number&gt;</p>
+</td>
+<td width="16%"></td>
+<td width="64%">
+
+<p>With this flag the setsize for a set of integers can be
+changed. The number must be the number of bits per set.
+Default value : (#bits in a word) &minus; 1</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>&minus;<b>w</b></p>
+</td>
+<td width="32%"></td>
+<td width="64%">
+
+<p>Suppress warning messages (see also section 2.5).</p>
+</td>
+</table>
+
+
+<p>&minus;<b>V</b>[[<b>w</b>|<b>i</b>|<b>f</b>|<b>p</b>|<b>S</b>][<i>size</i>]?[<i>.alignment</i>]?]*</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="35%"></td>
+<td width="64%">
+<p>Option to set the object sizes and alignments on the
+target machine dynamically. The objects that can be
+manipulated are:<b><br>
+w</b> word<b><br>
+i</b> integer<b><br>
+f</b> float<b><br>
+p</b> pointer<b><br>
+S</b> structure<br>
+In case of a structure, <i>size</i> is discarded and the
+<i>alignment</i> is the initial alignment of the structure.
+The effective alignment is the least common multiple of
+<i>alignment</i> and the alignment of its members. This
+option has been implemented so that the compiler can be used
+as cross compiler.</p>
+</td>
+</table>
+<a name="6. Extensions to Pascal as specified by ISO 7185"></a>
+<h2>6. Extensions to Pascal as specified by ISO 7185</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><b>ISO 6.1.3:</b></p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>The underscore is treated as a letter when the &minus;u
+option is turned on (see also section 5.2). This is
+implemented to be compatible with Pascal-VU and can be used
+in identifiers to increase readability.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p><b>ISO 6.1.4:</b></p>
+</td>
+<td width="4%"></td>
+<td width="72%">
+
+<p>The directive <i>extern</i> can be used in a
+procedure-declaration or function-declaration to specify
+that the procedure-block or function-block corresponding to
+that declaration is external to the program-block. This can
+be used in conjunction with library routines.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><b>ISO 6.1.9:</b> An</p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p>alternative representation for the following</p>
+</td>
+</table>
+
+<p>tokens and delimiting characters is recognized:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="37%"></td>
+<td width="62%">
+<p><b>token alternative token</b></p>
+<!-- INDENTATION -->
+<p><tt>^ @</tt></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><tt>[ (.<br>
+] .)</tt></p>
+<!-- INDENTATION -->
+<p><b>delimiting character alternative delimiting pair of
+characters</b></p>
+<!-- INDENTATION -->
+<p><tt>{ (*<br>
+} *)</tt></p>
+</td>
+</table>
+
+<p><b>ISO 6.6.3.7.2:</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p>A conformant array parameter can be passed as value
+conformant array parameter without the restrictions imposed
+by the standard. The compiler gives a warning. This is
+implemented to keep the parameter mechanism orthogonal (see
+also Chapter 4).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><b>ISO 6.9.3.1:</b> If</p>
+</td>
+<td width="2%"></td>
+<td width="68%">
+
+<p>the value of the argument <i>TotalWidth</i> of the</p>
+</td>
+</table>
+
+<p>required procedure <i>write</i> is zero or negative, no
+characters are written for character, string or boolean type
+arguments. If the value of the argument <i>FracDigits</i> of
+the required procedure <i>write</i> is zero or negative, the
+fraction and &rsquo;.&rsquo; character are suppressed for
+fixed-point arguments.</p>
+<a name="7. Deviations from the standard"></a>
+<h2>7. Deviations from the standard</h2>
+
+<p>The compiler deviates from the ISO 7185 standard with
+respect to the following clauses:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><b>ISO 6.1.3:</b></p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>Identifiers may be of any length and all characters of
+an identifier shall be significant in distinguishing between
+them.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>The constant IDFSIZE, defined in the file
+<i>idfsize.h</i>, determines the (maximum) significant
+length of an identifier. It can be set at run time with the
+&minus;M option (see also section on compiler
+options).</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><b>ISO 6.1.8:</b></p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>There shall be at least one separator between any pair
+of consecutive tokens made up of identifiers, word-symbols,
+labels or unsigned-numbers.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>A token separator is not needed when a number is followed
+by an identifier or a word-symbol. For example the input
+sequence, 2<b>then</b>, is recognized as the integer 2
+followed by the keyword <b>then</b>.</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="34%">
+
+<p><b>ISO 6.2.1:</b> The</p>
+</td>
+<td width="4%"></td>
+<td width="62%">
+
+<p>label-declaration-part shall specify all</p>
+</td>
+</table>
+
+<p>labels that prefix a statement in the corresponding
+statement-part.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>The compiler generates a warning if a label is declared
+but never defined.</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="20%">
+
+<p><b>ISO 6.2.2:</b></p>
+</td>
+<td width="8%"></td>
+<td width="72%">
+
+<p>The scope of identifiers and labels should start at the
+beginning of the block in which these identifiers or labels
+are declared.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>The compiler, as most other one pass compilers deviates
+in this respect, because the scope of variables and labels
+start at their defining-point.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><b>program</b> deviates<b>;<br>
+const</b><br>
+x <b>=</b> 3<b>;<br>
+procedure</b> p<b>;<br>
+const</b></p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>y <b>=</b> x<b>;</b><br>
+x <b>=</b> true<b>;</b></p>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><b>begin end;<br>
+begin<br>
+end.</b></p>
+<!-- INDENTATION -->
+<p>In procedure p, the constant y has the integer value 3.
+This program does not conform to the standard. In [SAL] a
+simple algorithm is described for enforcing the scope rules,
+it involves numbering all scopes encoutered in the program
+in order of their opening, and recording in each identifier
+table entry the number of the latest scope in which it is
+used.</p>
+<!-- INDENTATION -->
+<p>Note: The compiler does not deviate from the standard in
+the following program:</p>
+<!-- INDENTATION -->
+<pre><b>       program</b> conforms<b>;
+       type
+</b></pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>x <b>=</b> real<b>;</b></p>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><b>procedure</b> p<b>;<br>
+type</b></p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>y <b>= ^</b>x<b>;</b><br>
+x <b>=</b> boolean<b>;</b></p>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><b>var</b></p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>p <b>:</b> y<b>;</b></p>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="27%"></td>
+<td width="72%">
+<p><b>begin end;<br>
+begin<br>
+end.</b></p>
+<!-- INDENTATION -->
+<p>In procedure p, the variable p is a pointer to
+boolean.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="26%">
+
+<p><b>ISO 6.4.3.2:</b></p>
+</td>
+<td width="2%"></td>
+<td width="72%">
+
+<p>The standard specifies that any ordinal type is allowed
+as index-type.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>The required type <i>integer</i> is not allowed as
+index-type, i.e.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="37%"></td>
+<td width="62%">
+<p><b>ARRAY [</b> <i>integer</i> <b>] OF</b>
+&lt;component-type&gt; is not permitted.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>This could be implemented, but this might cause problems
+on machines with a small memory.</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%">
+
+<p><b>ISO 6.4.3.3:</b></p>
+</td>
+<td width="4%"></td>
+<td width="72%">
+
+<p>The type possessed by the variant-selector, called the
+tag-type, must be an ordinal type, so the integer type is
+permitted. The values denoted by all case-constants shall be
+distinct and the set thereof shall be equal to the set of
+values specified by the tag-type.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>Because it is impracticable to enumerate all integers as
+case-constants, the integer type is not permitted as
+tag-type. It would not make a great difference to allow it
+as tagtype.</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="30%">
+
+<p><b>ISO 6.8.3.9:</b></p>
+</td>
+<td width="4%"></td>
+<td width="66%">
+
+<p>The standard specifies that the</p>
+</td>
+</table>
+
+<p>control-variable of a for-statement is not allowed to be
+modified while executing the loop.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="33%"></td>
+<td width="66%">
+<p>Violation of this rule is not detected. An algorithm to
+implement this rule can be found in [PCV].</p>
+</td>
+</table>
+<a name="8. Hints to change the standard"></a>
+<h2>8. Hints to change the standard</h2>
+
+<p>We encoutered some difficulties when the compiler was
+developed. In this chapter some hints are presented to
+change the standard, which would make the implementation of
+the compiler less difficult. The semantics of Pascal would
+not be altered by these adaptions.</p>
+
+<p>&minus; Some minor changes in the grammar of Pascal from
+the user&rsquo;s point of view, but which make the writing
+of an LL(1) parser considerably easier, could be:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<pre>field-list   : [ ( fixed-part [ variant-part ] | variant-part ) ] .
+fixed-part   : record-section <b>;</b> { record-section <b>;</b> } .
+variant-part : <b>case</b> variant-selector <b>of</b> variant <b>;</b> { variant <b>;</b> } .
+
+case-statement : <b>case</b> case-index <b>of</b> case-list-element <b>;</b> { case-list-element <b>;</b> } <b>end</b> .
+</pre>
+</td>
+</table>
+
+<p>&minus; To ease the semantic checking on sets, the
+principle of qualified sets could be used, every
+set-constructor must be preceeded by its
+type-identifier:</p>
+<pre>   set-constructor : type-identifier <b>[</b> [ member-designator { <b>,</b> member-designator } ] <b>]</b> .
+</pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>Example:</p>
+</td>
+<td width="10%">
+
+<p>t1 = set of 1..5;</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%"></td>
+<td width="10%">
+
+<p>t2 = set of integer;</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>The type of [3, 5] would be ambiguous, but the type of
+t1[3, 5] not.</p>
+
+<p>&minus; Another problem arises from the fact that a
+function name can appear in three distinct &rsquo;use&rsquo;
+contexts: function call, assignment of function result and
+as function parameter.<br>
+Example:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><b>program</b> function_name;
+
+<b>function</b> p(x : integer; function y : integer) : integer;
+<b>begin</b> .. <b>end</b>;
+
+<b>function</b> f : integer;
+<b>begin
+</b>        f := p(f, f);     (*)
+<b>end</b>;
+
+<b>begin</b> .. <b>end</b>.
+</pre>
+</td>
+</table>
+
+<p>A possible solution in case of a call (also a procedure
+call) would be to make the (possibly empty)
+actual-parameter-list mandatory. The assignment of the
+function result could be changed in a <i>return</i>
+statement. Though this would change the semantics of the
+program slightly.<br>
+The above statement (*) would look like this: return p(f(),
+f);</p>
+
+<p>&minus; Another extension to the standard could be the
+implementation of an <i>otherwise</i> clause in a
+case-statement. This would behave exactly like the
+<i>default</i> clause in a switch-statement in C.</p>
+<a name="9. Testing the compiler"></a>
+<h2>9. Testing the compiler</h2>
+
+<p>Although it is practically impossible to prove the
+correctness of a compiler, a systematic method of testing
+the compiler is used to increase the confidence that it will
+work satisfactorily in practice. The first step was to see
+if the lexical analysis was performed correctly. For this
+purpose, the routine LexScan() was used (see also the
+&minus;l option). Next we tested the parser generated by
+LLgen, to see whether correct Pascal programs were accepted
+and garbage was dealed with gracefully. The biggest test
+involved was the validation of the semantic analysis.
+Simultaneously we tested the code generation. First some
+small Pascal test programs were translated and executed.
+When these programs work correctly, the Pascal validation
+suite and a large set of Pascal test programs were compiled
+to see whether they behaved in the manner the standard
+specifies. For more details about the Pascal validation
+suite, the reader is referred to [PCV].</p>
+<a name="10. Comparison with the Pascal-VU compiler"></a>
+<h2>10. Comparison with the Pascal-VU compiler</h2>
+
+<p>In this chapter, the differences with the Pascal-VU
+compiler [IM2] are listed. The points enumerated below can
+be used as improvements to the compiler (see also Chapter
+11).</p>
+<a name="10.1. Deviations"></a>
+<h2>10.1. Deviations</h2>
+
+<p>- large labels</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>only labels in the closed interval 0..9999 are allowed,
+as opposed to the Pascal-VU compiler. The Pascal-VU compiler
+allows every unsigned integer as label.</p></td>
+</table>
+
+<p>- goto</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>the new compiler conforms to the standard as opposed to
+the old one. The following program, which contains an
+illegal jump to label 1, is accepted by the Pascal-VU
+compiler.</p>
+<!-- INDENTATION -->
+<pre><b>program</b> illegal_goto(output);
+<b>label</b> 1;
+<b>var</b> i : integer;
+<b>begin
+</b></pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="10%">
+
+<p><b>goto</b> 1;</p>
+</td>
+<td width="10%"></td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="10%">
+
+<p><b>for</b> i := 1 <b>to</b> 10 <b>do</b></p>
+</td>
+<td width="10%"></td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="10%">
+
+<p><b>begin</b></p>
+</td>
+<td width="10%"></td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>1 : writeln(i);</p>
+</td>
+<td width="63%">
+</td>
+<tr valign="top" align="left">
+<td width="15%"></td>
+<td width="10%">
+
+<p><b>end</b>;</p>
+</td>
+<td width="10%"></td>
+<td width="63%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p><b>end</b>.</p>
+</td>
+</table>
+
+<p>This program is rejected by the new compiler.</p>
+<a name="10.2. Extensions"></a>
+<h2>10.2. Extensions</h2>
+
+<p>The extensions implemented by the Pascal-VU compiler are
+listed in Chapter 5 of [IM2].</p>
+
+<p>- separate compilation</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>the new compiler only accepts programs, not modules.</p>
+<!-- INDENTATION -->
+<p>- assertions not implemented.</p>
+<!-- INDENTATION -->
+<p>- additional procedures the procedures <i>halt, mark</i>
+and <i>release</i> are not available.</p>
+</td>
+</table>
+
+<p>- UNIX&trade; interfacing</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>the &minus;c option is not implemented.</p></td>
+</table>
+
+<p align=center><img src="grohtml-100602.png"></p>
+
+<p>- double length integers</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="5%"></td>
+<td width="94%">
+<p>integer size can be set with the &minus;V option, so the
+additional type <i>long</i> is not implemented.</p>
+</td>
+</table>
+<a name="10.3. Compiler options"></a>
+<h2>10.3. Compiler options</h2>
+
+<p>The options implemented by the Pascal-VU compiler are
+listed in Chapter 7 of [IM2].</p>
+
+<p>The construction &quot;{$....}&quot; is not
+recognized.</p>
+
+<p>The options: <i>a, c, d, s</i> and <i>t</i> are not
+available.</p>
+
+<p>The &minus;l option has been changed into the &minus;L
+option.</p>
+
+<p>The size of reals can be set with the &minus;V
+option.</p>
+<a name="11. Improvements to the compiler"></a>
+<h2>11. Improvements to the compiler</h2>
+
+<p>In consideration of portability, a restricted option
+could be implemented. Under this option, the extensions and
+warnings should be considered as errors.</p>
+
+<p>The restrictions imposed by the standard on the control
+variable of a for-statment should be implemented (<b>ISO
+6.8.3.9</b>).</p>
+
+<p>To check whether a function returns a valid result, the
+following algorithm could be used. When a function is
+entered a hidden temporary variable of type boolean is
+created. This variable is initialized with the value false.
+The variable is set to true, when an assignment to the
+function name occurs. On exit of the function a test is
+performed on the variable. If the value of the variable is
+false, a run-time error occurs.<br>
+Note: The check has to be done run-time.</p>
+
+<p>The <i>undefined value</i> should be implemented. A
+problem arises with local variables, for which space on the
+stack is allocated. A possible solution would be to generate
+code for the initialization of the local variables with the
+undefined value at the beginning of a procedure or
+function.</p>
+
+<p>The implementation for the global variables is easy,
+because <b>bss</b> blocks are used.</p>
+
+<p>Closely related to the last point is the generation of
+warnings when variables are never used or assigned. This is
+not yet implemented.</p>
+
+<p>The error messages could specify more details about the
+errors occurred, if some additional testing is done.</p>
+
+<p>Every time the compiler detects sets with different
+base-types, a warning is given. Sometimes this is
+superfluous.</p>
+<pre><b>program</b> sets(output);
+<b>type
+</b></pre>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>week = (sunday, monday, tuesday, wednesday, thursday,
+friday, saturday);</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+
+<p>workweek = monday..friday;</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p><b>var</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p>s : <b>set of</b> workweek;</p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+
+<p>day : week;</p>
+</td>
+</table>
+
+<p><b>begin</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="7" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p>day := monday;</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p>s := [day];</p>
+</td>
+<td width="20%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>(* warning *)</p>
+</td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p>day := saturday;</p>
+</td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="39%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="0%"></td>
+<td width="10%">
+
+<p>s := [day];</p>
+</td>
+<td width="20%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>(* warning *)</p>
+</td>
+<td width="39%">
+</td>
+</table>
+
+<p><b>end</b>.<br>
+The new compiler gives two warnings, the first one is
+redundant.</p>
+
+<p>A nasty point in the compiler is the way the procedures
+<i>read, readln, write</i> and <i>writeln</i> are handled
+(see also section 2.2). They have been added to the grammar.
+This implies that they can not be redefined as opposed to
+the other required procedures and functions. They should be
+removed from the grammar altogether. This could imply that
+more semantic checks have to be performed.</p>
+
+<p>No effort is made to detect possible run-time errors
+during compilation.<br>
+E.g. a : <b>array</b>[1..10] <b>of</b> <i>something</i>, and
+the array selection a[11] would occur.</p>
+
+<p>Some assistance to implement the improvements mentioned
+above, can be obtained from [PCV].</p>
+<a name="12. History &amp; Acknowledgements"></a>
+<h2>12. History &amp; Acknowledgements</h2>
+
+<p><b>History</b></p>
+
+<p>The purpose of this project was to make a Pascal
+compiler which should satisfy the conditions of the ISO
+standard. The task was considerably simplified, because
+parts of the Modula-2 compiler were used. This gave the
+advantage of increasing the uniformity of the compilers in
+ACK.<br>
+While developing the compiler, a number of errors were
+detected in the Modula-2 compiler, EM utility modules and
+the old Pascal compiler.</p>
+
+<p><b>Acknowledgements</b></p>
+
+<p>During the development of the compiler, valuable support
+was received from a number of persons. In this regard we owe
+a debt of gratitude to Fred van Beek, Casper Capel, Rob
+Dekker, Frank Engel, Jos&eacute; Gouweleeuw and Sonja
+Keijzer (Jut and Jul !!), Herold Kroon, Martin van
+Nieuwkerk, Sjaak Schouten, Eric Valk, and Didan Westra.<br>
+Special thanks are reserved for Dick Grune, who introduced
+us to the field of Compiler Design and who helped testing
+the compiler. Ceriel Jacobs, who developed LLgen and the
+Modula-2 compiler of ACK. Finally we would like to thank
+Erik Baalbergen, who had the supervision on this entire
+project and gave us many valuable suggestions.</p>
+<a name="13. References"></a>
+<h2>13. References</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[ISO]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>ISO 7185 Specification for Computer Programming Language
+Pascal, 1982, Acornsoft ISO-PASCAL, 1984</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>[EM]</p>
+</td>
+<td width="8%"></td>
+<td width="84%">
+
+<p>A.S. Tanenbaum, H. van Staveren, E.G. Keizer and J.W.
+Stevenson, <i>Description Of A Machine Architecture for use
+with Block Structured Languages</i>, Informatica Rapport
+IR-81, Vrije Universiteit, Amsterdam, 1983</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>[C]</p>
+</td>
+<td width="10%"></td>
+<td width="84%">
+
+<p>B.W. Kernighan and D.M. Ritchie, <i>The C Programming
+Language</i>, Prentice-Hall, 1978</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>[LL]</p>
+</td>
+<td width="8%"></td>
+<td width="84%">
+
+<p>C.J.H. Jacobs, <i>Some Topics in Parser Generation</i>,
+Informatica Rapport IR-105, Vrije Universiteit, Amsterdam,
+October 1985</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[IM2]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>J.W. Stevenson, <i>Pascal-VU Reference Manual and Unix
+Manual Pages</i>, Informatica Manual IM-2, Vrije
+Universiteit, Amsterdam, 1980</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[JEN]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>K. Jensen and N.Wirth, <i>Pascal User Manual and
+Report</i>, Springer-Verlag, 1978</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[ACK]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p><i>ACK Manual Pages</i>: ALLOC, ASSERT, EM_CODE, EM_MES,
+IDF, INPUT, PRINT, STRING, SYSTEM</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[AHO]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>A.V. Aho, R. Sethi and J.D. Ullman, <i>Compiler
+Principles, Techniques, and Tools</i>, Addison Wesley,
+1985</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[LEX]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>M.E. Lesk, <i>Lex - A Lexical Analyser Generator</i>,
+Comp. Sci. Tech. Rep. No. 39, Bell Laboratories, Murray
+Hill, New Jersey, October 1975</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[PCV]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>B.A. Wichmann and Z.J. Ciechanowicz, <i>Pascal Compiler
+Validation</i>, John Wiley &amp; Sons, 1983</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>[SAL]</p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p>A.H.J. Sale, <i>A Note on Scope, One-Pass Compilers and
+Pascal</i>, Australian Communications, 1, 1, 80-82, 1979</p>
+</td>
+</table>
+
+<p><b>Appendix A: ISO-PASCAL grammar</b></p>
+
+<p><b>A.1 Lexical tokens</b></p>
+
+<p>The syntax describes the formation of lexical tokens
+from characters and the separation of these tokens, and
+therefore does not adhere to the same rules as the syntax in
+A.2.</p>
+
+<p>The lexical tokens used to construct Pascal programs
+shall be classified into special-symbols, identifiers,
+directives, unsigned-numbers, labels and character-strings.
+The representation of any letter (upper-case or lower-case,
+differences of font, etc) occurring anywhere outside of a
+character-string shall be insignificant in that occurrence
+to the meaning of the program.</p>
+
+<p>letter = <b>a</b> | <b>b</b> | <b>c</b> | <b>d</b> |
+<b>e</b> | <b>f</b> | <b>g</b> | <b>h</b> | <b>i</b> |
+<b>j</b> | <b>k</b> | <b>l</b> | <b>m</b> | <b>n</b> |
+<b>o</b> | <b>p</b> | <b>q</b> | <b>r</b> | <b>s</b> |
+<b>t</b> | <b>u</b> | <b>v</b> | <b>w</b> | <b>x</b> |
+<b>y</b> | <b>z</b> .</p>
+
+<p>digit = <b>0</b> | <b>1</b> | <b>2</b> | <b>3</b> |
+<b>4</b> | <b>5</b> | <b>6</b> | <b>7</b> | <b>8</b> |
+<b>9</b> .</p>
+
+<p>The special symbols are tokens having special meanings
+and shall be used to delimit the syntactic units of the
+language.</p>
+
+<p>special-symbol = <b>+</b> | <b>&minus;</b> | <b>*</b> |
+<b>/</b> | <b>=</b> | <b>&lt;</b> | <b>&gt;</b> | <b>[</b> |
+<b>]</b> | <b>.</b> | <b>,</b> | <b>:</b> | <b>;</b> |
+<b>^</b> | <b>(</b> | <b>)</b> | <b>&lt;&gt;</b> |
+<b>&lt;=</b> | <b>&gt;=</b> | <b>:=</b> | <b>..</b> |
+word-symbol .</p>
+
+<p>word-symbol = <b>and</b> | <b>array</b> | <b>begin</b> |
+<b>case</b> | <b>const</b> | <b>div</b> | <b>do</b> |
+<b>downto</b> | <b>else</b> | <b>end</b> | <b>file</b> |
+<b>for</b> | <b>function</b> | <b>goto</b> | <b>if</b> |
+<b>in</b> | <b>label</b> | <b>mod</b> | <b>nil</b> |
+<b>not</b> | <b>of</b> | <b>or</b> | <b>packed</b> |
+<b>procedure</b> | <b>program</b> | <b>record</b> |
+<b>repeat</b> | <b>set</b> | <b>then</b> | <b>to</b> |
+<b>type</b> | <b>until</b> | <b>var</b> | <b>while</b> |
+<b>with</b> .</p>
+
+<p>Identifiers may be of any length. All characters of an
+identifier shall be significant. No identifier shall have
+the same spelling as any word-symbol.</p>
+
+<p>identifier = letter { letter | digit } .</p>
+
+<p>A directive shall only occur in a procedure-declaration
+or function-declaration. No directive shall have the same
+spelling as any word-symbol.</p>
+
+<p>directive = letter {letter | digit} .</p>
+
+<p>Numbers are given in decimal notation.</p>
+<pre>unsigned-integer = digit-sequence .
+unsigned-real = unsigned-integer <b>.</b> fractional-part [ <b>e</b> scale-factor ] | unsigned-integer <b>e</b> scale-factor .
+digit-sequence = digit {digit} .
+fractional-part = digit-sequence .
+</pre>
+
+<p>scale-factor = signed-integer . signed-integer = [sign]
+unsigned-integer . sign = <b>+</b> | <b>&minus;</b> .</p>
+
+<p>Labels shall be digit-sequences and shall be
+distinguished by their apparent integral values and shall be
+in the closed interval 0 to 9999.</p>
+
+<p>label = digit-sequence .</p>
+
+<p>A character-string containing a single string-element
+shall denote a value of the required char-type. Each
+string-character shall denote an implementation- defined
+value of the required char-type.</p>
+<pre>character-string = <b>&rsquo;</b> string-element { string-element } <b>&rsquo;</b> .
+string-element = apostrophe-image | string-character .
+apostrophe-image = <b>&rsquo;&rsquo;</b> .
+string-character = All 7-bits ASCII characters except linefeed (10), vertical tab (11), and new page (12).
+</pre>
+
+<p>The construct:</p>
+
+<p><b>{</b>
+any-sequence-of-characters-and-separations-of-lines-
+not-containing-right-brace <b>}</b></p>
+
+<p>shall be a comment if the &quot;{&quot; does not occur
+within a character-string or within a comment. The
+substitution of a space for a comment shall not alter the
+meaning of a program.</p>
+
+<p>Comments, spaces (except in character-strings), and the
+separation of consecutive lines shall be considered to be
+token separators. Zero or more token separators may occur
+between any two consecutive tokens, or before the first
+token of a program text. No separators shall occur within
+tokens.</p>
+
+<p><b>A.2 Grammar</b></p>
+
+<p>The non-terminal symbol <i>program</i> is the start
+symbol of the grammar.</p>
+<pre>actual-parameter : expression | variable-access | procedure-identifier | function-identifier .
+actual-parameter-list : <b>(</b> actual-parameter { <b>,</b> actual-parameter } <b>)</b> .
+adding-operator : <b>+</b> | <b>&minus;</b> | <b>or</b> .
+array-type : <b>array [</b> index-type { <b>,</b> index-type } <b>] of</b> component-type .
+array-variable : variable-access .
+assignment-statement : ( variable-access | function-identifier ) <b>:=</b> expression .
+
+base-type : ordinal-type .
+block : label-declaration-part constant-definition-part type-definition-part variable-declaration-part
+        procedure-and-function-declaration-part statement-part .
+Boolean-expression : expression .
+bound-identifier : identifier .
+buffer-variable : file-variable <b>^</b> .
+
+case-constant : constant .
+case-constant-list : case-constant { <b>,</b> case-constant } .
+case-index : expression .
+case-list-element : case-constant-list <b>:</b> statement .
+case-statement : <b>case</b> case-index <b>of</b> case-list-element { <b>;</b> case-list-element } [ <b>;</b> ] <b>end</b> .
+component-type : type-denoter .
+component-variable : indexed-variable | field-designator .
+compound-statement : <b>begin</b> statement-sequence <b>end</b> .
+conditional-statement : if-statement | case-statement .
+conformant-array-parameter-specification : value-conformant-array-specification |
+                  variable-conformant-array-specification .
+conformant-array-schema : packed-conformant-array-schema | unpacked-conformant-array-schema .
+constant : [ sign ] ( unsigned-number | constant-identifier ) | character-string .
+constant-definition : identifier <b>=</b> constant .
+constant-definition-part : [ <b>const</b> constant-definition <b>;</b> { constant-definition <b>;</b> } ] .
+constant-identifier : identifier .
+control-variable : entire-variable .
+
+domain-type : type-identifier .
+
+else-part : <b>else</b> statement .
+empty-statement : .
+entire-variable : variable-identifier .
+enumerated-type : <b>(</b> identifier-list <b>)</b> .
+expression : simple-expression [ relational-operator simple-expression ] .
+</pre>
+
+<p>factor : variable-access | unsigned-constant |
+bound-identifier | function-designator | set-constructor |
+<b>(</b> expression <b>)</b> | <b>not</b> factor .
+field-designator : record-variable <b>.</b> field-specifier
+| field-designator-identifier . field-designator-identifier
+: identifier . field-identifier : identifier . field-list :
+[ ( fixed-part [ <b>;</b> variant-part ] | variant-part ) [
+<b>;</b> ] ] . field-specifier : field-identifier .
+file-type : <b>file of</b> component-type . file-variable :
+variable-access . final-value : expression . fixed-part :
+record-section { <b>;</b> record-section } . for-statement :
+<b>for</b> control-variable <b>:=</b> initial-value (
+<b>to</b> | <b>downto</b> ) final-value <b>do</b> statement
+. formal-parameter-list : <b>(</b> formal-parameter-section
+{ <b>;</b> formal-parameter-section } <b>)</b> .
+formal-parameter-section : value-parameter-specification |
+variable-parameter-specification |
+procedural-parameter-specification |
+functional-parameter-specification |
+conformant-array-parameter-specification . function-block :
+block . function-declaration : function-heading <b>;</b>
+directive | function-identification <b>;</b> function-block
+| function-heading <b>;</b> function-block .
+function-designator : function-identifier [
+actual-parameter-list ] . function-heading : <b>function</b>
+identifier [ formal-parameter-list ] <b>:</b> result-type .
+function-identification : <b>function</b>
+function-identifier . function-identifier : identifier .
+functional-parameter-specification : function-heading .</p>
+
+<p>goto-statement : <b>goto</b> label .</p>
+
+<p>identified-variable : pointer-variable <b>^</b> .
+identifier-list : identifier { <b>,</b> identifier } .
+if-statement : <b>if</b> Boolean-expression <b>then</b>
+statement [ else-part ] . index-expression : expression .
+index-type : ordinal-type . index-type-specification :
+identifier <b>..</b> identifier <b>:</b>
+ordinal-type-identifier . indexed-variable : array-variable
+<b>[</b> index-expression { <b>,</b> index-expression }
+<b>]</b> . initial-value : expression .</p>
+
+<p>label : digit-sequence . label-declaration-part : [
+<b>label</b> label { <b>,</b> label } <b>;</b> ] .</p>
+
+<p>member-designator : expression [ <b>..</b> expression ]
+. multiplying-operator : <b>*</b> | <b>/</b> | <b>div</b> |
+<b>mod</b> | <b>and</b> .</p>
+
+<p>new-ordinal-type : enumerated-type | subrange-type .
+new-pointer-type : <b>^</b> domain-type .
+new-structured-type : [ <b>packed</b> ]
+unpacked-structured-type . new-type : new-ordinal-type |
+new-structured-type | new-pointer-type .</p>
+
+<p>ordinal-type : new-ordinal-type |
+ordinal-type-identifier . ordinal-type-identifier :
+type-identifier .</p>
+
+<p>packed-conformant-array-schema : <b>packed array [</b>
+index-type-specification <b>] of</b> type-identifier .
+pointer-type-identifier : type-identifier . pointer-variable
+: variable-access . procedural-parameter-specification :
+procedure-heading . procedure-and-function-declaration-part
+: { ( procedure-declaration | function-declaration )
+<b>;</b> } . procedure-block : block . procedure-declaration
+: procedure-heading <b>;</b> directive |
+procedure-identification <b>;</b> procedure-block |
+procedure-heading <b>;</b> procedure-block .
+procedure-heading : <b>procedure</b> identifier [
+formal-parameter-list ] . procedure-identification :
+<b>procedure</b> procedure-identifier . procedure-identifier
+: identifier . procedure-statement : procedure-identifier (
+[ actual-parameter-list ] | read-parameter-list |
+readln-parameter-list | write-parameter-list |
+writeln-parameter-list ) . program : program-heading
+<b>;</b> program-block <b>.</b> . program-block : block .
+program-heading : <b>program</b> identifier [ <b>(</b>
+program-parameters <b>)</b> ] . program-parameters :
+identifier-list .</p>
+
+<p>read-parameter-list : <b>(</b> [ file-variable <b>,</b>
+] variable-access { <b>,</b> variable-access } <b>)</b> .
+readln-parameter-list : [ <b>(</b> ( file-variable |
+variable-access ) { <b>,</b> variable-access } <b>)</b> ] .
+record-section : identifier-list <b>:</b> type-denoter .
+record-type : <b>record</b> field-list <b>end</b> .
+record-variable : variable-access . record-variable-list :
+record-variable { <b>,</b> record-variable } .
+relational-operator : <b>=</b> | <b>&lt;&gt;</b> |
+<b>&lt;</b> | <b>&gt;</b> | <b>&lt;=</b> | <b>&gt;=</b> |
+<b>in</b> . repeat-statement : <b>repeat</b>
+statement-sequence <b>until</b> Boolean-expression .
+repetitive-statement : repeat-statement | while-statement |
+for-statement . result-type : simple-type-identifier |
+pointer-type-identifier .</p>
+
+<p>set-constructor : <b>[</b> [ member-designator {
+<b>,</b> member-designator } ] <b>]</b> . set-type : <b>set
+of</b> base-type . sign : <b>+</b> | <b>&minus;</b> .
+simple-expression : [ sign ] term { adding-operator term } .
+simple-statement : empty-statement | assignment-statement |
+procedure-statement | goto-statement .
+simple-type-identifier : type-identifier .</p>
+
+<p>statement : [ label <b>:</b> ] ( simple-statement |
+structured-statement ) . statement-part : compound-statement
+. statement-sequence : statement { <b>;</b> statement } .
+structured-statement : compound-statement |
+conditional-statement | repetitive-statement |
+with-statement . subrange-type : constant <b>..</b> constant
+.</p>
+
+<p>tag-field : identifier . tag-type :
+ordinal-type-identifier . term : factor {
+multiplying-operator factor } . type-definition : identifier
+<b>=</b> type-denoter . type-definition-part : [ <b>type</b>
+type-definition <b>;</b> { type-definition <b>;</b> } ] .
+type-denoter : type-identifier | new-type . type-identifier
+: identifier .</p>
+
+<p>unpacked-conformant-array-schema : <b>array [</b>
+index-type-specification { <b>;</b> index-type-specification
+} <b>] of</b> ( type-identifier | conformant-array-schema )
+. unpacked-structured-type : array-type | record-type |
+set-type | file-type . unsigned-constant : unsigned-number |
+character-string | constant-identifier | <b>nil</b> .
+unsigned-number : unsigned-integer | unsigned-real .</p>
+
+<p>value-conformant-array-specification : identifier-list
+<b>:</b> conformant-array-schema .
+value-parameter-specification : identifier-list <b>:</b>
+type-identifier . variable-access : entire-variable |
+component-variable | identified-variable | buffer-variable .
+variable-conformant-array-specification : <b>var</b>
+identifier-list <b>:</b> conformant-array-schema .
+variable-declaration : identifier-list <b>:</b> type-denoter
+. variable-declaration-part : [ <b>var</b>
+variable-declaration <b>;</b> { variable-declaration
+<b>;</b> } ] . variable-identifier : identifier .
+variable-parameter-specification : <b>var</b>
+identifier-list <b>:</b> type-identifier . variant :
+case-constant-list <b>: (</b> field-list <b>)</b> .
+variant-part : <b>case</b> variant-selector <b>of</b>
+variant { <b>;</b> variant } . variant-selector : [
+tag-field <b>:</b> ] tag-type .</p>
+
+<p>while-statement : <b>while</b> Boolean-expression
+<b>do</b> statement . with-statement : <b>with</b>
+record-variable-list <b>do</b> statement . write-parameter :
+expression [ <b>:</b> expression [ <b>:</b> expression ] ] .
+write-parameter-list : <b>(</b> [ file-variable <b>,</b> ]
+write-parameter { <b>,</b> write-parameter } <b>)</b> .
+writeln-parameter-list : [ <b>(</b> ( file-variable |
+write-parameter ) { <b>,</b> write-parameter } <b>)</b> ]
+.</p>
+
+<p><b>Appendix B: Changes to the run time library</b></p>
+
+<p>Some minor changes in the run time library have been
+made concerning the external files (i.e. program arguments).
+The old compiler reserved space for the file structures of
+the external files in one <b>hol</b> block. In the new
+compiler, every file structure is placed in a separate
+<b>bss</b> block. This implies that the arguments with which
+<i>_ini</i> is called are slightly different. The second
+argument was the base of the <b>hol</b> block to relocate
+the buffer addresses, it is changed into an integer denoting
+the size of the array passed as third argument. The third
+argument was a pointer to an array of integers containing
+the description of external files, this argument is changed
+into a pointer to an array of pointers to file
+structures.</p>
+
+<p>The differences in the generated EM code for an
+arbitrary Pascal program are listed below (only the relevant
+parts are shown):</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre><b>program</b> external_files(output,f);
+<b>var
+</b></pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+
+<p>f : <b>file of</b> <i>some-type</i>;</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>.<br>
+.<b><br>
+end</b>.</p>
+<!-- INDENTATION -->
+<p>EM code generated by Pascal-VU:<br>
+.<br>
+.<br>
+hol 1088,-2147483648,0 ; space belonging to file structures
+of the program arguments<br>
+.<br>
+.<br>
+.<br>
+.2<br>
+con 3, -1, 544, 0 ; description of external files<br>
+lxl 0<br>
+lae .2<br>
+lae 0 ; base of hol block, to relocate buffer addresses<br>
+lxa 0<br>
+cal $_ini<br>
+asp 16<br>
+.<br>
+.</p>
+<!-- INDENTATION -->
+<p>EM code generated by our compiler:<br>
+.<br>
+.<br>
+f<br>
+bss 540,0,0 ; space belonging to file structure of program
+argument f<br>
+output<br>
+bss 540,0,0 ; space belonging to file structure of standard
+output</p>
+</td>
+</table>
+
+<p>. . . .2 con 0U4, output, f ; the absence of standard
+input is denoted by a null pointer lxl 0 lae .2 loc 3 ;
+denotes the size of the array of pointers to file structures
+lxa 0 cal $_ini asp 16 . .</p>
+
+<p>The following files in the run time library have been
+changed:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="98%">
+<p>pc_file.h hlt.c ini.c opn.c pentry.c pexit.c</p></td>
+</table>
+
+<p><b>Appendix C: An example</b></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>1</p>
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p><b>program</b> factorials(input, output);<br>
+2</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p>{ This program prints factorials }</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>3</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>4</p>
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p><b>const</b><br>
+5</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p>FAC1 = 1;<br>
+6</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p><b>var</b><br>
+7</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="8%"></td>
+<td width="10%">
+
+<p>i : integer;</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>8</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>9</p>
+</td>
+<td width="10%">
+
+<p><b>function</b> factorial(n : integer) : integer;</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>10</p>
+</td>
+<td width="10%">
+
+<p><b>begin</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>11</p>
+</td>
+<td width="10%">
+
+<p><b>if</b> n = FAC1 <b>then</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>12</p>
+</td>
+<td width="10%">
+
+<p>factorial := FAC1</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>13</p>
+</td>
+<td width="10%">
+
+<p><b>else</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>14</p>
+</td>
+<td width="10%">
+
+<p>factorial := n * factorial(n-1);</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>15</p>
+</td>
+<td width="10%">
+
+<p><b>end</b>;</p>
+</td>
+<td width="79%">
+</td>
+</table>
+
+<p>16</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>17</p>
+</td>
+<td width="10%">
+
+<p><b>begin</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>18</p>
+</td>
+<td width="10%">
+
+<p>write(&rsquo;Give a number : &rsquo;);</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>19</p>
+</td>
+<td width="10%">
+
+<p>readln(i);</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>20</p>
+</td>
+<td width="10%">
+
+<p><b>if</b> i &lt; 1 <b>then</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>21</p>
+</td>
+<td width="10%">
+
+<p>writeln(&rsquo;No factorial&rsquo;)</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>22</p>
+</td>
+<td width="10%">
+
+<p><b>else</b></p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>23</p>
+</td>
+<td width="10%">
+
+<p>writeln(factorial(i):1);</p>
+</td>
+<td width="79%">
+</td>
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>24</p>
+</td>
+<td width="10%">
+
+<p><b>end</b>.</p>
+</td>
+<td width="79%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="11" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>mes 2,4,4</p>
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loc 16<br>
+.1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_wrs<br>
+rom &rsquo;factorials.p\000&rsquo;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 12<br>
+i</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lin 19<br>
+bss 4,0,0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae input<br>
+output</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_rdi<br>
+bss 540,0,0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 4<br>
+input</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lfr 4<br>
+bss 540,0,0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>ste i<br>
+exp $factorial</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae input<br>
+pro $factorial, ?</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_rln<br>
+mes 9,4</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 4<br>
+lin 11</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lin 20<br>
+lol 0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loe i<br>
+loc 1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loc 1<br>
+cmi 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cmi 4<br>
+teq</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>tlt<br>
+zeq *1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>zeq *1<br>
+lin 12</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lin 21<br>
+loc 1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>.4<br>
+stl -4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>rom &rsquo;No factorial&rsquo;<br>
+bra *2</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae output<br>
+1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae .4<br>
+lin 14</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loc 12<br>
+lol 0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_wrs<br>
+lol 0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 12<br>
+loc 1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae output<br>
+sbi 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_wln<br>
+cal $factorial</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 4<br>
+asp 4</p>
+</td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>bra *2<br>
+lfr 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>1<br>
+mli 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lin 23<br>
+stl -4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae output<br>
+2</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loe i<br>
+lin 15</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $factorial<br>
+mes 3,0,4,0,0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 4<br>
+lol -4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lfr 4<br>
+ret 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loc 1<br>
+end 4</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_wsi<br>
+exp $m_a_i_n</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 12<br>
+pro $m_a_i_n, ?</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lae output<br>
+mes 9,0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_wln<br>
+fil .1</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>asp 4<br>
+.2</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>2<br>
+con input, output</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>lin 24<br>
+lxl 0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>loc 0<br>
+lae .2</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>cal $_hlt<br>
+loc 2</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>end 0<br>
+lxa 0</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>mes 4,24,&rsquo;factorials.p\000&rsquo;</p>
+</td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+</table>
+
+<p>cal $_ini asp 16 lin 18 .3 rom &rsquo;Give a number :
+&rsquo; lae output lae .3</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/pascal.pdf b/doc/tack/pascal.pdf
new file mode 100644 (file)
index 0000000..34ea952
Binary files /dev/null and b/doc/tack/pascal.pdf differ
diff --git a/doc/tack/pcref.html b/doc/tack/pcref.html
new file mode 100644 (file)
index 0000000..5486ff3
--- /dev/null
@@ -0,0 +1,2036 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:13 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title></title>
+</head>
+<body>
+
+<hr>
+
+<p align=center><b>Amsterdam Compiler Kit-Pascal reference
+manual</b></p>
+
+<p align=center>by</p>
+
+<p align=center>Johan W. Stevenson</p>
+
+<p align=center>( January 4, 1983 )</p>
+
+<p align=center>(revised)</p>
+
+<p align=center>Hans van Eck</p>
+
+<p align=center>( May 1, 1989 )</p>
+
+<p align=center>Vakgroep Informatica<br>
+Vrije Universiteit<br>
+De Boelelaan 1081<br>
+Amsterdam</p>
+
+<p><b>1. Introduction</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This document refers to the (1982) BSI standard for
+Pascal [1]. Ack-Pascal complies with the requirements of
+level 1 of BS 6192: 1982, with the exceptions as listed in
+this document.</p>
+<!-- INDENTATION -->
+<p>The standard requires an accompanying document describing
+the implementation-defined and implementation-dependent
+features, the reaction on errors and the extensions to
+standard Pascal. These four items will be treated in the
+rest of this document, each in a separate chapter. The other
+chapters describe the deviations from the standard and the
+list of options recognized by the compiler.</p>
+<!-- INDENTATION -->
+<p>The Ack-Pascal compiler produces code for an EM machine
+as defined in [2]. It is up to the implementor of the EM
+machine to decide whether errors like integer overflow,
+undefined operand and range bound error are recognized or
+not.</p>
+<!-- INDENTATION -->
+<p>There does not (yet) exist a hardware EM machine.
+Therefore, EM programs must be interpreted, or translated
+into instructions for a target machine. The Ack-Pascal
+compiler is currently available for use with the VAX,
+Motorola MC68020, Motorola MC68000, PDP-11, and Intel 8086
+code-generators. For the 8086, MC68000, and MC68020,
+floating point emulation is used. This is made available
+with the <i>-fp</i> option, which must be passed to
+<i>ack</i>[3].</p></td>
+</table>
+
+<p><b>2. Implementation-defined features</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>For each implementation-defined feature mentioned in the
+BSI standard we give the section number, the quotation from
+that section and the definition. First we quote the
+definition of implementation-defined:</p>
+<!-- INDENTATION -->
+<p>Possibly differing between processors, but defined for
+any particular processor.</p></td>
+</table>
+
+<p><b>BS 6.1.7:</b> Each string-character shall denote an
+implementation-defined value of the required char-type.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>All 7-bits ASCII characters except linefeed LF (10) are
+allowed.</p></td>
+</table>
+
+<p><b>BS 6.4.2.2:</b> The values of type real shall be an
+implementation-defined subset of the real numbers denoted as
+specified by 6.1.5 bu signed real.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The format of reals is not defined in EM. Even the size
+of reals depends on the EM-implementation. The compiler can
+be instructed, by the V-option, to use a different size for
+real values. The size of reals is preset by the calling
+program <i>ack</i> [3] to the proper size.</p></td>
+</table>
+
+<p><b>BS 6.4.2.2:</b> The type char shall be the
+enumeration of a set of implementation-defined characters,
+some possibly without graphic representations.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The 7-bits ASCII character set is used, where LF (10)
+denotes the end-of-line marker on text-files.</p>
+</td>
+</table>
+
+<p><b>BS 6.4.2.2:</b> The ordinal numbers of the character
+values shall be values of integer-type, that are
+implementation-defined, and that are determined by mapping
+the character values on to consecutive non-negative integer
+values starting at zero.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The normal ASCII ordering is used:
+ord(&rsquo;0&rsquo;)=48, ord(&rsquo;A&rsquo;)=65,
+ord(&rsquo;a&rsquo;)=97, etc.</p></td>
+</table>
+
+<p><b>BS 6.6.5.2:</b> The post-assertions imply
+corresponding activities on the external entities, if any,
+to which the file-variables are bound. These activities, and
+the point at which they are actually performed, shall be
+implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The reading and writing writing of objects on files is
+buffered. This means that when a program terminates
+abnormally, IO may be unfinished. Terminal IO is unbuffered.
+Files are closed whenever they are rewritten or reset, or on
+program termination.</p>
+</td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> The predefined constant maxint shall
+be of integer-type and shall denote an
+implementation-defined value, that satisfies the</p>
+
+<p>following conditions:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="1%"></td>
+<td width="98%">
+<p>(a) All integral values in the closed interval from
+-maxint to +maxint shall be values of the integer-type. (b)
+Any monadic operation performed on an integer value in this
+interval shall be correctly performed according to the
+mathematical rules for integer arithmetic. (c) Any dyadic
+integer operation on two integer values in this same
+interval shall be correctly performed according to the
+mathematical rules for integer arithmetic, provided that the
+result is also in this interval. (d) Any relational
+operation on two integer values in this same interval shall
+be correctly performed according to the mathematical rules
+for integer arithmetic.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The representation of integers in EM is a <i>n</i>*8-bit
+word using two&rsquo;s complement arithmetic. Where <i>n</i>
+is called wordsize. The range of available integers depends
+on the EM implementation: For 2-byte machines, the integers
+range from -32767 to +32767. For 4-byte machines, the
+integers range from -2147483647 to 2147483647. The number
+-maxint-1 may be used to indicate
+&rsquo;undefined&rsquo;.</p></td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> The result of the real arithmetic
+operators and functions shall be approximations to the
+corresponding mathematical results. The accuracy of this
+approximation shall be implementation-defined</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Since EM doesn&rsquo;t specify floating point format, it
+is not possible to specify the accuracy. When the floating
+point emulation is used, and the default size of reals is 8
+bytes, the accuracy is 11 bits for the exponent, and 53 bits
+for the mantissa. This gives an accuracy of about 16 digits,
+and exponents ranging from -309 to +307.</p></td>
+</table>
+
+<p><b>BS 6.9.3.1:</b> The default TotalWidth values for
+integer, Boolean and real types shall be
+implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The defaults are: integer 6 for 2-byte machines, 11 for
+4-byte machines Boolean 5 real 14</p>
+</td>
+</table>
+
+<p><b>BS 6.9.3.4.1:</b> ExpDigits, the number of digits
+written in an exponent part of a real, shall be
+implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>ExpDigits is defined as 3. This is sufficient for all
+implementations currently available. When the representation
+would need more than 3 digits, then the string
+&rsquo;***&rsquo; replaces the exponent.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.3.4.1:</b> The character written as part of
+the representation of a real to indicate the beginning of
+the exponent part shall be implementation-defined, either
+&rsquo;E&rsquo; or &rsquo;e&rsquo;.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The exponent part starts with &rsquo;e&rsquo;.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.3.5:</b> The case of the characters written as
+representation of the Boolean values shall be
+implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The representations of true and false are
+&rsquo;true&rsquo; and &rsquo;false&rsquo;.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.5:</b> The effect caused by the standard
+procedure page on a text file shall be
+implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The ASCII character form feed FF (12) is written.</p>
+</td>
+</table>
+
+<p><b>BS 6.10:</b> The binding of the variables denoted by
+the program-parameters to entities external to the program
+shall be implementation-defined if the variable is of a
+file-type.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The program parameters must be files and all, except
+input and output, must be declared as such in the program
+block.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The program parameters input and output, if specified,
+will correspond with the UNIX streams &rsquo;standard
+input&rsquo; and &rsquo;standard output&rsquo;.</p>
+<!-- INDENTATION -->
+<p>The other program parameters will be mapped to the
+argument strings provided by the caller of this program. The
+argument strings are supposed to be path names of the files
+to be opened or created. The order of the program parameters
+determines the mapping: the first parameter is mapped onto
+the first argument string etc. Note that input and output
+are ignored in this mapping.</p>
+<!-- INDENTATION -->
+<p>The mapping is recalculated each time a program parameter
+is opened for reading or writing by a call to the standard
+procedures reset or rewrite. This gives the programmer the
+opportunity to manipulate the list of string arguments using
+the external procedures argc, argv and argshift available in
+libpc [6].</p>
+</td>
+</table>
+
+<p><b>BS 6.10:</b> The effect of an explicit use of reset
+or rewrite on the standard textfiles input or output shall
+be implementation-defined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The procedures reset and rewrite are no-ops if applied to
+input or output.</p></td>
+</table>
+
+<p><b>3. Implementation-dependent features</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>For each implementation-dependent feature mentioned in
+the BSI standard, we give the section number, the quotation
+from that section and the way this feature is treated by the
+Ack-Pascal system. First we quote the definition of
+&rsquo;implementation-dependent&rsquo;:</p>
+<!-- INDENTATION -->
+<p>Possibly differing between processors and not necessarily
+defined for any particular processor.</p></td>
+</table>
+
+<p><b>BS 6.7.2.1:</b> The order of evaluation of the
+operands of a dyadic operator shall be
+implementation-dependent.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Operands are always evaluated, so the program part</p>
+<!-- INDENTATION -->
+<p>if (p&lt;&gt;nil) and (p^.value&lt;&gt;0) then</p>
+<!-- INDENTATION -->
+<p>is probably incorrect.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The left-hand operand of a dyadic operator is almost
+always evaluated before the right-hand side. Some peculiar
+evaluations exist for the following cases:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="11%"></td>
+<td width="88%">
+<p>1. the modulo operation is performed by a library routine
+to check for negative values of the right operand.</p>
+<!-- INDENTATION -->
+<p>2. the expression</p>
+<!-- INDENTATION -->
+<pre>        set1 &lt;= set2
+</pre>
+<!-- INDENTATION -->
+<p>where set1 and set2 are compatible set types is evaluated
+in the following steps:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>- evaluate set2<br>
+- evaluate set1<br>
+- compute set2+set1<br>
+- test set2 and set2+set1 for equality</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="11%"></td>
+<td width="88%">
+<p>3. the expression</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>set1 &gt;= set2</p>
+<!-- INDENTATION -->
+<p>where set1 and set2 are compatible set types is evaluated
+in the following steps:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>- evaluate set1<br>
+- evaluate set2<br>
+- compute set1+set2<br>
+- test set1 and set1+set2 for equality</p></td>
+</table>
+
+<p><b>BS 6.7.3:</b> The order of evaluation, accessing and
+binding of the</p>
+
+<p>actual-parameters for functions shall be
+implementation-dependent.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The order of evaluation is from right to left.</p>
+</td>
+</table>
+
+<p><b>BS 6.8.2.2:</b> The decision as to the order of
+accessing the variable and evaluating the expression in an
+assignment-statement, shall be implementation-dependent.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The expression is evaluated first.</p>
+</td>
+</table>
+
+<p><b>BS 6.8.2.3:</b> The order of evaluation and binding
+of the actual-parameters for procedures shall be
+implementation-dependent.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The same as for functions.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.5:</b> The effect of inspecting a text file to
+which the page procedure was applied during generation is
+implementation-dependent.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The formfeed character written by page is treated like a
+normal character, with ordinal value 12.</p>
+</td>
+</table>
+
+<p><b>BS 6.10:</b> The binding of the variables denoted by
+the program-parameters to entities external to the program
+shall be implementation-dependent unless the variable is of
+a file-type.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Only variables of a file-type are allowed as program
+parameters.</p></td>
+</table>
+
+<p><b>4. Error handling</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>There are three classes of errors to be distinguished. In
+the first class are the error messages generated by the
+compiler. The second class consists of the occasional errors
+generated by the other programs involved in the compilation
+process. Errors of the third class are the errors as defined
+in the standard by:</p>
+<!-- INDENTATION -->
+<p>An error is a violation by a program of the requirements
+of this standard that a processor is permitted to leave
+undetected.</p></td>
+</table>
+
+<p><b>4.1. Compiler errors</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Error are written on the standard error output. Each line
+has the form:</p></td>
+</table>
+
+<p>&lt;file&gt;, line &lt;number&gt;:
+&lt;description&gt;<br>
+Every time the compiler detects an error that does not have
+influence on the code produced by the compiler or on the
+syntax decisions, a warning messages is given. If only
+warnings are generated, compilation proceeds and probably
+results in a correctly compiled program.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Sometimes the compiler produces several errors for the
+same line. They are only shown up to a maximum of 5 errors
+per line. Warning are also shown up to a maximum of 5 per
+line.</p>
+<!-- INDENTATION -->
+<p>Extensive treatment of these errors is outside the scope
+of this manual.</p>
+</td>
+</table>
+
+<p><b>4.2. Runtime errors</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Errors detected at run time cause an error message to be
+generated on the diagnostic output stream (UNIX file
+descriptor 2). The message consists of the name of the
+program followed by a message describing the error, possibly
+followed by the source line number. Unless the -L-option is
+turned on, the compiler generates code to keep track of
+which source line causes which EM instructions to be
+generated. It depends on the EM implementation whether these
+LIN instructions are skipped or executed.</p>
+<!-- INDENTATION -->
+<p>For each error mentioned in the standard we give the
+section number, the quotation from that section and the way
+it is processed by the Pascal-compiler or runtime
+system.</p>
+<!-- INDENTATION -->
+<p>For detected errors the corresponding message and trap
+number are given. Trap numbers are useful for
+exception-handling routines. Normally, each error causes the
+program to terminate. By using exception-handling routines
+one can ignore errors or perform alternate actions. Only
+some of the errors can be ignored by restarting the failing
+instruction. These errors are marked as non-fatal, all
+others</p></td>
+</table>
+
+<p>as fatal. A list of errors with trap number between 0
+and 63 (EM errors) can be found in [2]. Errors with trap
+number between 64 and 127 (Pascal errors) are listed in
+[7].</p>
+
+<p><b>BS 6.4.6:</b> It shall be an error if a value of type
+T2 must be assignment-compatible with type T1, while T1 and
+T2 are compatible ordinal-types and the value of type T2 is
+not in the closed interval specified by T1.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The compiler distinguishes between array-index
+expressions and the other places where
+assignment-compatibility is required.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Array subscripting is done using the EM array
+instructions. These instructions have three arguments: the
+array base address, the index and the address of the array
+descriptor. An array descriptor describes one dimension by
+three values: the lower bound on the index, the number of
+elements minus one and the element-size. It depends on the
+EM implementation whether these bounds are checked. Since
+most implementations don&rsquo;t, an extra compiler flag is
+added to force these checks.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The other places where assignment-compatibility is
+required are:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>- assignment<br>
+- value parameters<br>
+- procedures read and readln<br>
+- the final value of the for-statement</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>For these places the compiler generates an EM range check
+instruction, except when the R-option is turned on, or when
+the range of values of T2 is enclosed in the range of T1. If
+the expression consists of a single variable and if that
+variable is of a subrange type, then the subrange type
+itself is taken as T2, not its host-type. Therefore, a range
+instruction is only generated if T1 is a subrange type and
+if the expression is a constant, an expression with two or
+more operands, or a single variable with a type not enclosed
+in T1. If a constant is assigned, then the EM optimizer
+removes the range check instruction, except when the value
+is out of bounds.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>It depends on the EM implementation whether the range
+check instruction is executed or skipped.</p>
+</td>
+</table>
+
+<p><b>BS 6.4.6:</b> It shall be an error if a value of type
+T2 must be assignment-compatible with type T1, while T1 and
+T2 are compatible set-types and any member of the value of
+type T2 is not in the closed interval specified by the
+base-type of the type T1.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.5.3.3:</b> It shall be an error if a component
+of a variant-part of a variant, where the selector of the
+variant-part is not a field, is accessed unless the variant
+is active for the entirety of each reference and access to
+each component of the variant.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.5.4:</b> It shall be an error if the
+pointer-variable of an identified-variable either denotes a
+nil-value or is undefined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The EM definition does not specify the binary
+representation of pointer values, so that it is not possible
+to choose an otherwise illegal binary representation for the
+pointer value NIL. Rather arbitrary the compiler uses the
+integer value zero to represent NIL. For all current
+implementations this does not cause problems.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The size of pointers depends on the implementation and is
+preset in the compiler by <i>ack</i> [3]. The compiler can
+be instructed, by the V-option, to use another size for
+pointer objects. NIL is represented here by the appropriate
+number of zero words.</p>
+<!-- INDENTATION -->
+<p>It depends on the EM implementation whether
+de-referencing of a pointer with value NIL causes an
+error.</p></td>
+</table>
+
+<p><b>BS 6.5.4:</b> It shall be an error to remove the
+identifying-value of an identified variable from its
+pointer-type when a reference to the variable exists.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>When the identified variable is an element of the
+record-variable-list of a with_statement, a warning is given
+at compile-time. Otherwise, this error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.5.5:</b> It shall be an error to alter the value
+of a file-variable f when a reference to the buffer-variable
+f^ exists.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>When f is altered when it is an element of the
+record-variable-list of a with-statement, a warning is
+given. When a buffer-variable is used as a
+variable-parameter, an error is given. This is done at
+compile-time.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.2:</b> It shall be an error if the stated
+pre-assertion does not hold immediately prior to any use of
+the file handling procedures rewrite, put, reset and
+get.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>For each of these four operations the pre-assertions can
+be reformulated as:</p>
+<!-- INDENTATION -->
+<p>rewrite(f): no pre-assertion.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>put(f): f is opened for writing and f^ is not
+undefined.<br>
+reset(f): f exists.<br>
+get(f): f is opened for reading and eof(f) is false.</p>
+<!-- INDENTATION -->
+<p>The following errors are detected for these
+operations:</p>
+<!-- INDENTATION -->
+<p>rewrite(f):</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>more args expected, trap 64, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>f is a program-parameter and the corresponding file name
+is not supplied by the caller of the program.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>rewrite error, trap 101, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>the caller of the program lacks the necessary access
+rights to create the file in the file system or
+operating</p></td>
+</table>
+
+<p>system problems like table overflow prevent creation of
+the file.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>put(f):</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>file not yet open, trap 72, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>reset or rewrite are never applied to the file. The
+checks performed by the run time system are not
+foolproof.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>not writable, trap 96, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>f is opened for reading.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>write error, trap 104, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>probably caused by file system problems. For instance,
+the file storage is exhausted. Because IO is buffered to
+improve performance, it might happen that this error occurs
+if the file is closed. Files are closed whenever they are
+rewritten or reset, or on program termination.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>reset(f):</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>more args expected, trap 64, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>same as for rewrite(f).</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>reset error, trap 100, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>f does not exist, or the caller has insufficient access
+rights, or operating system tables are exhausted.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>get(f):</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>file not yet open, trap 72, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>as for put(f).</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>not readable, trap 97, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>f is opened for writing.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>end of file, trap 98, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>eof(f) is true just before the call to get(f).</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>read error, trap 103, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>unlikely to happen. Probably caused by hardware problems
+or by errors elsewhere in the program that destroyed the
+file information maintained by the run time system.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>truncated, trap 99, fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>the file is not properly formed by an integer number of
+file elements. For instance, the size of a file of integer
+is odd.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>non-ASCII char read, trap 106, non-fatal:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>the character value of the next character-type file
+element is out of range (0..127). Only for text
+files.</p></td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error if a variant of
+a variant-part within the new variable becomes active and a
+different variant of the variant-part is one of the
+specified variants.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error to use
+dispose(q) if the identifying variable has been allocated
+using the form new(p,c1,...,cn).</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected. However, this error can cause
+more memory to be freed then was allocated. Dispose causes a
+fatal trap 73 when memory already on the free list is freed
+again.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error to use
+dispose(q,k1,...,km) if the identifying variable has been
+allocated using the form new(p,c1,...,cn) and m is not equal
+to n.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected. However, this error can cause
+more memory to be freed then was allocated. Dispose causes a
+fatal trap 73 when memory already on the free list is freed
+again.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error if the variants
+of a variable to be disposed are different from those
+specified by the case-constants to dispose.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error if the value of
+the pointer parameter of dispose has nil-value or is
+undefined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The same comments apply as for de-referencing NIL or
+undefined pointers.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.5.3:</b> It shall be an error if a variable
+created using the second form of new is accessed by the
+identified variable of the variable-access of a factor, of
+an assignment-statement, or of an actual-parameter.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is not detected.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.2:</b> It shall be an error if the value of
+sqr(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected for real-type arguments (real
+overflow, trap 4, non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.2:</b> It shall be an error if x in ln(x) is
+smaller than or equal to 0.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (error in ln, trap 66,
+non-fatal)</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.2:</b> It shall be an error if x in sqrt(x)
+is smaller than 0.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (error in sqrt, trap 67,
+non-fatal)</p>
+<!-- INDENTATION -->
+<p>In addition to these errors, overflow in the expression
+exp(x) is detected (error in exp, trap 65, non-fatal; real
+overflow, trap 4, non-fatal)</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.3:</b> It shall be an error if the integer
+value of trunc(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>It depends on the implementations whether this error is
+detected. The floating-point emulation detects this error
+(conversion error, trap 10, non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.3:</b> It shall be an error if the integer
+value of round(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>It depends on the implementations whether this error is
+detected. The floating-point emulation detects this error
+(conversion error, trap 10, non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.4:</b> It shall be an error if the integer
+value of ord(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error can not occur, because the compiler will not
+allow such ordinal types.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.4:</b> It shall be an error if the character
+value of chr(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Except when the R-option is off, the compiler generates
+an EM range check instruction. The effect of this
+instruction depends on the EM implementation.</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.4:</b> It shall be an error if the value of
+succ(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Same comments as for chr(x).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.4:</b> It shall be an error if the value of
+pred(x) does not exist.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Same comments as for chr(x).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.5:</b> It shall be an error if f in eof(f)
+is undefined.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (file not yet open, trap 72,
+fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.6.6.5:</b> It shall be an error if f in eoln(f)
+is undefined, or if eof(f) is true at that time.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The following errors may occur:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>file not yet open, trap 72, fatal;<br>
+not readable, trap 97, fatal;<br>
+end of file, trap 98, fatal.</p></td>
+</table>
+
+<p><b>BS 6.7.1:</b> It shall be an error if a
+variable-access used as an operand in an expression is
+undefined at the time of its use.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The compiler performs some limited checks to see if
+identifiers are used before they are set. Since it can not
+always be sure (one could, for instance, jump out of a
+loop), only a warning is generated. When an expression
+contains a function-call, an error occur if the function is
+not assigned at run-time.</p>
+</td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> A term of the form x/y shall be an
+error if y is zero.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>It depends on the EM implementation whether this error is
+detected. On some machines, a trap may occur.</p>
+</td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> It shall be an error if j is zero in
+&rsquo;i div j&rsquo;.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>It depends on the EM implementation whether this error is
+detected. On some machines, a trap may occur.</p></td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> It shall be an error if j is zero or
+negative in i MOD j.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (only positive j in &rsquo;i mod
+j&rsquo;, trap 71, non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.7.2.2:</b> It shall be an error if the result of
+any operation on integer operands is not performed according
+to the mathematical rules for integer arithmetic.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The reaction depends on the EM implementation. Most
+implementations, however, will not notice integer
+overflow.</p>
+</td>
+</table>
+
+<p><b>BS 6.8.3.5:</b> It shall be an error if none of the
+case-constants is equal to the value of the case-index upon
+entry to the case-statement.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (case error, trap 20, fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.9.1:</b> It shall be an error if the sequence of
+characters read looking for an integer does not form a
+signed-integer as specified in 6.1.5.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (digit expected, trap 105,
+non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.9.1:</b> It shall be an error if the sequence of
+characters read looking for a real does not form a
+signed-number as specified in 6.1.5.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (digit expected, trap 105,
+non-fatal).</p>
+</td>
+</table>
+
+<p><b>BS 6.9.1:</b> When read is applied to f, it shall be
+an error if the buffer-variable f^ is undefined or the
+pre-assertions for get do not hold.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (see get(f)).</p>
+</td>
+</table>
+
+<p><b>BS 6.9.3:</b> When write is applied to a textfile f,
+it shall be an error if f is undefined or f is opened for
+reading.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (see put(f)). Furthermore, this
+error is also detected when f is not a textfile.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.3.1:</b> The values of TotalWidth or
+FracDigits shall be greater than or equal to one; it shall
+be an error if either value is less then one.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>When either value is less than zero, an error (illegal
+field width, trap 75, non-fatal) occurs. Zero values are
+allowed, in order to maintain some compatibility with the
+old Ack-Pascal compiler.</p>
+</td>
+</table>
+
+<p><b>BS 6.9.5:</b> It shall be an error if the
+pre-assertion required for writeln(f) doe not hold prior to
+the invocation of page(f);</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>This error is detected (see put(f)).</p></td>
+</table>
+
+<p><b>5. Extensions to the standard</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>1. External routines</p>
+<!-- INDENTATION -->
+<p>Except for the required directive &rsquo;forward&rsquo;
+the Ack-Pascal compiler recognizes the directive
+&rsquo;extern&rsquo;. This directive tells the compiler that
+the procedure block of this procedure will not be present in
+the current program. The code for the body of this procedure
+must be included at a later stage of the compilation
+process.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>This feature allows one to build libraries containing
+often used routines. These routines do not have to be
+included in all the programs using them. Maintenance is much
+simpler if there is only one library module to be changed
+instead of many Pascal programs.</p>
+<!-- INDENTATION -->
+<p>Another advantage is that these library modules may be
+written in a different language, for instance C or the EM
+assembly language. This is useful for accessing some
+specific EM instructions not generated by the Pascal
+compiler. Examples are the system call routines and some
+floating point conversion routines. Another motive could be
+the optimization of some time-critical program parts.</p>
+<!-- INDENTATION -->
+<p>The use of external routines, however, is dangerous. The
+compiler normally checks for the correct number and type of
+parameters when a procedure is called and for the result
+type of functions. If an external routine is called these
+checks are not sufficient, because the compiler can not
+check whether the procedure heading of the external routine
+as given in the Pascal program matches the actual routine
+implementation. It should be the loader&rsquo;s task to
+check this. However, the current loaders are not that smart.
+Another solution is to check at run time, at least the
+number of words for parameters. Some EM implementations
+check this.</p>
+<!-- INDENTATION -->
+<p>For those who wish the use the interface between C and
+Pascal we give an incomplete list of corresponding formal
+parameters in C and Pascal.</p>
+<!-- INDENTATION -->
+<p>HTML-IMAGE.nr 3c 0</p>
+<!-- INDENTATION -->
+<pre>Pascal                  C
+
+
+
+
+
+a:integer               int a
+
+
+
+
+
+a:char                  int a
+
+
+
+
+
+a:boolean               int a
+
+
+
+
+
+a:real                  double a
+
+
+
+
+
+a:^type                 type *a
+
+
+
+
+
+var a:type              type *a
+
+
+
+
+
+procedure a(pars)       struct {
+
+
+
+
+
+                        void (*a)() ;
+
+
+
+
+
+                        char *static_link ;
+
+
+
+
+
+                   }
+
+
+
+
+
+function a(pars):type   struct {
+
+
+
+
+
+                        type (*a)() ;
+
+
+
+
+
+                        char *static_link ;
+
+
+
+
+
+                   }
+
+
+
+</pre>
+<!-- INDENTATION -->
+<p>HTML-IMAGE-ENDThe Pascal runtime system uses the
+following algorithm when calling function/procedures passed
+as parameters. HTML-IMAGE.nr 3c 0</p>
+<!-- INDENTATION -->
+<pre>if ( static_link )   (*a)(static_link,pars) ;
+
+
+
+
+
+else                 (*a)(pars) ;
+
+
+
+</pre>
+<!-- INDENTATION -->
+<p>HTML-IMAGE-END.ti -3 2. Separate compilation.</p>
+<!-- INDENTATION -->
+<p>The compiler is able to (separately) compile a collection
+of declarations, procedures and functions to form a library.
+The library may be linked with the main program, compiled
+later. The syntax of these modules is</p>
+<!-- INDENTATION -->
+<pre>module = [constant-definition-part]
+         [type-definition-part]
+         [var-declaration-part]
+         [procedure-and-function-declaration-part]
+</pre>
+<!-- INDENTATION -->
+<p>The compiler accepts a program or a module:</p>
+<!-- INDENTATION -->
+<pre>unit = program | module
+</pre>
+<!-- INDENTATION -->
+<p>All variables declared outside a module must be imported
+by parameters, even the files input and output. Access to a
+variable declared in a module is only possible using the
+procedures and functions declared in that same module. By
+giving the correct procedure/function heading followed by
+the directive &rsquo;extern&rsquo; procedures and functions
+declared in other units may be used.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>3. Assertions.</p>
+<!-- INDENTATION -->
+<p>When the s-option is off, Ack-Pascal compiler recognizes
+an additional statement, the assertion. Assertions can be
+used as an aid in debugging and documentation. The syntax
+is:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>assertion = &rsquo;assert&rsquo; Boolean-expression</p>
+<!-- INDENTATION -->
+<p>An assertion is a simple-statement, so</p>
+<!-- INDENTATION -->
+<pre>simple-statement = [assignment-statement |
+                    procedure-statement |
+                    goto-statement |
+                    assertion
+                   ]
+</pre>
+<!-- INDENTATION -->
+<p>An assertion causes an error if the Boolean-expression is
+false. That is its only purpose. It does not change any of
+the variables, at least it should not. Therefore, do not use
+functions with side-effects in the Boolean-expression. If
+the a-option is turned on, then assertions are skipped by
+the compiler. &rsquo;assert&rsquo; is not a word-symbol
+(keyword) and may be used as identifier. However, assignment
+to a variable and calling of a procedure with that name will
+be impossible. If the s-option is turned on, the compiler
+will not know a thing about assertions, so using assertions
+will then give a parse error.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>4. Additional procedures.</p>
+<!-- INDENTATION -->
+<p>Three additional standard procedures are available:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="11%"></td>
+<td width="88%">
+<p>halt: a call of this procedure is equivalent to jumping
+to the end of the program. It is always the last statement
+executed. The exit status of the program may be supplied as
+optional argument. If not, it will be zero. release: mark:
+for most applications it is sufficient to use the heap as
+second stack. Mark and release are suited for this type of
+use, more suited than dispose. mark(p), with p of type
+pointer, stores the current value of the heap pointer in p.
+release(p), with p initialized by a call of mark(p),
+restores the heap pointer to its old value. All the heap
+objects, created by calls of new between the call of mark
+and the call of release, are removed and the space they used
+can be reallocated. Never use mark and release together with
+dispose!</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>5. UNIX interfacing.</p>
+<!-- INDENTATION -->
+<p>If the c-option is turned on, then some special features
+are available to simplify an interface with the UNIX
+environment. First of all, the compiler allows for a
+different type of string constants. These string constants
+are delimited by double quotes (&rsquo;&quot;&rsquo;). To
+put a double quote into these strings, the double quote must
+be repeated, like the single quote in normal string
+constants. These special string constants are terminated by
+a zero byte (chr(0)). The type of these constants is a
+pointer to a packed array of characters, with lower bound 1
+and unknown upper bound.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Secondly, the compiler predefines a new type identifier
+&rsquo;string&rsquo; denoting this just described string
+type.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>These features are only useful for declaration of
+constants and variables of type &rsquo;string&rsquo;. String
+objects may not be allocated on the heap and string pointers
+may not be de-referenced. Still these strings are very
+useful in combination with external routines. The procedure
+write is extended to print these zero-terminated strings
+correctly.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>6. Double length (32 bit) integers.</p>
+<!-- INDENTATION -->
+<p>If the d-option is turned on, then the additional type
+&rsquo;long&rsquo; is known to the compiler. By default,
+long variables have integer values in the range
+-2147483647..+2147483647, but this can be changed with the
+-V option (if the backend can support this). Long constants
+can not be declared. Longs can not be used as
+control-variables. It is not allowed to form subranges of
+type long. All operations allowed on integers are also
+allowed on longs and are indicated by the same operators:
+&rsquo;+&rsquo;, &rsquo;-&rsquo;, &rsquo;*&rsquo;,
+&rsquo;/&rsquo;, &rsquo;div&rsquo;, &rsquo;mod&rsquo;. The
+procedures read and write have been extended to handle long
+arguments correctly. It is possible to read longs from a
+file of integers and vice-versa, but only if longs and
+integers have the same size. The default width for longs is
+11. The standard procedures &rsquo;abs&rsquo; and
+&rsquo;sqr&rsquo; have been extended to work on long
+arguments. Conversion from integer to long, long to real,
+real to long and long to integer are automatic, like the
+conversion from integer to real. These conversions may cause
+a</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>conversion error, trap 10, non-fatal</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>7. Underscore as letter.</p>
+<!-- INDENTATION -->
+<p>The character &rsquo;_&rsquo; may be used in forming
+identifiers, if the u- or U-option is turned on. It is
+forbidden to start identifiers with underscores, since this
+may cause name-clashes with run-time routines.</p>
+<!-- INDENTATION -->
+<p>8. Zero field width in write.</p>
+<!-- INDENTATION -->
+<p>Zero TotalWidth arguments are allowed. No characters are
+written for character, string or Boolean type arguments
+then. A zero FracDigits argument for fixed-point
+representation of reals causes the fraction and the
+character &rsquo;.&rsquo; to be suppressed.</p>
+<!-- INDENTATION -->
+<p>9. Pre-processing.</p>
+<!-- INDENTATION -->
+<p>If the very first character of a file containing a Pascal
+program is the sharp (&rsquo;#&rsquo;, ASCII 23(hex)) the
+file is preprocessed in the same way as C programs. Lines
+beginning with a &rsquo;#&rsquo; are taken as preprocessor
+command lines and not fed to the Pascal compiler proper. C
+style comments, /*......*/, are removed by the C
+preprocessor, thus C comments inside Pascal programs are
+also removed when they are fed through the
+preprocessor.</p></td>
+</table>
+
+<p><b>6. Deviations from the standard</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Ack-Pascal deviates from the standard proposal in the
+following ways:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>1. Standard procedures and functions are not allowed as
+parameters in Ack-Pascal. The same result can be obtained
+with negligible loss of performance by declaring some user
+routines like:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>function sine(x:real):real;<br>
+begin<br>
+sine:=sin(x)<br>
+end;</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>2. The standard procedures read, readln, write and
+writeln are implemented as word-symbols, and can therefore
+not be redeclared.</p></td>
+</table>
+
+<p><b>7. Compiler options</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Some options of the compiler may be controlled by using
+&quot;{$....}&quot;. Each option consists of a lower case
+letter followed by +, - or an unsigned number. Options are
+separated by commas. The following options exist:</p></td>
+</table>
+
+<p>a +/- this option switches assertions on and off. If
+this option is on, then code is included to test these
+assertions at run time. Default +.</p>
+
+<p>c +/- this option, if on, allows the use of C-type
+string constants surrounded by double quotes. Moreover, a
+new type identifier &rsquo;string&rsquo; is predefined.
+Default -.</p>
+
+<p>d +/- this option, if on, allows the use of variables of
+type &rsquo;long&rsquo;. Default -.</p>
+
+<p>i &lt;num&gt; with this flag the setsize for a set of
+integers can be manipulated. The number must be the number
+of bits per set. The default value is wordsize-1.</p>
+
+<p>l +/- if + then code is inserted to keep track of the
+source line number. When this flag is switched on and off,
+an incorrect line number may appear if the error occurs in a
+part of the program for which this flag is off. These same
+line numbers are used for the profile, flow and count
+options of the EM interpreter em [5]. Default +.</p>
+
+<p>r +/- if + then code is inserted to check subrange
+variables against lower and upper subrange limits. Default
++.</p>
+
+<p>s +/- if + then the compiler will hunt for places in the
+program where non-standard features are used, and for each
+place found it will generate a warning. Default -.</p>
+
+<p>t +/- if + then each time a procedure is entered, the
+routine &rsquo;procentry&rsquo; is called, and each time a
+procedure exits, the procedure &rsquo;procexit&rsquo; is
+called. Both &rsquo;procentry&rsquo; and
+&rsquo;procexit&rsquo; have a &rsquo;string&rsquo; as
+parameter. This means that when a user specifies his or her
+own procedures, the c-option must be used. Default
+procedures are present in the run time library. Default
+-.</p>
+
+<p>u +/- if + then the character &rsquo;_&rsquo; is treated
+like a letter, so that it may be used in identifiers.
+Procedure and function identifiers are not allowed to start
+with an underscore because they may collide with library
+routine names. Default -.</p>
+
+<p>Some of these flags (c, d, i, s, u, C and U) are only
+effective when they appear before the &rsquo;program&rsquo;
+symbol. The others may be switched on and off.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>A very powerful debugging tool is the knowledge that
+inaccessible statements and useless tests are removed by the
+EM optimizer. For</p></td>
+</table>
+
+<p>instance, a statement like:</p>
+<pre>        if debug then
+          writeln(&rsquo;initialization done&rsquo;);
+</pre>
+
+<p>is completely removed by the optimizer if debug is a
+constant with value false. The first line is removed if
+debug is a constant with value true. Of course, if debug is
+a variable nothing can be removed.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>A disadvantage of Pascal, the lack of preinitialized
+data, can be diminished by making use of the possibilities
+of the EM optimizer. For instance, initializing an array of
+reserved words is sometimes optimized into 3 EM
+instructions. To maximize this effect variables must be
+initialized as much as possible in order of declaration and
+array entries in order of decreasing index.</p></td>
+</table>
+
+<p><b>8. References</b></p>
+
+<p>[1] BSI standard BS 6192: 1982 (ISO 7185).</p>
+
+<p>[2] A.S.Tanenbaum, J.W.Stevenson, Hans van Staveren,
+E.G.Keizer, &quot;Description of a machine architecture for
+use with block structured languages&quot;, Informatica
+rapport IR-81.</p>
+
+<p>[3] UNIX manual ack(I).</p>
+
+<p>[4] UNIX manual ld(I).</p>
+
+<p>[5] UNIX manual em(I).</p>
+
+<p>[6] UNIX manual libpc(VII)</p>
+
+<p>[7] UNIX manual pc_prlib(VII)</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/pcref.pdf b/doc/tack/pcref.pdf
new file mode 100644 (file)
index 0000000..8646f3d
Binary files /dev/null and b/doc/tack/pcref.pdf differ
diff --git a/doc/tack/peep.html b/doc/tack/peep.html
new file mode 100644 (file)
index 0000000..1e71e3a
--- /dev/null
@@ -0,0 +1,1189 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:05 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Internal documentation on the peephole optimizer</title>
+</head>
+<body>
+
+<h1 align=center>Internal documentation on the peephole optimizer</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Table format">2. Table format</a><br>
+<a href="#3. Internal format">3. Internal format</a><br>
+<a href="#4. A tour through the sources">4. A tour through the sources</a><br>
+<a href="#4.1. The header files">4.1. The header files</a><br>
+<a href="#4.1.1. alloc.h">4.1.1. alloc.h</a><br>
+<a href="#4.1.2. assert.h">4.1.2. assert.h</a><br>
+<a href="#4.1.3. ext.h">4.1.3. ext.h</a><br>
+<a href="#4.1.4. line.h">4.1.4. line.h</a><br>
+<a href="#4.1.5. lookup.h">4.1.5. lookup.h</a><br>
+<a href="#4.1.6. optim.h">4.1.6. optim.h</a><br>
+<a href="#4.1.7. param.h">4.1.7. param.h</a><br>
+<a href="#4.1.8. pattern.h">4.1.8. pattern.h</a><br>
+<a href="#4.1.9. proinf.h">4.1.9. proinf.h</a><br>
+<a href="#4.1.10. tes.h">4.1.10. tes.h</a><br>
+<a href="#4.1.11. types.h">4.1.11. types.h</a><br>
+<a href="#4.2. The C code itself.">4.2. The C code itself.</a><br>
+<a href="#4.2.1. main.c">4.2.1. main.c</a><br>
+<a href="#4.2.2. getline.c">4.2.2. getline.c</a><br>
+<a href="#4.2.3. process.c">4.2.3. process.c</a><br>
+<a href="#4.2.4. backward.c">4.2.4. backward.c</a><br>
+<a href="#4.2.5. peephole.c">4.2.5. peephole.c</a><br>
+<a href="#4.2.6. tes.c">4.2.6. tes.c</a><br>
+<a href="#4.2.7. putline.c">4.2.7. putline.c</a><br>
+
+<hr>
+
+<p><b>from the Amsterdam Compiler Kit</b></p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p><small>Part of the Amsterdam Compiler Kit is a program
+to do peephole optimization on an EM program. The optimizer
+scans the program to match patterns from a table and if
+found makes the optimization from the table, and with the
+result of the optimization it tries to find yet another
+optimization continuing until no more optimizations are
+found.</small></p>
+
+<p><small>Furthermore it does some optimizations that can
+not be called peephole optimizations for historical reasons,
+like branch chaining and the deletion of unreachable
+code.</small></p>
+
+<p><small>The peephole optimizer consists of three
+parts</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="30%">
+
+<p><small>A driving table</small></p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>A program translating the table to internal
+format</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>C code compiled with the table to make the
+optimizer proper</small></p>
+</td>
+</table>
+
+<p><small>In this document the table format, internal
+format and data structures in the optimizer will be
+explained, plus a hint on what the code does where it might
+not be obvious. It is a simple program mostly.</small></p>
+<a name="2. Table format"></a>
+<h2>2. Table format</h2>
+
+<p><small>The driving table consists of pattern/replacement
+pairs, in principle one per line, although a line starting
+with white space is considered a continuation line for the
+previous. The general format is:</small></p>
+<pre><small>     optimization : pattern &rsquo;:&rsquo; replacement &rsquo;\n&rsquo;
+
+
+     pattern : EMlist optional_boolean_expression
+
+
+     replacement : EM_plus_operand_list
+</small></pre>
+
+<p><small>Example of a simple one</small></p>
+<pre><small>     loc stl $1==0 : zrl $2
+</small></pre>
+
+<p><small>There is no real limit for the length of the
+pattern or the replacement, the replacement might even be
+longer than the pattern, and expressions can be made
+arbitrarily complicated.</small></p>
+
+<p><small>The expressions in the table are made of the
+following pieces:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="34%">
+
+<p><small>Integer constants</small></p>
+</td>
+<td width="55%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>$<i>n</i>, standing for the operand of the
+<i>n</i>&rsquo;th EM instruction in the pattern, undefined
+if that instruction has no operand.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>w, standing for the wordsize of the code
+optimized.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="46%">
+
+<p><small>p, for the pointersize.</small></p>
+</td>
+<td width="43%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="88%">
+
+<p><small>defined(expr), true if expression is
+defined</small></p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>samesign(expr,expr), true if expressions have the
+same sign.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>sfit(expr,expr), ufit(expr,expr), true if the
+first expression fits signed or unsigned in the number of
+bits given in the second expression.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>rotate(expr,expr), first expression rotated left
+the number of bits given by the second
+expression.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>notreg(expr), true if the local with the
+expression as number is not a candidate to put in a
+register.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>rom(<i>n</i>,expr), contents of the rom
+descriptor at index expr that is associated with the global
+label that should be the argument of the <i>n</i>&rsquo;th
+EM instruction. Undefined if such a thing does not
+exist.</small></p>
+</td>
+</table>
+
+<p><small>The usual arithmetic operators may be used on
+integer values, if any operand is undefined the expression
+is undefined, except for the defined() function above. An
+undefined expression used for its truth value is false. All
+arithmetic on local label operands is forbidden, only things
+allowed are tests for equality. Arithmetic on global labels
+makes sense, i.e. one can add a global label and a constant,
+but not two global labels.</small></p>
+
+<p><small>In the table one can use five additional EM
+instructions in patterns. These are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>lab</small></p>
+</td>
+<td width="4%"></td>
+<td width="48%">
+
+<p><small>Stands for a local label</small></p>
+</td>
+<td width="41%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>LLP</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Load Local Pointer, translates into a <b>lol</b>
+or into a <b>ldl</b> depending on the relationship between
+wordsize and pointersize.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>LEP</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>Load External Pointer, translates into a
+<b>loe</b> or into a <b>lde</b>.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>SLP</small></p>
+</td>
+<td width="4%"></td>
+<td width="64%">
+
+<p><small>Store Local Pointer, <b>stl</b> or
+<b>sdl</b>.</small></p>
+</td>
+<td width="25%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>SEP</small></p>
+</td>
+<td width="4%"></td>
+<td width="70%">
+
+<p><small>Store External Pointer, <b>ste</b> or
+<b>sde</b>.</small></p>
+</td>
+<td width="19%">
+</td>
+</table>
+
+<p><small>There is only one peephole optimizer, so the
+substitutions to be made for the last four instructions are
+made at run time before the first optimizations are
+made.</small></p>
+<a name="3. Internal format"></a>
+<h2>3. Internal format</h2>
+
+<p><small>The translating program, <i>mktab</i> converts
+the table into an array of bytes where all patterns follow
+unaligned. Format of a pattern is:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>1)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>One byte for high byte of hash value, will be
+explained later on.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>2)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Two bytes for the index of the next pattern in a
+chain.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>3)</small></p>
+</td>
+<td width="6%"></td>
+<td width="24%">
+
+<p><small>An integer*,</small></p>
+</td>
+<td width="65%">
+</td>
+</table>
+
+
+<p align=center><small><img src="grohtml-99071.png"></small></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p><small>pattern length.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>4)</small></p>
+</td>
+<td width="6%"></td>
+<td width="84%">
+
+<p><small>The list of pattern opcodes, one per
+byte.</small></p>
+</td>
+<td width="5%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>5)</small></p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p><small>An integer expression index, 0 if not
+used.</small></p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>6)</small></p>
+</td>
+<td width="6%"></td>
+<td width="62%">
+
+<p><small>An integer, replacement length.</small></p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>7)</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>A list of pairs consisting of a one byte opcode
+and an integer expression index.</small></p>
+</td>
+</table>
+
+<p><small>The expressions are kept in an array of triples,
+implementing a binary tree. The <i>mktab</i> program tries
+to minimize the number of triples by reusing duplicates and
+even reverses the operands of commutative operators when
+doing so would spare a triple.</small></p>
+<a name="4. A tour through the sources"></a>
+<h2>4. A tour through the sources</h2>
+
+<p><small>Now we will walk through the sources and note
+things of interest.</small></p>
+<a name="4.1. The header files"></a>
+<h2>4.1. The header files</h2>
+
+<p><small>The header files are the place where data
+structures and options reside.</small></p>
+<a name="4.1.1. alloc.h"></a>
+<h2>4.1.1. alloc.h</h2>
+
+<p><small>In the header file alloc.h several defines can be
+used to select various kinds of core allocation schemes.
+This is important on small machines like the PDP-11 since a
+complete procedure must be in core at the same space, and
+the peephole optimizer should not be the limiting factor in
+determining the maximum size of procedures if possible.
+Options are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>USEMALLOC, standard malloc() and free() are used
+instead of the own core allocation package. Not recommended
+unless the own package does not work on some bizarre
+machine.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>COREDEBUG, prints large amounts of information
+about core management. Not recommended unless the code is
+changed and it stops working.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>SEPID, defining this will add an extra procedure
+that will go through a lot of work to scrape the last bytes
+together if the system won&rsquo;t provide more. This is not
+a good idea if memory is scarce and code and data reside in
+the same spaces, since the room used by the procedure might
+well be more than the room saved.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>STACKROOM, number of shorts used in stack space.
+This is used if memory is scarce and stack space and data
+space are different. On the PDP-11 a UNIX process starts
+with an 8K stack segment which cannot be transferred to the
+data segment. Under these conditions one can use a lot of
+the stack space for storage.</small></p>
+</td>
+</table>
+<a name="4.1.2. assert.h"></a>
+<h2>4.1.2. assert.h</h2>
+
+<p><small>Just defines the assert macro. When compiled with
+-DNDEBUG all asserts will be off.</small></p>
+<a name="4.1.3. ext.h"></a>
+<h2>4.1.3. ext.h</h2>
+
+<p><small>Gives external definitions of variables used by
+more than one module.</small></p>
+<a name="4.1.4. line.h"></a>
+<h2>4.1.4. line.h</h2>
+
+<p><small>Defines the structures used to keep instructions,
+one structure per line of EM code, and the structure to keep
+arguments of pseudos, one structure per argument. Both
+structures essentially contain a pointer to the next, a
+type, and a union containing information depending on the
+type. Core is allocated only for the part of the union
+used.</small></p>
+
+<p><small>The <i>struct line</i> has a very compact
+encoding for small integers, they are encoded in the type
+field. On the PDP-11 this gives a line structure of only 4
+bytes for most instructions.</small></p>
+<a name="4.1.5. lookup.h"></a>
+<h2>4.1.5. lookup.h</h2>
+
+<p><small>Contains definition of the struct used for symbol
+table management, global labels and procedure names are kept
+in one table.</small></p>
+<a name="4.1.6. optim.h"></a>
+<h2>4.1.6. optim.h</h2>
+
+<p><small>If one defines the DIAGOPT option in this header
+file, for every optimization performed a number is written
+on stderr. The number gives the number of the pattern in the
+table or one of the four special numbers in this header
+file.</small></p>
+<a name="4.1.7. param.h"></a>
+<h2>4.1.7. param.h</h2>
+
+<p><small>Contains one settable option, LONGOFF. If this is
+not defined the optimizer can only optimize programs with
+wordsize 2 and pointersize 2. Set this only if it must be
+run on a Z80 or something pathetic like that.</small></p>
+
+<p><small>Other defines here should not be
+touched.</small></p>
+<a name="4.1.8. pattern.h"></a>
+<h2>4.1.8. pattern.h</h2>
+
+<p><small>Contains defines of indices in a pattern,
+definition of the expression triples, definitions of the
+various expression operators and definition of the result
+struct where expression results are put.</small></p>
+
+<p><small>This header file is the main one that is also
+included by <i>mktab</i>.</small></p>
+<a name="4.1.9. proinf.h"></a>
+<h2>4.1.9. proinf.h</h2>
+
+<p><small>This one contains definitions for the local label
+table structs and for the struct where all information for
+one procedure is kept. This is in one struct so it can be
+saved easily when recursive procedures have to be
+resolved.</small></p>
+<a name="4.1.10. tes.h"></a>
+<h2>4.1.10. tes.h</h2>
+
+<p><small>Contains the data structure used by the top
+element size computation.</small></p>
+<a name="4.1.11. types.h"></a>
+<h2>4.1.11. types.h</h2>
+
+<p><small>Collection of typedefs to be used by almost all
+modules.</small></p>
+<a name="4.2. The C code itself."></a>
+<h2>4.2. The C code itself.</h2>
+
+<p><small>The C code will now be the center of our
+attention. We will make a walk through the sources and we
+will try to follow the sources in a logical order. So we
+will start at</small></p>
+<a name="4.2.1. main.c"></a>
+<h2>4.2.1. main.c</h2>
+
+<p><small>The main.c module contains the main() function.
+Here nothing spectacular happens, only thing of interest is
+the handling of flags:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>-L</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>This is an instruction to the peephole optimizer
+to perform one of its auxiliary functions, the generation of
+a library module. This makes the peephole optimizer write
+its output on a temporary file, and at the end making the
+real output by first generating a list of exported symbols
+and then copying the temporary file behind it.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p><small>-n</small></p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p><small>Disables all optimization. Only thing the
+optimizer does now is filling in the blank after the
+<i>END</i> pseudo and resolving recursive
+procedures.</small></p>
+</td>
+</table>
+
+<p><small>The place where main() is left is the call to
+getlines() which brings us to</small></p>
+<a name="4.2.2. getline.c"></a>
+<h2>4.2.2. getline.c</h2>
+
+<p><small>This module reads the EM code and constructs a
+list of <i>struct line</i> records, linked together
+backwards, i.e. the first instruction read is the last in
+the list. Pseudos are handled here also, for most pseudos
+this just means that a chain of argument records is linked
+into the linked line list but some pseudos get special
+attention:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>exc</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>This pseudo is acted upon right away. Lines read
+are shuffled around according to instruction.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>mes</small></p>
+</td>
+<td width="4%"></td>
+<td width="82%">
+
+<p><small>Some messages are acted upon. These
+are:</small></p>
+</td>
+<td width="7%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="12%">
+
+<p><small>ms_err</small></p>
+</td>
+<td width="4%"></td>
+<td width="74%">
+
+<p><small>The input is drained, just in case it is a pipe.
+After that the optimizer exits.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="12%">
+
+<p><small>ms_opt</small></p>
+</td>
+<td width="4%"></td>
+<td width="74%">
+
+<p><small>The do not optimize flag is set. Acts just like
+-n on the command line.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="12%">
+
+<p><small>ms_emx</small></p>
+</td>
+<td width="4%"></td>
+<td width="74%">
+
+<p><small>The word- and pointersize are read, complain if
+we are not able to handle this.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="12%">
+
+<p><small>ms_reg</small></p>
+</td>
+<td width="4%"></td>
+<td width="74%">
+
+<p><small>We take notice of the offset of this local. See
+also comments in the description of peephole.c</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>pro</small></p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p><small>A new procedure starts, if we are already in one
+save the status, else process collected input. Collect
+information about this procedure and if already in a
+procedure call getlines() recursively.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p><small>end</small></p>
+</td>
+<td width="4%"></td>
+<td width="48%">
+
+<p><small>Process collected input.</small></p>
+</td>
+<td width="41%">
+</td>
+</table>
+
+<p><small>The phrase &quot;process collected input&quot; is
+used twice, which brings us to</small></p>
+<a name="4.2.3. process.c"></a>
+<h2>4.2.3. process.c</h2>
+
+<p><small>This module contains the entry point process()
+which is called at any time the collected input must be
+processed. It calls a variety of other routines to get the
+real work done. Routines in this module are in chronological
+order:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>symknown</small></p>
+</td>
+<td width="8%"></td>
+<td width="76%">
+
+<p><small>Marks all symbols seen until now as known, i.e.
+it is now known whether their scope is local or global. This
+information is used again during output.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%">
+
+<p><small>symvalue</small></p>
+</td>
+<td width="8%"></td>
+<td width="76%">
+
+<p><small>Runs through the chain of pseudos to give values
+to data labels. This needs an extra pass. It cannot be done
+during the getlines pass, since an <b>exc</b> pseudo could
+destroy things. Nor can it be done during the backward pass
+since it is impossible to do good fragment numbering
+backward.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="18%">
+
+<p><small>checklocs</small></p>
+</td>
+<td width="6%"></td>
+<td width="76%">
+
+<p><small>Checks whether all local labels referenced are
+defined. It needs to be sure about this since otherwise the
+semi global optimizations made cannot work.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="14%">
+
+<p><small>relabel</small></p>
+</td>
+<td width="10%"></td>
+<td width="76%">
+
+<p><small>This routine finds the final destination for each
+label in the procedure. Labels followed by unconditional
+branches or other labels are marked during the peephole fase
+and this leeds to chains of identical labels. These chains
+are followed here, and in the local label table each label
+has associated with it its replacement label, after this
+procedure is run. Care is taken in this routine to prevent a
+loop in the program to cause the optimizer to
+loop.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="22%">
+
+<p><small>cleanlocals</small></p>
+</td>
+<td width="2%"></td>
+<td width="76%">
+
+<p><small>This routine empties the local label table after
+everything is processed.</small></p>
+</td>
+</table>
+
+<p><small>But before this can all be done, the backward
+linked list of instructions first has to be reversed, so
+here comes</small></p>
+<a name="4.2.4. backward.c"></a>
+<h2>4.2.4. backward.c</h2>
+
+<p><small>The routine backward has a number of
+functions:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>It reverses the backward linked list, making two
+forward linked lists, one for the instructions and one for
+the pseudos.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>It notes the last occurrence of data labels in
+the backward linked list and puts it in the global symbol
+table. This is of course the first occurence in the
+procedure. This information is needed to decide whether the
+symbols are global or local to this module.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>It decides about the fragment boundaries of data
+blocks. Fragments are numbered backwards starting at 3. This
+is done to be able to make the type of an expression
+containing a symbol equal to its fragment. This type can
+then not clash with the types integer and local
+label.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>It allocates a rom buffer to every data label
+with a rom behind it, if that rom contains only plain
+integers at the start.</small></p>
+</td>
+</table>
+
+<p><small>The first thing done after process() has called
+backward() and some of its own little routines is a call to
+the real routine, the one that does the work the program was
+written for</small></p>
+<a name="4.2.5. peephole.c"></a>
+<h2>4.2.5. peephole.c</h2>
+
+<p><small>The first routines in peephole.c implement a
+linked list for the offsets of local variables that are
+candidates for a register implementation. Several patterns
+use the notreg() function, since it is forbidden to combine
+a load of that variable with the load of another and it is
+not allowed to take the address of that
+variable.</small></p>
+
+<p><small>The routine peephole hashes the patterns the
+first time it is called after which it doesn&rsquo;t do much
+more than calling optimize. But first
+hashpatterns().</small></p>
+
+<p><small>The patterns are hashed at run time of the
+optimizer because of the <b>LLP</b>, <b>LEP</b>, <b>SLP</b>
+and <b>SEP</b> instructions added to the instruction set in
+this optimizer. These are first replaced everywhere in the
+table by the correct replacement after which the first three
+instructions of the pattern are hashed and the pattern is
+linked into one of the 256 linked lists. There is a define
+CHK_HASH in this module that can be set if the randomness of
+the hashing function is not trusted.</small></p>
+
+<p><small>The attention now shifts to optimize(). This
+routine calls basicblock() for every piece of code between
+two labels. It also notes which labels have another label or
+a branch behind them so the relabel() routine from process.c
+can do something with that.</small></p>
+
+<p><small>Basicblock() keeps making passes over its basic
+block until no more optimizations are found. This might be
+inefficient if there is a long basicblock with some deep
+recursive optimization in one part of it. The entire basic
+block is then scanned a lot of times just for that one
+piece. The alternative is backing up after making an
+optimization and running through the same code again, but
+that is difficult in a single linked list.</small></p>
+
+<p><small>It hashes instructions and calls trypat() for
+every pattern that has a full hash value match, i.e. lower
+byte and upper byte equal. Longest pattern is tried
+first.</small></p>
+
+<p><small>Trypat() checks length and opcodes of the
+pattern. If correct it fills the iargs[] array with argument
+values and calculates the expression. If that is also
+correct the work shifts to tryrepl().</small></p>
+
+<p><small>Tryrepl() generates the list of replacement
+instructions, links it into the list and returns true. Why
+then the name tryrepl() if it always succeeds? Well, there
+is a mechanism in the optimizer, unused until today that
+makes it possible to do optimizations that cannot be
+described by the table. It is possible to give a number as a
+replacement which will cause the optimizer to call a routine
+special() to do some work. This routine might decide not to
+do an optimization and return false.</small></p>
+
+<p><small>The last routine that is called from process() is
+putline() to write the optimized code, bringing us
+to</small></p>
+<a name="4.2.6. tes.c"></a>
+<h2>4.2.6. tes.c</h2>
+
+<p><small>Contains the routines used by the top element
+size computation phase, which is run after the
+peephole-optimisation. The main routine of tes.c is
+tes_instr(). This looks at an instruction and decides the
+size of the element on top of the stack after the
+instruction is executed. When a label is defined or used,
+the size of the top element is remembered for later use.
+When the information in consistent throuhout the procedure,
+it is passed to the code generator by means of an ms_tes
+message.</small></p>
+<a name="4.2.7. putline.c"></a>
+<h2>4.2.7. putline.c</h2>
+
+<p><small>The major part of putline.c is the standard set
+of routines that makes EM compact code. The extra functions
+performed are:</small></p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>For every occurence of a global symbol it might
+be necessary to output a <b>exa</b>, <b>exp</b>, <b>ina</b>
+or <b>inp</b> pseudo instruction. That task is
+performed.</small></p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p><small>-</small></p>
+</td>
+<td width="8%"></td>
+<td width="90%">
+
+<p><small>The <b>lin</b> instructions are optimized here,
+<b>lni</b> instructions added for <b>lin</b> instructions
+and superfluous <b>lin</b> instructions deleted.</small></p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/peep.pdf b/doc/tack/peep.pdf
new file mode 100644 (file)
index 0000000..1932aab
Binary files /dev/null and b/doc/tack/peep.pdf differ
diff --git a/doc/tack/regadd.html b/doc/tack/regadd.html
new file mode 100644 (file)
index 0000000..5a6f7e7
--- /dev/null
@@ -0,0 +1,510 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:11 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>Addition of register variables to an existing table.</title>
+</head>
+<body>
+
+<h1 align=center>Addition of register variables to an existing table.</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Modifications to the table itself.">2. Modifications to the table itself.</a><br>
+<a href="#2.1. Register section">2.1. Register section</a><br>
+<a href="#2.2. Codesection">2.2. Codesection</a><br>
+<a href="#3. Modifications to mach.c">3. Modifications to mach.c</a><br>
+<a href="#4. Examples">4. Examples</a><br>
+<a href="#5. Afterthoughts.">5. Afterthoughts.</a><br>
+
+<hr>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p>This is a short description of the newest feature in the
+table driven code generator for the Amsterdam Compiler Kit.
+It describes how to add register variables to an existing
+table. This assumes a distribution of October 1983 or later.
+It is not clear whether one should read this when starting
+with a table for a new machine, or waiting till the table is
+well debugged already.</p>
+<a name="2. Modifications to the table itself."></a>
+<h2>2. Modifications to the table itself.</h2>
+<a name="2.1. Register section"></a>
+<h2>2.1. Register section</h2>
+
+<p>Just before the properties of the register one of the
+following can be added:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="12%">
+
+<p>regvar</p>
+</td>
+<td width="83%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="36%">
+
+<p>regvar ( pointer )</p>
+</td>
+<td width="59%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="30%">
+
+<p>regvar ( loop )</p>
+</td>
+<td width="65%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="32%">
+
+<p>regvar ( float )</p>
+</td>
+<td width="63%">
+</td>
+</table>
+
+<p>All register variables of one type must be of the same
+size, and they may have no subregisters.</p>
+<a name="2.2. Codesection"></a>
+<h2>2.2. Codesection</h2>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="96%">
+
+<p>Two pseudo functions are added to the list allowed
+inside expressions:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>inreg ( expr ) has as a parameter the offset of a local,
+and returns 0,1 or 2:</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>2:</p>
+</td>
+<td width="2%"></td>
+<td width="66%">
+
+<p>if the variable is in a register.</p>
+</td>
+<td width="17%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>1:</p>
+</td>
+<td width="2%"></td>
+<td width="84%">
+
+<p>if the variable could be in a register but
+isn&rsquo;t.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="4%">
+
+<p>0:</p>
+</td>
+<td width="2%"></td>
+<td width="80%">
+
+<p>if the variable cannot be in a register.</p>
+</td>
+<td width="3%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>regvar ( expr ) returns the register associated with the
+variable. Undefined if it is not in a register. So regvar (
+expr ) is defined if and only if inreg (expr ) == 2.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="96%">
+
+<p>It is now possible to remove() a register expression,
+this is of course needed for a store into a register
+local.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="96%">
+
+<p>The return out of a procedure may now involve register
+restores, so the special word &rsquo;return&rsquo; in the
+table will invoke a user defined function.</p>
+</td>
+</table>
+<a name="3. Modifications to mach.c"></a>
+<h2>3. Modifications to mach.c</h2>
+
+<p>If register variables are used in a table, the program
+<i>cgg</i> will define the word REGVARS during compilation
+of the sources. So the following functions described here
+should be bracketed by #ifdef REGVARS and #endif.</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="86%">
+
+<p>regscore(off,size,typ,freq,totyp) long off;</p>
+</td>
+<td width="9%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>This function should assign a score to a register
+variable, the score should preferably be the estimated
+number of bytes gained when it is put in a register. Off and
+size are the offset and size of the variable, typ is the
+type, that is reg_any, reg_pointer, reg_loop or reg_float.
+Freq is the number of times it occurs statically, and totyp
+is the type of the register it is planned to go into.<br>
+Keep in mind that the gain should be net, that is the cost
+for register save/restore sequences and the cost of
+initialisation in the case of parameters should already be
+included.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="22%">
+
+<p>i_regsave()</p>
+</td>
+<td width="73%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>This function is called at the start of a procedure, just
+before register saves are done. It can be used to initialise
+some variables if needed.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="22%">
+
+<p>f_regsave()</p>
+</td>
+<td width="73%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>This function is called at end of the register save
+sequence. It can be used to do the real saving if multiple
+register move instructions are available.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="96%">
+
+<p>regsave(regstr,off,size) char *regstr; long off;</p>
+</td>
+<td width="0%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>Should either do the real saving or set up a table to
+have it done by f_regsave. Note that initialisation of
+parameters should also be done, or planned here.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="2%">
+
+<p>-</p>
+</td>
+<td width="2%"></td>
+<td width="22%">
+
+<p>regreturn()</p>
+</td>
+<td width="73%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="3%"></td>
+<td width="96%">
+<p>Should restore saved registers and return. The function
+result is already in the function return area by
+now.</p></td>
+</table>
+<a name="4. Examples"></a>
+<h2>4. Examples</h2>
+
+<p>Here are some examples out of the PDP 11 table</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="8" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+
+<p>lol inreg($1)==2| |</p>
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="30%"></td>
+<td width="10%">
+
+<p>| regvar($1)</p>
+</td>
+<td width="10%">
+</td>
+<td width="20%"></td>
+<td width="10%">
+</td>
+<td width="0%">
+
+<p>| |</p>
+
+<p>lil inreg($1)==2| |</p>
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%">
+</td>
+<td width="30%"></td>
+<td width="10%">
+
+<p>| {regdef2, regvar($1)}</p>
+</td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="0%">
+</td>
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="10%"></td>
+<td width="30%"></td>
+<td width="10%"></td>
+<td width="10%"></td>
+<td width="20%"></td>
+<td width="10%"></td>
+<td width="0%">
+
+<p>| |</p>
+</td>
+</table>
+
+<p>stl inreg($1)==2| xsource2 |</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>remove(regvar($1))</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>move(%[1],regvar($1)) | | |</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+
+<p>inl inreg($1)==2| | remove(regvar($1))</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="5" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>&quot;inc %(regvar($1)%)&quot;</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="19%"></td>
+<td width="10%">
+</td>
+<td width="10%">
+
+<p>setcc(regvar($1)) | | |</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<a name="5. Afterthoughts."></a>
+<h2>5. Afterthoughts.</h2>
+
+<p>At the time of this writing the tables for the PDP 11
+and the M68000 and the VAX are converted, in all cases the
+two byte wordsize versions. No big problems have occurred,
+but experience has shown that it is necessary to check the
+table carefully for all patterns with locals in them. Code
+may be generated that uses the memoryslot the local is not
+in.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/regadd.pdf b/doc/tack/regadd.pdf
new file mode 100644 (file)
index 0000000..fab96c9
Binary files /dev/null and b/doc/tack/regadd.pdf differ
diff --git a/doc/tack/toolkit.html b/doc/tack/toolkit.html
new file mode 100644 (file)
index 0000000..f25c768
--- /dev/null
@@ -0,0 +1,938 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:16:55 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>A Practical Tool Kit for Making Portable Compilers</title>
+</head>
+<body>
+
+<h1 align=center>A Practical Tool Kit for Making Portable Compilers</h1>
+<a href="#*.">*.</a><br>
+<a href="#Introduction">Introduction</a><br>
+<a href="#*.">*.</a><br>
+<a href="#An Overview of the Amsterdam Compiler Kit">An Overview of the Amsterdam Compiler Kit</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Preprocessor">The Preprocessor</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Front Ends">The Front Ends</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Peephole Optimizer">The Peephole Optimizer</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Global Optimizer">The Global Optimizer</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Back End">The Back End</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Target Machine Optimizer">The Target Machine Optimizer</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Universal Assembler/Linker">The Universal Assembler/Linker</a><br>
+<a href="#*.">*.</a><br>
+<a href="#The Utility Package">The Utility Package</a><br>
+<a href="#*.">*.</a><br>
+<a href="#Summary and Conclusions">Summary and Conclusions</a><br>
+<a href="#*.">*.</a><br>
+<a href="#References">References</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>Andrew S. Tanenbaum<br>
+Hans van Staveren<br>
+E. G. Keizer<br>
+Johan W. Stevenson</i><br>
+Mathematics Dept.<br>
+Vrije Universiteit<br>
+Amsterdam, The Netherlands</p>
+
+<p>The Amsterdam Compiler Kit is an integrated collection
+of programs designed to simplify the task of producing
+portable (cross) compilers and interpreters. For each
+language to be compiled, a program (called a front end) must
+be written to translate the source program into a common
+intermediate code. This intermediate code can be optimized
+and then either directly interpreted or translated to the
+assembly language of the desired target machine. The paper
+describes the various pieces of the tool kit in some detail,
+as well as discussing the overall strategy.</p>
+
+<p>Keywords: Compiler, Interpreter, Portability,
+Translator</p>
+
+<p>CR Categories: 4.12, 4.13, 4.22</p>
+
+<p>Author&rsquo;s present addresses: A.S. Tanenbaum, H. van
+Staveren, E.G. Keizer: Mathematics Dept., Vrije
+Universiteit, Postbus 7161, 1007 MC Amsterdam, The
+Netherlands</p>
+
+<p>J.W. Stevenson: NV Philips, S&amp;I, T&amp;M, Building
+TQ V5, Eindhoven, The Netherlands</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="Introduction"></a>
+<h2>Introduction</h2>
+
+<p>As more and more organizations acquire many micro- and
+minicomputers, the need for portable compilers is becoming
+more and more acute. The present situation, in which each
+hardware vendor provides its own compilers -- each with its
+own deficiencies and extensions, and none of them compatible
+-- leaves much to be desired. The ideal situation would be
+an integrated system containing a family of (cross)
+compilers, each compiler accepting a standard source
+language and producing code for a wide variety of target
+machines. Furthermore, the compilers should be compatible,
+so programs written in one language can call procedures
+written in another language. Finally, the system should be
+designed so as to make adding new languages and new machines
+easy. Such an integrated system is being built at the Vrije
+Universiteit. Its design and implementation is the subject
+of this article.</p>
+
+<p>Our compiler building system, which is called the
+&quot;Amsterdam Compiler Kit&quot; (ACK), can be thought of
+as a &quot;tool kit.&quot; It consists of a number of parts
+that can be combined to form compilers (and interpreters)
+with various properties. The tool kit is based on an idea
+(UNCOL) that was first suggested in 1960 [7], but which
+never really caught on then. The problem which UNCOL
+attempts to solve is how to make a compiler for each of
+<i>N</i> languages on <i>M</i> different machines without
+having to write <i>N</i> x <i>M</i> programs.</p>
+
+<p>As shown in Fig. 1, the UNCOL approach is to write
+<i>N</i> &quot;front ends,&quot; each of which translates
+one source language to a common intermediate language, UNCOL
+(UNiversal Computer Oriented Language), and <i>M</i>
+&quot;back ends,&quot; each of which translates programs in
+UNCOL to a specific machine language. Under these
+conditions, only <i>N</i> + <i>M</i> programs must be
+written to provide all <i>N</i> languages on all <i>M</i>
+machines, instead of <i>N</i> x <i>M</i> programs.</p>
+
+<p>Various researchers have attempted to design a suitable
+UNCOL [2,8], but none of these have become popular. It is
+our belief that previous attempts have failed because they
+have been too ambitious, that is, they have tried to cover
+all languages and all machines using a single UNCOL. Our
+approach is more modest: we cater only to algebraic
+languages and machines whose memory consists of 8-bit bytes,
+each with its own address. Typical languages that could be
+handled include Ada, ALGOL 60, ALGOL 68, BASIC, C, FORTRAN,
+Modula, Pascal, PL/I, PL/M, PLAIN, and RATFOR, whereas
+COBOL, LISP, and SNOBOL would be less efficient. Examples of
+machines that could be included are the Intel 8080 and 8086,
+Motorola 6800, 6809, and 68000, Zilog Z80 and Z8000, DEC
+PDP-11 and VAX, and IBM 370 but not the Burroughs 6700, CDC
+Cyber, or Univac 1108 (because they are not byte-oriented).
+With these restrictions, we believe the old UNCOL idea can
+be used as the basis of a practical compiler-building
+system.</p>
+
+<p align=center>Fig. 1. The UNCOL model.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="An Overview of the Amsterdam Compiler Kit"></a>
+<h2>An Overview of the Amsterdam Compiler Kit</h2>
+
+<p>The tool kit consists of eight components:</p>
+
+<p>1. The preprocessor. 2. The front ends. 3. The peephole
+optimizer. 4. The global optimizer. 5. The back end. 6. The
+target machine optimizer. 7. The universal assembler/linker.
+8. The utility package.</p>
+
+<p>A fully optimizing compiler, depicted in Fig. 2, has
+seven cascaded phases. Conceptually, each component reads an
+input file and writes a transformed output file to be used
+as input to the next component. In practice, some components
+may use temporary files to allow multiple passes over the
+input or internal intermediate files.</p>
+
+<p align=center>Fig. 2. Structure of the Amsterdam Compiler
+Kit.</p>
+
+<p>In the following paragraphs we will briefly describe
+each component. After this overview, we will look at all of
+them again in more detail. A program to be compiled is first
+fed into the (language independent) preprocessor, which
+provides a simple macro facility, and similar textual
+facilties. The preprocessor&rsquo;s output is a legal
+program in one of the programming languages supported,
+whereas the input is a program possibly augmented with
+macros, etc.</p>
+
+<p>This output goes into the appropriate front end, whose
+job it is to produce intermediate code. This intermediate
+code (our UNCOL) is the machine language for a simple stack
+machine called EM (Encoding Machine). A typical front end
+might build a parse tree from the input, and then use the
+parse tree to generate EM code, which is similar to reverse
+Polish. In order to perform this work, the front end has to
+maintain tables of declared variables, labels, etc.,
+determine where to place the data structures in memory, and
+so on.</p>
+
+<p>The EM code generated by the front end is fed into the
+peephole optimizer, which scans it with a window of a few
+instructions, replacing certain inefficient code sequences
+by better ones. Such a search is important because EM
+contains instructions to handle numerous important special
+cases efficiently (e.g., incrementing a variable by 1). It
+is our strategy to relieve the front ends of the burden of
+hunting for special cases because there are many front ends
+and only one peephole optimizer. By handling the special
+cases in the peephole optimizer, the front ends become
+simpler, easier to write and easier to maintain.</p>
+
+<p>Following the peephole optimizer is a global optimizer
+[5], which unlike the peephole optimizer, examines the
+program as a whole. It builds a data flow graph to make
+possible a variety of global optimizations, among them,
+moving invariant code out of loops, avoiding redundant
+computations, live/dead analysis and eliminating tail
+recursion. Note that the output of the global optimizer is
+still EM code.</p>
+
+<p>Next comes the back end, which differs from the front
+ends in a fundamental way. Each front end is a separate
+program, whereas the back end is a single program that is
+driven by a machine dependent driving table. The driving
+table for a specific machine tells how the EM code is mapped
+onto the machine&rsquo;s assembly language. Although a
+simple driving table might just macro expand each EM
+instruction into a sequence of target machine instructions,
+a much more sophisticated translation strategy is normally
+used, as described later. For speed, the back end does not
+actually read in the driving table at run time. Instead, the
+tables are compiled along with the back end in advance,
+resulting in one binary program per machine.</p>
+
+<p>The output of the back end is a program in the assembly
+language of some particular machine. The next component in
+the pipeline reads this program and performs peephole
+optimization on it. The optimizations performed here involve
+idiosyncracies of the target machine that cannot be
+performed in the machine-independent EM-to-EM peephole
+optimizer. Typically these optimizations take advantage of
+special instructions or special addressing modes.</p>
+
+<p>The optimized target machine assembly code then goes
+into the final component in the pipeline, the universal
+assembler/linker. This program assembles the input to object
+format, extracting routines from libraries and including
+them as needed.</p>
+
+<p>The final component of the tool kit is the utility
+package, which contains various test programs, interpreters
+for EM code, EM libraries, conversion programs, and other
+aids for the implementer and user.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Preprocessor"></a>
+<h2>The Preprocessor</h2>
+
+<p>The function of the preprocessor is to extend all the
+programming languages by adding certain generally useful
+facilities to them in a uniform way. One of these is a
+simple macro system, in which the user can give names to
+character strings. The names can be used in the program,
+with the knowledge that they will be macro expanded prior to
+being input to the front end. Macros can be used for named
+constants, expanding short &quot;procedures&quot; in line,
+etc.</p>
+
+<p>Another useful facility provided by the preprocessor is
+the ability to include compile-time libraries. On large
+projects, it is common to have all the declarations and
+definitions gathered together in a few files that are
+textually included in the programs by instructing the
+preprocessor to read them in, thus fooling the front end
+into thinking that they were part of the source program.</p>
+
+<p>A third feature of the preprocessor is conditional
+compilation. The input program can be split up into labeled
+sections. By setting flags, some of the sections can be
+deleted by the preprocessor, thus allowing a family of
+slightly different programs to be conveniently stored on a
+single file.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Front Ends"></a>
+<h2>The Front Ends</h2>
+
+<p>A front end is a program that converts input in some
+source language to a program in EM. At present, front ends
+exist or are in preparation for Pascal, C, and Plain, and
+are being considered for Ada, ALGOL 68, FORTRAN 77, and
+Modula 2. Each of the present front ends is independent of
+all the other ones, although a general-purpose, table-driven
+front end is conceivable, provided one can devise a way to
+express the semantics of the source language in the driving
+tables. The Pascal front end uses a top-down parsing
+algorithm (recursive descent), whereas the C and Plain front
+ends are bottom-up.</p>
+
+<p>All front ends, independent of the language being
+compiled, produce a common intermediate code called EM,
+which is the assembly language for a simple stack machine.
+The EM machine is based on a memory architecture containing
+a stack for local variables, a (static) data area for
+variables declared in the outermost block and global to the
+whole program, and a heap for dynamic data structures. In
+some ways EM resembles P-code [6], but is more general,
+since it is intended for a wider class of languages than
+just Pascal.</p>
+
+<p>The EM instruction set has been described elsewhere
+[9,10,11] so we will only briefly summarize it here.
+Instructions exist to:</p>
+
+<p>1. Load a variable or constant of some length onto the
+stack. 2. Store the top item on the stack in memory. 3. Add,
+subtract, multiply, divide, etc. the top two stack items. 4.
+Examine the top one or two stack items and branch
+conditionally. 5. Call procedures and return from them.</p>
+
+<p>Loads and stores come in several variations,
+corresponding to the most common programming language
+semantics, for example, constants, simple variables, fields
+of a record, elements of an array, and so on. Distinctions
+are also made between variables local to the current block
+(i.e., stack frame), those in the outermost block (static
+storage), and those at intermediate lexicographic levels,
+which are accessed by following the static chain at run
+time.</p>
+
+<p>All arithmetic instructions have a type (integer,
+unsigned, real, pointer, or set) and an operand length,
+which may either be explicit or may be popped from the stack
+at run time. Monadic branch instructions pop an item from
+the stack and branch if it is less than zero, less than or
+equal to zero, etc. Dyadic branch instructions pop two
+items, compare them, and branch accordingly.</p>
+
+<p>In addition to these basic EM instructions, there is a
+collection of special purpose instructions (e.g., to
+increment a local variable), which are typically produced
+from the simple ones by the peephole optimizer. Although the
+complete EM instruction set contains nearly 150
+instructions, only about 60 of them are really primitive;
+the rest are simply abbreviations for commonly occurring EM
+instruction sequences.</p>
+
+<p>Of particular interest is the way object sizes are
+parametrized. The front ends allow the user to indicate how
+many bytes an integer, real, etc. should occupy. Given this
+information, the front ends can allocate memory, determining
+the placement of variables within the stack frame. Sizes for
+primitive types are restricted to 8, 16, 32, 64, etc. bits.
+The front ends are also parametrized by the target
+machine&rsquo;s word length and address size so they can
+tell, for example, how many &quot;load&quot; instructions to
+generate to move a 32-bit integer. In the examples used
+henceforth, we will assume a 16-bit word size and 16-bit
+integers.</p>
+
+<p>Since only byte-addressable target machines are
+permitted, it is nearly always possible to implement any
+requested sizes on any target machine. For example, the
+designer of the back end tables for the Z80 should provide
+code for 8-, 16-, and 32-bit arithmetic. In our view, the
+Pascal, C, or Plain programmer specifies what lengths are
+needed, without reference to the target machine, and the
+back end provides it. This approach greatly enhances
+portability. While it is true that doing all arithmetic
+using 32-bit integers on the Z80 will not be terribly fast,
+we feel that if that is what the programmer needs, it should
+be possible to implement it.</p>
+
+<p>Like all assembly languages, EM has not only machine
+instructions, but also pseudoinstructions. These are used to
+indicate the start and end of each procedure, allocate and
+initialize storage for data, and similar functions. One
+particularly important pseudoinstruction is the one that is
+used to transmit information to the back end for
+optimization purposes. It can be used to suggest variables
+that are good candidates to assign to registers, delimit the
+scope of loops, indicate that certain variables contain a
+useful value (next operation is a load) or not (next
+operation is a store), and various other things.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Peephole Optimizer"></a>
+<h2>The Peephole Optimizer</h2>
+
+<p>The peephole optimizer reads in unoptimized EM programs
+and writes out optimized ones. Both the input and output are
+expressed in a highly compact code, rather than in ASCII, to
+reduce the i/o time, which would otherwise dominate the CPU
+time. The program itself is table driven, and is, by and
+large, ignorant of the semantics of EM. The knowledge of EM
+is contained in a language- and machine-independent table
+consisting of about 400 pattern-replacement pairs. We will
+briefly describe the kinds of optimizations it performs
+below; a more complete discussion can be found in [9].</p>
+
+<p>Each line in the driving table describes one
+optimization, consisting of a pattern part and a replacement
+part. The pattern part is a series of one or more EM
+instructions and a boolean expression. The replacement part
+is a series of EM instructions with operands. A typical
+optimization might be:</p>
+
+<p>LOL LOC ADI STL ($1 = $4) and ($2 = 1) and ($3 = 2)
+==&gt; INL $1</p>
+
+<p>where the text prior to the ==&gt; symbol is the pattern
+and the text after it is the replacement. LOL loads a local
+variable onto the stack, LOC loads a constant onto the
+stack, ADI is integer addition, and STL is store local. The
+pattern specifies that four consecutive EM instructions are
+present, with the indicated opcodes, and that furthermore
+the operand of the first instruction (denoted by $1) and the
+fourth instruction (denoted by $4) are the same, the
+constant pushed by LOC is 1, and the size of the integers
+added by ADI is 2 bytes. (EM instructions have at most one
+operand, so it is not necessary to specify the operand
+number.) Under these conditions, the four instructions can
+be replaced by a single INL (increment local) instruction
+whose operand is equal to that of LOL.</p>
+
+<p>Although the optimizations cover a wide range, the main
+ones can be roughly divided into the following categories.
+<i>Constant folding</i> is used to evaluate constant
+expressions, such as 2*3 + 7 at compile time instead of run
+time. <i>Strength reduction</i> is used to replace one
+operation, such as multiply, by another, such as shift.
+<i>Reordering of expressions</i> helps in cases like -K/5,
+which can be better evaluated as K/-5, because the former
+requires a division and a negation, whereas the latter
+requires only a division. <i>Null instructions</i> include
+resetting the stack pointer after a call with 0 parameters,
+offsetting zero bytes to access the first element of a
+record, or jumping to the next instruction. <i>Special
+instructions</i> are those like INL, which deal with common
+special cases such as adding one to a variable or comparing
+something to zero. <i>Group moves</i> are useful because a
+sequence of consecutive moves can often be replaced with EM
+code that allows the back end to generate a loop instead of
+in line code. <i>Dead code elimination</i> is a technique
+for removing unreachable statements, possibly made
+unreachable by previous optimizations. <i>Branch chain
+compression</i> can be applied when a branch instruction
+jumps to another branch instruction. The first branch can
+jump directly to the final destination instead of
+indirectly.</p>
+
+<p>The last two optimizations logically belong in the
+global optimizer but are in the local optimizer for
+historical reasons (meaning that the local optimizer has
+been the only optimizer for many years and the optimizations
+were easy to do there).</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Global Optimizer"></a>
+<h2>The Global Optimizer</h2>
+
+<p>In contrast to the peephole optimizer, which examines
+the EM code a few lines at a time through a small window,
+the global optimizer examines the program&rsquo;s large
+scale structure. Three distinct types of optimizations can
+be found here:</p>
+
+<p>1. Interprocedural optimizations. 2. Intraprocedural
+optimizations. 3. Basic block optimizations.</p>
+
+<p>We will now look at each of these in turn.</p>
+
+<p>Interprocedural optimizations are those spanning
+procedure boundaries. The most important one is deciding to
+expand procedures in line, especially short procedures that
+occur in loops and pass several parameters. If it takes more
+time or memory to pass the parameters than to do the work,
+the program can be improved by eliminating the procedure.
+The inverse optimization -- discovering long common code
+sequences and turning them into a procedure -- is also
+possible, but much more difficult. Like much of the global
+optimizer&rsquo;s work, the decision to make or not make a
+certain program transformation is a heuristic one, based on
+knowledge of how the back end works, how most target
+machines are organized, etc.</p>
+
+<p>The heart of the global optimizer is its analysis of
+individual procedures. To perform this analysis, the
+optimizer must locate the basic blocks, instruction
+sequences which can be entered only at the top and exited
+only at the bottom. It then constructs a data flow graph,
+with the basic blocks as nodes and jumps between blocks as
+arcs.</p>
+
+<p>From the data flow graph, many important properties of
+the program can be discovered and exploited. Chief among
+these is the presence of loops, indicated by cycles in the
+graph. One important optimization is looking for code that
+can be moved outside the loop, either prior to it or
+subsequent to it. Such code motion saves execution time,
+although it does not save memory. Unrolling loops is also
+possible and desirable in some cases.</p>
+
+<p>Another area in which global analysis of loops is
+especially important is in register allocation. While it is
+true that EM does not have any registers to allocate, the
+optimizer can easily collect information to allow the back
+end to allocate registers wisely. For example, the global
+optimizer can collect static frequency-of-use and live/dead
+information about variables. (A variable is dead at some
+point in the program if its current value is not needed,
+i.e., the next reference to it overwrites it rather than
+reading it; if the current value will eventually be used,
+the variable is live.) If two variables are never
+simultaneously live over some interval of code (e.g., the
+body of a loop), they can be packed into a single variable,
+which, if used often enough, may warrant being assigned to a
+register.</p>
+
+<p>Many loops involve arrays: this leads to other
+optimizations. If an array is accessed sequentially, with
+each iteration using the next higher numbered element, code
+improvement is often possible. Typically, a pointer to the
+bottom element of each array can be set up prior to the
+loop. Within the loop the element is accessed indirectly via
+the pointer, which is also incremented by the element size
+on each iteration. If the target machine has an
+autoincrement addressing mode and the pointer is assigned to
+a register, an array access can often be done in a single
+instruction.</p>
+
+<p>Other intraprocedural optimizations include removing
+tail recursion (last statement is a recursive call to the
+procedure itself), topologically sorting the basic blocks to
+minimize the number of branch instructions, and common
+subexpression recognition.</p>
+
+<p>The third general class of optimizations done by the
+global optimizer is improving the structure of a basic
+block. For the most part these involve transforming
+arithmetic or boolean expressions into forms that are likely
+to result in better target code. As a simple example, A +
+B*C can be converted to B*C + A. The latter can often be
+handled by loading B into a register, multiplying the
+register by C, and then adding in A, whereas the former may
+involve first putting A into a temporary, depending on the
+details of the code generation table. Another example of
+this kind of basic block optimization is transforming -B + A
+&lt; 0 into the equivalent, but simpler, A &lt; B.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Back End"></a>
+<h2>The Back End</h2>
+
+<p>The back end reads a stream of EM instructions and
+generates assembly code for the target machine. Although the
+algorithm itself is machine independent, for each target
+machine a machine dependent driving table must be supplied.
+The driving table effectively defines the mapping of EM code
+to target code.</p>
+
+<p>It will be convenient to think of the EM instructions
+being read as a stream of tokens. For didactic purposes, we
+will concentrate on two kinds of tokens: those that load
+something onto the stack, and those that perform some
+operation on the top one or two values on the stack. The
+back end maintains at compile time a simulated stack whose
+behavior mirrors what the stack of a hardware EM machine
+would do at run time. If the current input token is a load
+instruction, a new entry is pushed onto the simulated
+stack.</p>
+
+<p>Consider, as an example, the EM code produced for the
+statement K := I + 7. If K and I are 2-byte local variables,
+it will normally be LOL I; LOC 7; ADI 2; STL K. Initially
+the simulated stack is empty. After the first token has been
+read and processed, the simulated stack will contain a stack
+token of type MEM with attributes telling that it is a
+local, giving its address, etc. After the second token has
+been read and processed, the top two tokens on the simulated
+stack will be CON (constant) on top and MEM directly
+underneath it.</p>
+
+<p>At this point the back end reads the ADI 2 token and
+looks in the driving table to find a line or lines that
+define the action to be taken for ADI 2. For a typical
+multiregister machine, instructions will exist to add
+constants to registers, but not to memory. Consequently, the
+driving table will not contain an entry for ADI 2 with stack
+configuration CON, MEM.</p>
+
+<p>The back end is now faced with the problem of how to get
+from its current stack configuration, CON, MEM, which is not
+listed, to one that is listed. The table will normally
+contain rules (which we call &quot;coercions&quot;) for
+converting between CON, REG, MEM, and similar tokens.
+Therefore the back end attempts to &quot;coerce&quot; the
+stack into a configuration that <i>is</i> present in the
+table. A typical coercion rule might tell how to convert a
+MEM into a REG, namely by performing the actions of
+allocating a register and emitting code to move the memory
+word to that register. Having transformed the compile-time
+stack into a configuration allowed for ADI 2, the rule can
+be carried out. A typical rule for ADI 2 might have stack
+configuration REG, MEM and would emit code to add the MEM to
+the REG, leaving the stack with a single REG token instead
+of the REG and MEM tokens present before the ADI 2.</p>
+
+<p>In general, there will be more than one possible
+coercion path. Assuming reasonable coercion rules for our
+example, we might be able to convert CON MEM into CON REG by
+loading the variable I into a register. Alternatively, we
+could coerce CON to REG by loading the constant into a
+register. The first coercion path does the add by first
+loading I into a register and then adding 7 to it. The
+second path first loads 7 into a register and then adds I to
+it. On machines with a fast LOAD IMMEDIATE instruction for
+small constants but no fast ADD IMMEDIATE, or vice versa,
+one code sequence will be preferable to the other.</p>
+
+<p>In fact, we actually have more choices than suggested
+above. In both coercion paths a register must be allocated.
+On many machines, not every register can be used in every
+operation, so the choice may be important. On some machines,
+for example, the operand of a multiply must be in an odd
+register. To summarize, from any state (i.e., token and
+stack configuration), a variety of choices can be made,
+leading to a variety of different target code sequences.</p>
+
+<p>To decide which of the various code sequences to emit,
+the back end must have some information about the time and
+memory cost of each one. To provide this information, each
+rule in the driving table, including coercions, specifies
+both the time and memory cost of the code emitted when the
+rule is applied. The back end can then simply try each of
+the legal possibilities (including all the possible register
+allocations) to find the cheapest one.</p>
+
+<p>This situation is similar to that found in a chess or
+other game-playing program, in which from any state a finite
+number of moves can be made. Just as in a chess program, the
+back end can look at all the &quot;moves&quot; that can be
+made from each state reachable from the original state, and
+thus find the sequence that gives the minimum cost to a
+depth of one. More generally, the back end can evaluate all
+paths corresponding to accepting the next <i>N</i> input
+tokens, find the cheapest one, and then make the first move
+along that path, precisely the way a chess program
+would.</p>
+
+<p>Since the back end is analogous to both a parser and a
+chess playing program, some clarifying remarks may be
+helpful. First, chess programs and the back end must do some
+look ahead, whereas the parser for a well-designed grammar
+can usually suffice with one input token because grammars
+are supposed to be unambiguous. In contrast, many legal
+mappings from a sequence of EM instructions to target code
+may exist. Second, like a parser but unlike a chess program,
+the back end has perfect information -- it does not have to
+contend with an unpredictable opponent&rsquo;s moves. Third,
+chess programs normally make a static evaluation of the
+board and label the <i>nodes</i> of the tree with the
+resulting scores. The back end, in contrast, associates
+costs with <i>arcs</i> (moves) rather than nodes (states).
+However, the difference is not essential, since it could
+also label each node with the cumulative cost from the root
+to that node.</p>
+
+<p>As mentioned above, the cost field in the table contains
+<i>both</i> the time and memory costs for the code emitted.
+It should be clear that the back end could use either one or
+some linear combination of them as the scoring function for
+evaluating moves. A user can instruct the compiler to
+optimize for time or for memory or for, say, 0.3 x time +
+0.7 x memory. Thus the same compiler can provide a wide
+range of performance options to the user. The writer of the
+back end table can take advantage of this flexibility by
+providing several code sequences with different tradeoffs
+for each EM instruction (e.g., in line code vs. call to a
+run time routine).</p>
+
+<p>In addition to the time-space tradeoffs, by specifying
+the depth of search parameter, <i>N</i>, the user can
+effectively also tradeoff compile time vs. object code
+quality, for whatever code metric has been chosen. In
+summary, by combining the properties of a parser and a game
+playing program, it is possible to make a code generator
+that is table driven, highly flexible, and has the ability
+to produce good code from a stack machine intermediate
+code.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Target Machine Optimizer"></a>
+<h2>The Target Machine Optimizer</h2>
+
+<p>In the model of Fig 2., the peephole optimizer comes
+before the global optimizer. It may happen that the code
+produced by the global optimizer can also be improved by
+another round of peephole optimization. Conceivably, the
+system could have been designed to iterate peephole and
+global optimizations until no more of either could be
+performed.</p>
+
+<p>However, both of these optimizations are done on the
+machine independent EM code. Neither is able to take
+advantage of the peculiarities and idiosyncracies with which
+most target machines are well endowed. It is the function of
+the final optimizer to do any (peephole) optimizations that
+still remain.</p>
+
+<p>The algorithm used here is the same as in the EM
+peephole optimizer. In fact, if it were not for the
+differences between EM syntax, which is very restricted, and
+target assembly language syntax, which is less so, precisely
+the same program could be used for both. Nevertheless, the
+same ideas apply concerning patterns and replacements, so
+our discussion of this optimizer will be restricted to one
+example.</p>
+
+<p>To see what the target optimizer might do, consider the
+PDP-11 instruction sequence sub #2,r0; mov (r0),x. First 2
+is subtracted from register 0, then the word pointed to by
+it is moved to x. The PDP-11 happens to have an addressing
+mode to perform this sequence in one instruction: mov
+-(r0),x. Although it is conceivable that this instruction
+could be included in the back end driving table for the
+PDP-11, it is awkward to do so because it can occur in so
+many contexts. It is much easier to catch things like this
+in a separate program.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Universal Assembler/Linker"></a>
+<h2>The Universal Assembler/Linker</h2>
+
+<p>Although assembly languages for different machines may
+appear very different at first glance, they have a
+surprisingly large intersection. We have been able to
+construct an assembler/linker that is almost entirely
+independent of the assembly language being processed. To
+tailor the program to a specific assembly language, it is
+necessary to supply a table giving the list of instructions,
+the bit patterns required for each one, and the language
+syntax. The machine independent part of the assembler/linker
+is then compiled with the table to produce an assembler and
+linker for a particular target machine. Experience has shown
+that writing the necessary table for a new machine can be
+done in less than a week.</p>
+
+<p>To enforce a modicum of uniformity, we have chosen to
+use a common set of pseudoinstructions for all target
+machines. They are used to initialize memory, allocate
+uninitialized memory, determine the current segment, and
+similar functions found in most assemblers.</p>
+
+<p>The assembler is also a linker. After assembling a
+program, it checks to see if there are any unsatisfied
+external references. If so, it begins reading the libraries
+to find the necessary routines, including them in the object
+file as it finds them. This approach requires libraries to
+be maintained in assembly language form, but eliminates the
+need for inventing a language to express relocatable object
+programs in a machine independent way. It also simplifies
+the assembler, since producing absolute object code is
+easier than producing relocatable object code. Finally,
+although assembly language libraries may be somewhat larger
+than relocatable object module libraries, the loss in speed
+due to having more input may be more than compensated for by
+not having to pass an intermediate file between the
+assembler and linker.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="The Utility Package"></a>
+<h2>The Utility Package</h2>
+
+<p>The utility package is a collection of programs designed
+to aid the implementers of new front ends or new back ends.
+The most useful ones are the test programs. For example, one
+test set, EMTEST, systematically checks out a back end by
+executing an ever larger subset of the EM instructions. It
+starts out by testing LOC, LOL and a few of the other
+essential instructions. If these appear to work, it then
+tries out new instructions one at a time, adding them to the
+set of instructions &quot;known&quot; to work as they pass
+the tests.</p>
+
+<p>Each instruction is tested with a variety of operands
+chosen from values where problems can be expected. For
+example, on target machines which have 16-bit index
+registers but only allow 8-bit displacements, a
+fundamentally different algorithm may be needed for
+accessing the first few bytes of local variables and those
+with offsets of thousands. The test programs have been
+carefully designed to thoroughly test all relevant
+cases.</p>
+
+<p>In addition to EMTEST, test programs in Pascal, C, and
+other languages are also available. A typical test is:</p>
+
+<p>i := 9; <b>if</b> i + 250 &lt;&gt; 259 <b>then</b>
+error(16);</p>
+
+<p>Like EMTEST, the other test programs systematically
+exercise all features of the language being tested, and do
+so in a way that makes it possible to pinpoint errors
+precisely. While it has been said that testing can only
+demonstrate the presence of errors and not their absence,
+our experience is that the test programs have been
+invaluable in debugging new parts of the system quickly.</p>
+
+<p>Other utilities include programs to convert the highly
+compact EM code produced by front ends to ASCII and vice
+versa, programs to build various internal tables from human
+writable input formats, a variety of libraries written in or
+compiled to EM to make them portable, an EM assembler, and
+EM interpreters for various machines.</p>
+
+<p>Interpreting the EM code instead of translating it to
+target machine language is useful for several reasons.
+First, the interpreters provide extensive run time
+diagnostics including an option to list the original source
+program (in Pascal, C, etc.) with the execution frequency or
+execution time for each source line printed in the left
+margin. Second, since an EM program is typically about
+one-third the size of a compiled program, large programs can
+be executed on small machines. Third, running the EM code
+directly makes it easier to pinpoint errors in the EM output
+of front ends still being debugged.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="Summary and Conclusions"></a>
+<h2>Summary and Conclusions</h2>
+
+<p>The Amsterdam Compiler Kit is a tool kit for building
+portable (cross) compilers and interpreters. The main pieces
+of the kit are the front ends, which convert source programs
+to EM code, optimizers, which improve the EM code, and back
+ends, which convert the EM code to target assembly language.
+The kit is highly modular, so writing one front end (and its
+associated runtime routines) is sufficient to implement a
+new language on a dozen or more machines, and writing one
+back end table and one universal assembler/linker table is
+all that is needed to bring up all the previously
+implemented languages on a new machine. In this manner, the
+contents, and hopefully the usefulness, of the toolkit will
+increase in time.</p>
+
+<p>We believe the principal lesson to be learned from our
+work is that the old UNCOL idea is basically a sound way to
+produce compilers, provided suitable restrictions are placed
+on the source languages and target machines. We also believe
+that although compilers produced by this technology may not
+be equal to the very best handcrafted compilers, in terms of
+object code quality, they are certainly competitive with
+many existing compilers. However, when one factors in the
+cost of producing the compiler, the possible slight loss in
+performance may be more than compensated for by the large
+decrease in production cost. As a consequence of our work
+and similar work by other researchers [1,3,4], we expect
+integrated compiler building kits to become increasingly
+popular in the near future.</p>
+
+<p>The toolkit is now available for various computers
+running the <small>UNIX</small> &reg; operating system. For
+information, contact the authors.</p>
+<a name="*."></a>
+<h2>*.</h2>
+<a name="References"></a>
+<h2>References</h2>
+
+<p><b>1.</b> Graham, S.L. Table-Driven Code Generation.
+<i>Computer 13</i>, 8 (August 1980), 25-34.</p>
+
+<p>A discussion of systematic ways to do code generation,
+in particular, the idea of having a table with templates
+that match parts of the parse tree and convert them into
+machine instructions.</p>
+
+<p><b>2.</b> Haddon, B.K., and Waite, W.M. Experience with
+the Universal Intermediate Language Janus. <i>Software
+Practice &amp; Experience 8</i>, 5 (Sept.-Oct. 1978),
+601-616.</p>
+
+<p>An intermediate language for use with ALGOL 68, Pascal,
+etc. is described. The paper discusses some problems
+encountered and how they were dealt with.</p>
+
+<p><b>3.</b> Johnson, S.C. A Portable Compiler: Theory and
+Practice. <i>Ann. ACM Symp. Prin. Prog. Lang.</i>, Jan.
+1978.</p>
+
+<p>A cogent discussion of the portable C compiler.
+Particularly interesting are the author&rsquo;s thoughts on
+the value of computer science theory.</p>
+
+<p><b>4.</b> Leverett, B.W., Cattell, R.G.G, Hobbs, S.O.,
+Newcomer, J.M., Reiner, A.H., Schatz, B.R., and Wulf, W.A.
+An Overview of the Production-Quality Compiler-Compiler
+Project. <i>Computer 13</i>, 8 (August 1980), 38-49.</p>
+
+<p>PQCC is a system for building compilers similar in
+concept but differing in details from the Amsterdam Compiler
+Kit. The paper describes the intermediate representation
+used and the code generation strategy.</p>
+
+<p><b>5.</b> Lowry, E.S., and Medlock, C.W. Object Code
+Optimization. <i>Commun. ACM 12</i>, (Jan. 1969), 13-22.</p>
+
+<p>A classic paper on global object code optimization. It
+covers data flow analysis, common subexpressions, code
+motion, register allocation and other techniques.</p>
+
+<p><b>6.</b> Nori, K.V., Ammann, U., Jensen, K., Nageli, H.
+The Pascal P Compiler Implementation Notes. Eidgen. Tech.
+Hochschule, Zurich, 1975.</p>
+
+<p>A description of the original P-code machine, used to
+transport the Pascal-P compiler to new computers.</p>
+
+<p><b>7.</b> Steel, T.B., Jr. UNCOL: the Myth and the Fact.
+in <i>Ann. Rev. Auto. Prog.</i> Goodman, R. (ed.), vol 2.,
+(1960), 325-344.</p>
+
+<p>An introduction to the UNCOL idea by its originator.</p>
+
+<p><b>8.</b> Steel, T.B., Jr. A First Version of UNCOL.
+<i>Proc. Western Joint Comp. Conf.</i>, (1961), 371-377.</p>
+
+<p>The first detailed proposal for an UNCOL. By current
+standards it is a primitive language, but it is interesting
+for its historical perspective.</p>
+
+<p><b>9.</b> Tanenbaum, A.S., van Staveren, H., and
+Stevenson, J.W. Using Peephole Optimization on Intermediate
+Code. <i>ACM Trans. Prog. Lang. and Sys. 3</i>, 1 (Jan.
+1982) pp. 21-36.</p>
+
+<p>A detailed description of a table-driven peephole
+optimizer. The driving table provides a list of patterns to
+match as well as the replacement text to use for each
+successful match.</p>
+
+<p><b>10.</b> Tanenbaum, A.S., Stevenson, J.W., Keizer,
+E.G., and van Staveren, H. Description of an Experimental
+Machine Architecture for use with Block Structured
+Languages. Informatica Rapport 81, Vrije Universiteit,
+Amsterdam, 1983.</p>
+
+<p>The defining document for EM.</p>
+
+<p><b>11.</b> Tanenbaum, A.S. Implications of Structured
+Programming for Machine Architecture. <i>Comm. ACM 21</i>, 3
+(March 1978), 237-246.</p>
+
+<p>The background and motivation for the design of EM. This
+early version emphasized the idea of interpreting the
+intermediate code (then called EM-1) rather than compiling
+it.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/toolkit.pdf b/doc/tack/toolkit.pdf
new file mode 100644 (file)
index 0000000..49e706c
Binary files /dev/null and b/doc/tack/toolkit.pdf differ
diff --git a/doc/tack/top.html b/doc/tack/top.html
new file mode 100644 (file)
index 0000000..e8d4c7e
--- /dev/null
@@ -0,0 +1,1210 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:18 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>The ACK Target Optimizer</title>
+</head>
+<body>
+
+<h1 align=center>The ACK Target Optimizer</h1>
+<a href="#1. Introduction">1. Introduction</a><br>
+<a href="#2. Global structure of the target optimizer">2. Global structure of the target optimizer</a><br>
+<a href="#2.1. Assumptions about the assembly code format">2.1. Assumptions about the assembly code format</a><br>
+<a href="#2.2. Informal description of the machine-dependent tables">2.2. Informal description of the machine-dependent tables</a><br>
+<a href="#2.3. Examples">2.3. Examples</a><br>
+<a href="#2.3.1. Vax examples">2.3.1. Vax examples</a><br>
+<a href="#2.3.2. PDP-11 examples">2.3.2. PDP-11 examples</a><br>
+<a href="#3. Implementation of the target optimizer">3. Implementation of the target optimizer</a><br>
+<a href="#3.1. The window mechanism">3.1. The window mechanism</a><br>
+<a href="#3.2. Pattern matching">3.2. Pattern matching</a><br>
+<a href="#3.3. Data structures">3.3. Data structures</a><br>
+<a href="#4. Implementation of the target optimizer generator">4. Implementation of the target optimizer generator</a><br>
+<a href="#5. References">5. References</a><br>
+<a href="#References">References</a><br>
+<a href="#Appendix A">Appendix A</a><br>
+
+<hr>
+
+<p align=center><i>ABSTRACT</i></p>
+
+<p align=center><i>H.E. Bal</i><br>
+Vrije Universiteit<br>
+Wiskundig Seminarium, Amsterdam</p>
+
+<p>The Target Optimizer is one of several optimizers that
+are part of the Amsterdam Compiler Kit. It operates directly
+on assembly code, rather than on a higher level intermediate
+code, as the Peephole Optimizer and Global Optimizer do.
+Consequently, the Target Optimizer can do optimizations that
+are highly machine-dependent.</p>
+
+<p>Each target machine has its own Target Optimizer. New
+optimizers are generated by the Target Optimizer Generator,
+which uses a machine-dependent table as input. This document
+contains full information on how to write such a table for a
+new machine. It also discusses the implementation of the
+Target Optimizer and its generator.</p>
+<a name="1. Introduction"></a>
+<h2>1. Introduction</h2>
+
+<p align=center><img src="grohtml-102411.png"></p>
+
+<p>This document describes the target optimizer component
+of the Amsterdam Compiler Kit (ACK) .[Tane81a, Tane83a,
+Tane83b] Optimization takes place in several parts of ACK
+compilers, most notably in the Peephole Optimizer[Tane82a]
+and the Global Optimizer,[Bal85b, Bal85a] which are both
+language- and machine-independent, and in the
+machine-specific code generators.[Tane84a] The target
+optimizer is the finishing touch in this sequence of
+optimizers. It can be used to capture those optimizations
+that are hard to express in the other parts of ACK. These
+optimizations will typically be very machine-specific.</p>
+
+<p>The target optimizer operates on the assembly code of
+some target machine. Hence there is one target optimizer per
+machine. However, just as for the ACK code generators and
+assemblers, a framework has been build that allows easy
+generation of target optimizers out of machine-independent
+parts and a machine-dependent description table (see figure
+1.). So the major part of the code of a target optimizer is
+shared among all target optimizers.</p>
+<pre>                                            |-------------------------|
+                                            | machine-independent     |
+                                            | code                    |
+                                            |                         |
+               |-----------------|          |-------------------------|
+     descrip-  |target optimizer |          | machine-dependent code  |
+      tion --&gt; |generator        | ----&gt;    | + tables                |
+     table     |                 |          |                         |
+               |-----------------|          |-------------------------|
+
+
+                                                   target optimizer
+
+
+         Figure 1: Generation of a target optimizer.
+
+
+</pre>
+
+<p>This document focusses on the description of the
+machine-dependent table. In chapter 2 we give an informal
+introduction to the optimization algorithm and to the
+definition of the table format. Chapters 3 and 4 discuss the
+implementation of the target optimizer and the target
+optimizer generator. Appendix A gives full information for
+writing a description table.</p>
+<a name="2. Global structure of the target optimizer"></a>
+<h2>2. Global structure of the target optimizer</h2>
+
+<p>The target optimizer is based on the well understood
+model of a <i>peephole optimizer</i>.[Aho78a] It contains a
+machine-dependent table of (pattern,replacement) pairs. Each
+pattern describes a sequence of one or more assembler
+instructions that can be replaced by zero or more
+equivalent, yet cheaper, instructions (the
+&rsquo;replacement&rsquo;). The optimizer maintains a
+<i>window</i> that moves over the input. At any moment, the
+window contains some contiguous part of the input. If the
+instructions in the current window match some pattern in the
+table, they are replaced by the corresponding replacement;
+else, the window moves one instruction to the right.</p>
+
+<p>In the remainder of this section we will give an
+informal description of the machine-dependent table. A more
+precise definition is given in appendix A. We will first
+discuss the restrictions put on the format of the assembly
+code.</p>
+<a name="2.1. Assumptions about the assembly code format"></a>
+<h2>2.1. Assumptions about the assembly code format</h2>
+
+<p>We assume that a line of assembly code begins with an
+instruction <i>mnemonic</i> (opcode), followed by zero or
+more <i>operands</i>. The mnemonic and the first operand
+must be separated by a special character (e.g. a space or a
+tab). Likewise, the operands must be separated by a special
+character (e.g. a comma). These separators need not be the
+same for all machines.</p>
+<a name="2.2. Informal description of the machine-dependent tables"></a>
+<h2>2.2. Informal description of the machine-dependent tables</h2>
+
+<p>The major part of the table consists of
+(pattern,replacement) pairs called <i>entries</i>.</p>
+
+<p>A pattern is a list of instruction descriptions. Each
+instruction description describes the instruction mnemonic
+and the operands.</p>
+
+<p>A mnemonic is described either by a string constant or
+by the keyword ANY. As all entities dealt with by the target
+optimizer are strings, string constants do not contain
+quotes. A string constant matches only itself. ANY matches
+every instruction mnemonic.</p>
+<pre>Examples of mnemonic descriptions:
+
+       add
+        sub.l
+        mulw3
+        ANY
+</pre>
+
+<p>An operand can also be described by a string
+constant.</p>
+<pre>Examples:
+
+      (sp)+
+       r5
+       -4(r6)
+
+</pre>
+
+<p>Alternatively, it can be described by means of a
+<i>variable name</i>. Variables have values which are
+strings. They have to be declared in the table before the
+patterns. Each such declaration defines the name of a
+variable and a <i>restriction</i> to which its value is
+subjected.</p>
+<pre>Example of variable declarations:
+
+     CONST       { VAL[0] == &rsquo;$&rsquo; };
+      REG         { VAL[0] == &rsquo;r&rsquo; &amp;&amp; VAL[1] &gt;= &rsquo;0&rsquo; &amp;&amp; VAL[1] &lt;= &rsquo;3&rsquo; &amp;&amp;
+                    VAL[2] == &rsquo;\0&rsquo; };
+      X           { TRUE };
+
+</pre>
+
+<p>The keyword VAL denotes the value of the variable, which
+is a null-terminated string. An operand description given
+via a variable name matches an actual operand if the actual
+operand obeys the associated restriction.</p>
+<pre>     CONST  matches   $1, $-5, $foo etc.
+     REG    matches   r0, r1, r2 and r3
+     X      matches   anything
+
+</pre>
+
+<p>The restriction (between curly braces) may be any legal
+&quot;C&quot;[Kern78a] expression. It may also contain calls
+to user-defined procedures. These procedures must be added
+to the table after the patterns.</p>
+<pre>Example:
+
+    FERMAT_NUMBER    { VAL[0] == &rsquo;$&rsquo; &amp;&amp; is_fermat_number(&amp;VAL[1]) };
+
+</pre>
+
+<p>An operand can also be described by a mixture of a
+string constant and a variable name. The most general form
+allowed is:</p>
+<pre>       string_constant1 variable_name string_constant2
+
+Example:
+
+      (REG)+  matches  (r0)+, (r1)+, (r2)+ and (r3)+
+
+</pre>
+
+<p>Any of the three components may be omitted, so the first
+two forms are just special cases of the general form. The
+name of a variable can not be used as a string constant. In
+the above context, it is impossible to define an operand
+that matches the string &quot;REG&quot;. This limitation is
+of little consequence, as the table writer is free to choose
+the names of variables. This approach, however, avoids the
+need for awkward escape sequences.</p>
+
+<p>A pattern consists of one or more instruction
+descriptions (separated by a colon) followed by an optional
+constraint. A pattern &quot;P1 : P2 : .. : Pn C&quot;
+matches the sequence of instructions &quot;I1 I2 .. In&quot;
+if:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p>for each i, 1 &lt;= i &lt;= n, Pi matches Ii, as
+described above;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p>multiple occurrences of the same variable name or of the
+keyword ANY stand for the same values throughout the
+pattern;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>(iii)</p>
+</td>
+<td width="4%"></td>
+<td width="86%">
+
+<p>the optional constraint C is satisfied, i.e. it
+evaluates to TRUE.</p>
+</td>
+</table>
+<pre>The pattern:
+
+     dec REG : move.b CONST,(REG)
+
+matches:
+
+     dec r0 : move.b $4,(r0)
+
+but not:
+
+     dec r0 : move.b $4,(r1)
+
+(as the variable REG matches two different strings).
+</pre>
+
+<p>If a pattern containing different registers must be
+described, extra names for a register should be declared,
+all sharing the same restriction.</p>
+<pre>Example:
+
+    REG1,REG2  { VAL[0] == &rsquo;r&rsquo; &amp;&amp;  .....  };
+
+    addl3 REG1,REG1,REG2 : subl2 REG2,REG1
+</pre>
+
+<p>The optional constraint is an auxiliary &quot;C&quot;
+expression (just like the parameter restrictions). The
+expression may refer to the variables and to ANY.</p>
+<pre>Example:
+
+   move REG1,REG2    { REG1[1] == REG2[1] + 1 }
+
+matches
+
+   move r1,r0
+    move r2,r1
+    move r3,r2
+</pre>
+
+<p>The replacement part of a (pattern,replacement) table
+entry has the same structure as a pattern, except that:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="88%">
+
+<p>it may not contain an additional constraint;</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="32%">
+
+<p>it may be empty.</p>
+</td>
+<td width="57%">
+</td>
+</table>
+
+<p>A replacement may also refer to the values of variables
+and ANY.</p>
+<a name="2.3. Examples"></a>
+<h2>2.3. Examples</h2>
+
+<p>This section contains some realistic examples for
+optimization on PDP-11 and Vax assembly code.</p>
+<a name="2.3.1. Vax examples"></a>
+<h2>2.3.1. Vax examples</h2>
+
+<p>Suppose the table contains the following
+declarations:</p>
+<pre>         X, LOG        { TRUE };
+         LAB           { VAL[0] == &rsquo;L&rsquo; };   /* e.g. L0017 */
+         A             { no_side_effects(VAL) };
+         NUM           { is_number(VAL) };
+
+</pre>
+
+<p>The procedure &quot;no_side_effects&quot; checks if its
+argument contains any side effects, i.e. auto increment or
+auto decrement. The procedure &quot;is_number&quot; checks
+if its argument contains only digits. These procedures must
+be supplied by the table-writer and must be included in the
+table.</p>
+<pre><i>entry:</i>  addl3 X,A,A    -&gt; addl2 X,A;
+
+</pre>
+
+<p>This entry changes a 3-operand instruction into a
+cheaper 2-operand instruction. An optimization like:</p>
+<pre>        addl3 r0,(r2)+,(r2)+   -&gt; addl2 r0,(r2)+
+
+</pre>
+
+<p>is illegal, as r2 should be incremented twice. Hence the
+second argument is required to be side-effect free.</p>
+<pre><i>entry:</i>  addw2 $-NUM,X  -&gt; subw2 $NUM,X;
+
+</pre>
+
+<p>An instruction like &quot;subw2 $5,r0&quot; is cheaper
+than &quot;addw2 $-5,r0&quot;, because constants in the
+range 0 to 63 are represented very efficiently on the
+Vax.</p>
+<pre><i>entry:</i>  bitw $NUM,A : jneq LAB
+                { is_poweroftwo(NUM,LOG) }  -&gt; jbs $LOG,A,LAB;
+
+</pre>
+
+<p>A &quot;bitw x,y&quot; sets the condition codes to the
+bitwise &quot;and&quot; of x and y. A &quot;jbs n,x,l&quot;
+branches to l if bit n of x is set. So, for example, the
+following transformation is possible:</p>
+<pre>      bitw $32,r0 : jneq L0017 -&gt;  jbs $5,r0,L0017
+
+</pre>
+
+<p>The user-defined procedure &quot;is_poweroftwo&quot;
+checks if its first argument is a power of 2 and, if so,
+sets its second argument to the logarithm of the first
+argument. (Both arguments are strings). Note that the
+variable LOG is not used in the pattern itself. It is
+assigned a (string) value by &quot;is_poweroftwo&quot; and
+is used in the replacement.</p>
+<a name="2.3.2. PDP-11 examples"></a>
+<h2>2.3.2. PDP-11 examples</h2>
+
+<p>Suppose we have the following declarations:</p>
+<pre>         X             { TRUE };
+         A             { no_side_effects(VAL) };
+         L1, L2        { VAL[0] == &rsquo;I&rsquo; };
+         REG           { VAL[0] == &rsquo;r&rsquo; &amp;&amp; VAL[1] &gt;= &rsquo;0&rsquo; &amp;&amp; VAL[1] &lt;= &rsquo;5&rsquo; &amp;&amp;
+                         VAL[2] == &rsquo;\0&rsquo; };
+
+</pre>
+
+<p>The implementation of &quot;no_side_effects&quot; may of
+course differ for the PDP-11 and the Vax.</p>
+<pre><i>entry:</i>  mov REG,A : ANY A,X  -&gt;  mov REG,A : ANY REG,X ;
+
+</pre>
+
+<p>This entry implements register subsumption. If A and REG
+hold the same value (which is true after &quot;mov
+REG,A&quot;) and A is used as source (first) operand, it is
+cheaper to use REG instead.</p>
+<pre><i>entry:</i>  jeq L1 : jbr L2 : labdef L1  -&gt;  jne L2 : labdef L1;
+
+</pre>
+
+<p>The &quot;jeq L1&quot; is a &quot;skip over an
+unconditional jump&quot;. &quot;labdef L1&quot; denotes the
+definition (i.e. defining occurrence) of label L1. As the
+target optimizer has to know how such a definition looks
+like, this must be expressed in the table (see Appendix
+A).</p>
+<pre><i>entry:</i>  add $01,X { carry_dead(REST) }  -&gt; inc X;
+
+</pre>
+
+<p>On the PDP-11, an add-one is not equivalent to an
+increment. The latter does not set the carry-bit of the
+condition codes, while the former does. So a look-ahead is
+needed to see if the rest of the input uses the carry-bit
+before changing the condition codes. A look-ahead of one
+instruction is provided by the target optimizer. This will
+normally be sufficient for compiler-generated code. The
+keyword REST contains the mnemonic of the first instruction
+of the rest of the input. If this instruction uses the
+carry-bit (e.g. an adc, subc, bhis) the transformation is
+not allowed.</p>
+<a name="3. Implementation of the target optimizer"></a>
+<h2>3. Implementation of the target optimizer</h2>
+
+<p>The target optimizer reads one input file of assembler
+instructions, processes it, and writes the optimized code to
+the output file. So it performs one pass over the input.</p>
+<a name="3.1. The window mechanism"></a>
+<h2>3.1. The window mechanism</h2>
+
+<p>The optimizer uses a <i>window</i> that moves over the
+input. It repeatedly tries to match the instructions in the
+window with the patterns in the table. If no match is
+possible, the window moves one instruction forwards (to the
+right). After a successful match the matched instructions
+are removed from the window and are replaced by the
+replacement part of the table entry. Furthermore, the window
+is moved a few instructions backwards, as it is possible
+that instructions that were rejected earlier now do match.
+For example, consider the following patterns:</p>
+<pre>     cmp $0, X           -&gt; tst X ;
+     mov REG,X : tst X   -&gt; move REG.X ;   /* redundant test */
+</pre>
+
+<p>If the input is:</p>
+<pre>     mov r0,foo : cmp $0,foo
+</pre>
+
+<p>then the first instruction is initially rejected.
+However, after the transformation</p>
+<pre>     cmp $0,foo   -&gt;  tst foo
+</pre>
+
+<p>the following optimization is possible:</p>
+<pre>     mov r0,foo : tst foo  -&gt;  mov r0,foo
+</pre>
+
+<p>The window is implemented as a <i>queue</i>. Matching
+takes place at the head of the queue. New instructions are
+added at the tail. If the window is moved forwards, the
+instruction at the head is not yet written to the output, as
+it may be needed later on. Instead it is added to a second
+queue, the <i>backup queue</i>. After a successful match,
+the entire backup queue is inserted at the front of the
+window queue, which effectively implements the shift
+backwards.</p>
+
+<p>Both queues have the length of the longest pattern in
+the table. If, as a result of a forward window move, the
+backup queue gets full, the instruction at its head is
+outputted and removed. Instructions are read from the input
+whenever the window queue contains fewer elements than the
+length of the longest pattern.</p>
+<a name="3.2. Pattern matching"></a>
+<h2>3.2. Pattern matching</h2>
+
+<p>Pattern matching is done in three steps:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p>find patterns in the table whose instruction mnemonics
+match the mnemonics of the instructions in the current
+window;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p>check if the operands of the pattern match the operands
+of the instructions in the current window;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>(iii)</p>
+</td>
+<td width="4%"></td>
+<td width="86%">
+
+<p>check if the optional constraint is satisfied.</p>
+</td>
+</table>
+
+<p>For step (i) hashing is used. The mnemonic of the first
+instruction of the window is used to determine a list of
+possible patterns. Patterns starting with ANY are always
+tried.</p>
+
+<p>Matching of operand descriptions against actual operands
+takes place as follows. The general form of an operand
+description is:</p>
+<pre>     string_constant1 variable_name string_constant2
+</pre>
+
+<p>The actual operand should begin with string_constant1
+and end on string_constant2. If so, these strings are
+stripped from it and the remaining string is matched against
+the variable. Matching a string against a variable is
+defined as follows:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>initially (before the entire pattern match) all
+variables are uninstantiated;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>matching a string against an uninstantiated variable
+succeeds if the restriction associated with the variable is
+satisfied. As a side effect, it causes the variable to be
+instantiated to the string;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3.</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>matching a string against an instantiated variable
+succeeds only if the variable was instantiated to the same
+string.</p>
+</td>
+</table>
+
+<p>Matching an actual mnemonic against the keyword ANY is
+defined likewise.</p>
+
+<p>The matching scheme implements the requirement that
+multiple occurrences of the same variable name or of the
+keyword ANY should stand for the same values throughout the
+entire pattern (see section 2.).</p>
+
+<p>Both the parameter restriction of 2. and the constraint
+of step (iii) are checked by executing the &quot;C&quot;
+expression.</p>
+<a name="3.3. Data structures"></a>
+<h2>3.3. Data structures</h2>
+
+<p>The most important data structure is the representation
+of the input instructions. For every instruction we use two
+representations:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="90%">
+
+<p>the textual representation, i.e. the exact code as it
+appeared in the input;</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>a structural representation, containing the opcode and
+the operands.</p>
+</td>
+</table>
+
+<p>The opcode of an instruction is determined as soon as it
+is read. If the line contains a label definition, the opcode
+is set to &quot;labdef&quot;, so a label definition is
+treated like a normal instruction.</p>
+
+<p>The operands of an instruction are not determined until
+they are needed, i.e. until step (i) of the pattern matching
+process has succeeded. For every instruction we keep track
+of a <i>state</i>. After the opcode has successfully been
+determined, the state is OPC_ONLY. Once the operands have
+been recognized, the state is set to DONE. If the opcode or
+operands can not be determined, or if the instruction cannot
+be optimized for any other reason (see Appendix A), the
+state is set to JUNK and any attempt to match it will
+fail.</p>
+
+<p>For each table entry we record the following
+information:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="8%"></td>
+<td width="86%">
+
+<p>the length of the pattern (i.e. the number of
+instruction descriptions)</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p>a description of the instructions of the pattern</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="10%">
+
+<p>(iii)</p>
+</td>
+<td width="4%"></td>
+<td width="58%">
+
+<p>the length of the replacement</p>
+</td>
+<td width="27%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(iv)</p>
+</td>
+<td width="6%"></td>
+<td width="86%">
+
+<p>a description of the instructions of the
+replacement.</p>
+</td>
+</table>
+
+<p>The description of an instruction consists of:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="20%">
+
+<p>the opcode</p>
+</td>
+<td width="69%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="90%">
+
+<p>for each operand, a description of the operand.</p>
+</td>
+</table>
+
+<p>The description of an operand of the form:</p>
+<pre>     string_constant1 variable_name string_constant2
+</pre>
+
+<p>contains:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="42%">
+
+<p>both string constants</p>
+</td>
+<td width="47%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="54%">
+
+<p>the number of the variable.</p>
+</td>
+<td width="35%">
+</td>
+</table>
+
+<p>Each declared variable is assigned a unique number. For
+every variable we maintain:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="6%">
+
+<p>(i)</p>
+</td>
+<td width="4%"></td>
+<td width="88%">
+
+<p>its state (instantiated or not instantiated)</p>
+</td>
+<td width="1%">
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="8%">
+
+<p>(ii)</p>
+</td>
+<td width="2%"></td>
+<td width="58%">
+
+<p>its current value (a string).</p>
+</td>
+<td width="31%">
+</td>
+</table>
+
+<p>The restrictions on variables and the constraints are
+stored in a switch-statement, indexed by variable number and
+entry number respectively.</p>
+<a name="4. Implementation of the target optimizer generator"></a>
+<h2>4. Implementation of the target optimizer generator</h2>
+
+<p>The target optimizer generator (<i>topgen</i>) reads a
+target machine description table and produces two files:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>gen.h:</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>contains macro definitions for machine parameters that
+were changed in the parameter section of the table (see
+appendix A) and for some attributes derived from the table
+(longest pattern, number of patterns, number of
+variables).</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="12%">
+
+<p>gen.c:</p>
+</td>
+<td width="6%"></td>
+<td width="82%">
+
+<p>contains the entry description tables, code for checking
+the parameter restrictions and constraints (switch
+statements) and the user-defined procedures.</p>
+</td>
+</table>
+
+<p>These two files are compiled together with some
+machine-independent files to produce a target optimizer.</p>
+
+<p>Topgen is implemented using the LL(1) parser generator
+system LLgen ,[Jaco85a] a powerful tool of the Amsterdam
+Compiler Kit. This system provides a flexible way of
+describing the syntax of the tables. The syntactical
+description of the table format included in Appendix A was
+derived from the LLgen syntax rules.</p>
+
+<p>The parser uses a simple, hand-written, lexical analyzer
+(scanner). The scanner returns a single character in most
+cases. The recognition of identifiers is left to the parser,
+as this eases the analysis of operand descriptions. Comments
+are removed from the input by the scanner, but white space
+is passed to the parser, as it is meaningful in some
+contexts (it separates the opcode description from the
+description of the first operand).</p>
+
+<p>Topgen maintains two symbol tables, one for variable
+names and one for tunable parameters. The symbol tables are
+organized as binary trees.</p>
+<a name="5. References"></a>
+<h2>5. References</h2>
+<a name="References"></a>
+<h2>References</h2>
+
+<p>Aho78a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.V. Aho and J.D. Ullman, <i>Principles of compiler
+design,</i> Addison-Wesley, Reading, Massachusetts
+(1978).</p>
+</td>
+</table>
+
+<p>Bal85a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>H.E. Bal, &ldquo;The Design and Implementation of the EM
+Global Optimizer,&rdquo; Rapport IR-99, Vrije Universiteit,
+Amsterdam (March 1985).</p>
+</td>
+</table>
+
+<p>Bal85b.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>H.E. Bal and A.S. Tanenbaum, &ldquo;Language- and
+Machine-independant Global Optimization on Intermediate
+Code,&rdquo; Rapport IR-98, Vrije Universiteit, Amsterdam
+(March 1985).</p>
+</td>
+</table>
+
+<p>Jaco85a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>C.J.H. Jacobs, &ldquo;Some Topics in Parser
+Generation,&rdquo; Rapport IR-105, Vrije Universiteit,
+Amsterdam (October 1985).</p>
+</td>
+</table>
+
+<p>Kern78a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>B.W. Kernighan and D.M. Ritchie, <i>The C Programming
+Language,</i> Prentice-Hall, Inc, Englewood Cliffs,NJ
+(1978).</p>
+</td>
+</table>
+
+<p>Tane84a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, E.G. Keizer, J.M. van Staveren, and J.W.
+Stevenson, &ldquo;Amsterdam Compiler Kit
+documentation,&rdquo; Rapport nr IR-90, Vrije Universiteit,
+Amsterdam (June 1984).</p>
+</td>
+</table>
+
+<p>Tane81a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, J.M. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;A Practical Toolkit for Making Portable
+Compilers,&rdquo; Rapport nr IR-74, Vrije Universiteit,
+Amsterdam (October 1981).</p>
+</td>
+</table>
+
+<p>Tane83a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, J.M. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;A Practical Toolkit for Making Portable
+Compilers,&rdquo; <i>CACM,</i> 26, 9, pp. 654-660 (September
+1983).</p>
+</td>
+</table>
+
+<p>Tane83b.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, J.M. van Staveren, E.G. Keizer, and J.W.
+Stevenson, &ldquo;A Unix Toolkit for Making Portable
+Compilers,&rdquo; <i>Proceedings USENIX conf.,</i> 26, pp.
+255-261, Toronto, Canada (July 1983).</p>
+</td>
+</table>
+
+<p>Tane82a.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>A.S. Tanenbaum, J.M. van Staveren, and J.W. Stevenson,
+&ldquo;Using Peephole Optimization on Intermediate
+Code,&rdquo; <i>TOPLAS,</i> 4, 1, pp. 21-36 (January
+1982).</p>
+</td>
+</table>
+<a name="Appendix A"></a>
+<h2>Appendix A</h2>
+
+<p>In this appendix we present a complete definition of the
+target optimizer description table format. This appendix is
+intended for table-writers. We use syntax rules for the
+description of the table format. The following notation is
+used:</p>
+
+<p align=center><img src="grohtml-102412.png"></p>
+
+<p>Terminals are given in quotes, as in
+&rsquo;;&rsquo;.</p>
+
+<p>The table may contain white space and comment at all
+reasonable places. Comments are as in &quot;C&quot;, so they
+begin with /* and end on */. Identifiers are sequences of
+letters, digits and the underscore (&rsquo;_&rsquo;),
+beginning with a letter.</p>
+<pre>     table   -&gt;   {parameter_line} &rsquo;%%;&rsquo; {variable_declaration} &rsquo;%%;&rsquo;
+                  {entry} &rsquo;%%;&rsquo; user_routines.
+</pre>
+
+<p>A table consists of four sections, containing
+machine-dependent constants, variable declarations, pattern
+rules and user-supplied subroutines.</p>
+<pre>     parameter_line -&gt;  identifier value &rsquo;;&rsquo; .
+</pre>
+
+<p>A parameter line defines some attributes of the target
+machines assembly code. For unspecified parameters default
+values apply. The names of the parameters and the
+corresponding defaults are shown in table 1.</p>
+
+<p align=center><img src="grohtml-102413.png"></p>
+
+<p align=center>table 1: parameter names and defaults</p>
+
+<p>The OPC_TERMINATOR is the character that separates the
+instruction mnemonic from the first operand (if any). The
+OP_SEPARATOR separates adjacent operands. A LABEL_STARTER is
+the first character of an instruction label. (Instruction
+labels are assumed to start with the same character). The
+LABEL_TERMINATOR is the last character of a label
+definition. It is assumed that this character is not used in
+an applied occurrence of the label identifier. For example,
+the defining occurrence may be &quot;I0017:&quot; and the
+applied occurrence may be &quot;I0017&quot; as in &quot;jmp
+I0017&quot;. MAXOP defines the maximum number of operands an
+instruction can have. MAXOPLEN is the maximum length (in
+characters) of an operand. MAX_OPC_LEN is the maximum length
+of an instruction opcode. MAXVARLEN is the maximum length of
+a declared string variable. As variables may be set by user
+routines (see &quot;bitw&quot; example for the Vax) the
+table-writer must have access to this length and must be
+able to change it. MAXLINELEN denotes the maximum length of
+a line of assembly code. PAREN_OPEN and PAREN_CLOSE must be
+used when the operand separator can also occur within
+operands, between parentheses of some kind. In this case,
+PAREN_OPEN must be set to a string containing the opening
+parentheses, and PAREN_CLOSE must be set to a string
+containing the closing parentheses.</p>
+
+<p>If a line of assembly code violates any of the
+assumptions or exceeds some limit, the line is not
+optimized. Optimization does, however, proceed with the rest
+of the input.</p>
+<pre>     variable_declaration  -&gt; identifier {&rsquo;,&rsquo; identifier} restriction &rsquo;;&rsquo; .
+
+
+     restriction           -&gt;  &rsquo;{&rsquo; anything &rsquo;}&rsquo; .
+</pre>
+
+<p>A variable declaration declares one or more string
+variables that may be used in the patterns and in the
+replacements. If a variable is used as part of an operand
+description in a pattern, the entire pattern can only match
+if the restriction evaluates to TRUE. If the pattern does
+match, the variable is assigned the matching part of the
+actual operand. Variables that are not used in a pattern are
+initialized to null-strings and may be assigned a value in
+the constraint-part of the pattern.</p>
+
+<p>The restriction must be a legal &quot;C&quot;
+expression. It may not contain a closing bracket
+(&rsquo;}&rsquo;). Inside the expression, the name VAL
+stands for the part of the actual (matching) operand. The
+expression may contain calls to procedures that are defined
+in the user-routines section.</p>
+<pre>     entry             -&gt;  pattern &rsquo;-&gt;&rsquo; replacement &rsquo;;&rsquo; .
+
+
+     pattern           -&gt;  instruction_descr
+                     { &rsquo;:&rsquo; instruction_descr }
+                     constraint .
+
+
+     replacement       -&gt;  [ instruction_descr { &rsquo;:&rsquo; instruction_descr } ] .
+
+
+     instruction_descr -&gt; opcode
+                    white
+                    [ operand_descr { &rsquo;,&rsquo; operand_descr } ] .
+
+
+     constraint        -&gt; &rsquo;{&rsquo; anything &rsquo;}&rsquo; .
+
+
+     operand_descr     -&gt; [ string_constant ]
+                    [ variable_name ]
+                    [ string_constant ] .
+
+
+     variable_name     -&gt; identifier .
+
+
+     opcode            -&gt; anything .
+</pre>
+
+<p>The symbol &rsquo;white&rsquo; stands for white space
+(space or tab). An opcode can be any string not containing
+the special symbols &rsquo;;&rsquo;, &rsquo;{&rsquo;,
+&rsquo;}&rsquo;, &rsquo;:&rsquo;, &rsquo;,&rsquo;,
+&rsquo;-&gt;&rsquo; or white space. To be recognized, it
+must begin with a letter. The opcode should either be a
+mnemonic of a target machine instruction or it should be one
+of the keywords ANY and labdef. ANY matches any actual
+opcode. labdef matches only label definitions.</p>
+
+<p>If an operand description contains an identifier (as
+defined earlier), it is checked if the identifier is the
+name of a declared variable. This effects the semantics of
+the matching rules for the operand, as described in section
+2. An operand may contain at most one such variable
+name.</p>
+
+<p>The constraint must be a legal &quot;C&quot; expression,
+just as the operand restriction. It may call user-defined
+procedures and use or change the value of declared
+variables. It may also use the string variable REST, which
+contains the mnemonic of the first instruction of the rest
+of the input. (REST is a null-string if this mnemonic can
+not be determined).</p>
+<pre>     user_routines -&gt; anything .
+</pre>
+
+<p>The remainder of the table consists of user-defined
+subroutines.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/top.pdf b/doc/tack/top.pdf
new file mode 100644 (file)
index 0000000..27b6537
Binary files /dev/null and b/doc/tack/top.pdf differ
diff --git a/doc/tack/v7bugs.html b/doc/tack/v7bugs.html
new file mode 100644 (file)
index 0000000..59ff704
--- /dev/null
@@ -0,0 +1,2025 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:05 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title></title>
+</head>
+<body>
+
+<hr>
+
+<p align=center>UNIX version 7 bugs</p>
+
+<p>This document describes the UNIX version 7 errors fixed
+at the Vrije Universiteit, Amsterdam. Several of these are
+discovered at the VU. Others are quoted from a list of bugs
+distributed by BellLabs.</p>
+
+<p>For each error the differences between the original and
+modified source files are given, as well as a test
+program.</p>
+
+<p>ERROR 1: C optimizer bug for unsigned comparison</p>
+
+<p>The following C program caused an IOT trap, while it
+should not (compile with &rsquo;cc -O prog.c&rsquo;):</p>
+<!-- TABS -->
+
+<p>unsigned</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>i = 0;</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>main() {</p></td>
+</table>
+<!-- TABS -->
+
+<p>register j;</p>
+
+<p>j = -1;<br>
+if (i &gt; 40000)</p>
+<td width="-148%"></td>
+<td width="249%">
+
+<p>abort();</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>}</p>
+<!-- INDENTATION -->
+<p>BellLabs suggests to make the following patch in
+c21.c:</p>
+<!-- INDENTATION -->
+<pre>     /* modified /usr/src/cmd/c/c21.c */
+
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<p>189</p>
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if (r==0) {<br>
+190</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* next 2 lines replaced as indicated by<br>
+191</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* Bell Labs bug distribution ( v7optbug )<br>
+192</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;back-&gt;back-&gt;forw = p-&gt;forw;<br>
+193</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;forw-&gt;back = p-&gt;back-&gt;back;<br>
+194</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>End of lines changed */<br>
+195</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if (p-&gt;forw-&gt;op==CBR<br>
+196</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>|| p-&gt;forw-&gt;op==SXT<br>
+197</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>|| p-&gt;forw-&gt;op==CFCC) {<br>
+198</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;back-&gt;forw = p-&gt;forw;<br>
+199</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;forw-&gt;back = p-&gt;back;<br>
+200</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>} else {<br>
+201</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;back-&gt;back-&gt;forw = p-&gt;forw;<br>
+202</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;forw-&gt;back = p-&gt;back-&gt;back;<br>
+203</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}<br>
+204</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* End of new lines */<br>
+205</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>decref(p-&gt;ref);<br>
+206</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p = p-&gt;back-&gt;back;<br>
+207</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>nchange++;<br>
+208</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>} else if (r&gt;0) {</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>Use the previous program to test before and after the
+modification.</p></td>
+</table>
+
+<p>ERROR 2: The loader fails for large data or text
+portions</p>
+
+<p>The loader &rsquo;ld&rsquo; produces a &quot;local
+symbol botch&quot; error for the following C program.</p>
+<!-- TABS -->
+
+<p>int</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>big1[10000] = {</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>1</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>};</p></td>
+</table>
+<!-- TABS -->
+
+<p>int</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>big2[10000] = {</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>2</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>};</p>
+<!-- INDENTATION -->
+<p>main() {</p></td>
+</table>
+<!-- TABS -->
+
+<p>printf(&quot;loader is fine\n&quot;);</p>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>}</p>
+<!-- INDENTATION -->
+<p>We have made the following fix:</p>
+<!-- INDENTATION -->
+<pre>     /* original /usr/src/cmd/ld.c */
+
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<p>113</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>struct {<br>
+114</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>fmagic;<br>
+115</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>tsize;<br>
+116</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>dsize;<br>
+117</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>bsize;<br>
+118</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>ssize;<br>
+119</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>entry;<br>
+120</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>pad;<br>
+121</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>relflg;<br>
+122</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>} filhdr;</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>/* modified /usr/src/cmd/ld.c */</p>
+</td>
+</table>
+<!-- TABS -->
+
+<p>113</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+114</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* The original Version 7 loader had problems loading
+large<br>
+115</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* text or data portions.<br>
+116</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* Why not include &lt;a.out.h&gt; ???<br>
+117</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* then they would be declared unsigned<br>
+118</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/<br>
+119</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>struct {<br>
+120</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>int</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>fmagic;<br>
+121</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>tsize;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+122</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>dsize;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+123</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>bsize;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+124</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>ssize;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+125</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>entry;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+126</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>pad;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+127</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>relflg;</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* not int !!! */<br>
+128</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>} filhdr;</p>
+</td>
+</table>
+
+<p>ERROR 3: Floating point registers</p>
+
+<p>When a program is swapped to disk if it needs more
+memory, then the floating point registers were not saved, so
+that it may have different registers when it is restarted. A
+small assembly program demonstrates this for the status
+register. If the error is not fixed, then the program
+generates an IOT error. A &quot;memory fault&quot; is
+generated if all is fine.</p>
+<!-- TABS -->
+
+<p>start:</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>ldfps</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>$7400<br>
+1:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>stfps</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r0</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>mov</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r0,-(sp)</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>cmp</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r0,$7400</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>beq</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>1b</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>4</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>Some digging into the kernel is required to fix it. The
+following patch will do:</p>
+<!-- INDENTATION -->
+<pre>     /* original /usr/sys/sys/slp.c */
+
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<p>563</p>
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>a2 = malloc(coremap, newsize);<br>
+564</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if(a2 == NULL) {<br>
+565</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>xswap(p, 1, n);<br>
+566</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;p_flag |= SSWAP;<br>
+567</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>qswtch();<br>
+568</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* no return */<br>
+569</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>/* modified /usr/sys/sys/slp.c */</p>
+</td>
+</table>
+<!-- TABS -->
+
+<p>590</p>
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>a2 = malloc(coremap, newsize);<br>
+591</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if(a2 == NULL) {<br>
+592</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>#ifdef FPBUG<br>
+593</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+594</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* copy floating point register and status,<br>
+595</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* but only if you must switch processes<br>
+596</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/<br>
+597</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if(u.u_fpsaved == 0) {<br>
+598</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>savfp(&amp;u.u_fps);<br>
+599</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>u.u_fpsaved = 1;<br>
+600</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}<br>
+601</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>#endif<br>
+602</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>xswap(p, 1, n);<br>
+603</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>p-&gt;p_flag |= SSWAP;<br>
+604</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>qswtch();<br>
+605</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* no return */<br>
+606</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}</p>
+</td>
+</table>
+
+<p>ERROR 4: Floating point registers.</p>
+
+<p>A similar problem arises when a process forks. The child
+will have random floating point registers as is demonstrated
+by the following assembly language program. The child
+process will die by an IOT trap and the father prints the
+message &quot;child failed&quot;.</p>
+<!-- TABS -->
+
+<p>exit</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>= 1.<br>
+fork</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>= 2.<br>
+write</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>= 4.<br>
+wait</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>= 7.</p>
+
+<p>start:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>ldfps</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>$7400</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sys</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>fork</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>br</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>child</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sys</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>wait</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>tst</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r1</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>bne</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>bad</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>stfps</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r2</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>cmp</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r2,$7400</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>beq</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>start</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>4<br>
+child:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>stfps</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r2</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>cmp</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r2,$7400</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>beq</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>ex</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>4<br>
+bad:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>clr</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r0</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sys</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>write;mess;13.<br>
+ex:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>clr</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>r0</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sys</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>exit</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>.data<br>
+mess:</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>&lt;child failed\n&gt;</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>The same file slp.c should be patched as follows:</p>
+<!-- INDENTATION -->
+<pre>     /* original /usr/sys/sys/slp.c */
+
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<p>499</p>
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+500</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* When the resume is executed for the new process,<br>
+501</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* here&rsquo;s where it will resume.<br>
+502</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/<br>
+503</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if (save(u.u_ssav)) {<br>
+504</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sureg();<br>
+505</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>return(1);<br>
+506</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}<br>
+507</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>a2 = malloc(coremap, n);<br>
+508</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+509</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* If there is not enough core for the<br>
+510</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* new process, swap out the current process to generate
+the<br>
+511</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* copy.<br>
+512</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/</p>
+</td>
+</table>
+
+<p>/* modified /usr/sys/sys/slp.c */</p>
+<!-- TABS -->
+
+<p>519</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+520</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* When the resume is executed for the new process,<br>
+521</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* here&rsquo;s where it will resume.<br>
+522</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/<br>
+523</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if (save(u.u_ssav)) {<br>
+524</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>sureg();<br>
+525</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>return(1);<br>
+526</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}<br>
+527 #ifdef FPBUG<br>
+528</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/* copy the floating point registers and status to child
+*/<br>
+529</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>if(u.u_fpsaved == 0) {<br>
+530</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>savfp(&amp;u.u_fps);<br>
+531</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>u.u_fpsaved = 1;<br>
+532</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>}<br>
+533 #endif<br>
+534</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>a2 = malloc(coremap, n);<br>
+535</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>/*<br>
+536</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* If there is not enough core for the<br>
+537</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* new process, swap out the current process to generate
+the<br>
+538</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>* copy.<br>
+539</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>*/</p>
+</td>
+</table>
+
+<p>ERROR 5: /usr/src/libc/v6/stat.c</p>
+
+<p>Some system calls are changed from version 6 to version
+7. A library of system call entries, that make a version 6
+UNIX look like a version 7 system, is provided to run some
+useful version 7 utilities, like &rsquo;tar&rsquo;, on
+UNIX-6. The entry for &rsquo;stat&rsquo; contained two bugs:
+the 24-bit file size was incorrectly converted to 32 bits
+(sign extension of bit 15) and the uid/gid fields suffered
+from sign extension.</p>
+
+<p>Transferring files from version 6 to version 7 using
+&rsquo;tar&rsquo; will fail for all files for which</p>
+<!-- TABS -->
+<td width="-49%"></td>
+<td width="149%">
+
+<p>( (size &amp; 0100000) != 0 )</p>
+</td>
+</table>
+
+<p>These two errors are fixed if stat.c is modified as
+follows:</p>
+<!-- INDENTATION -->
+<td width="-49%"></td>
+<td width="149%">
+<p>/* original /usr/src/libc/v6/stat.c */</p>
+</td>
+</table>
+<!-- TABS -->
+
+<p>11</p>
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>char os_size0;<br>
+12</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>short os_size1;<br>
+13</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>short os_addr[8];</p>
+
+<p>49</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_nlink = osbuf.os_nlinks;<br>
+50</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_uid = osbuf.os_uid;<br>
+51</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_gid = osbuf.os_gid;<br>
+52</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_rdev = 0;</p>
+</td>
+</table>
+
+<p>/* modified /usr/src/libc/v6/stat.c */</p>
+<!-- TABS -->
+
+<p>11</p>
+<td width="-99%"></td>
+<td width="199%">
+
+<p>char os_size0;<br>
+12</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>unsigned os_size1;<br>
+13</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>short os_addr[8];</p>
+
+<p>49</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_nlink = osbuf.os_nlinks;<br>
+50</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_uid = osbuf.os_uid &amp; 0377;<br>
+51</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_gid = osbuf.os_gid &amp; 0377;<br>
+52</p>
+</td>
+<tr valign="top" align="left">
+<td width="-99%"></td>
+<td width="199%">
+
+<p>buf-&gt;st_rdev = 0;</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/v7bugs.pdf b/doc/tack/v7bugs.pdf
new file mode 100644 (file)
index 0000000..3ff6f73
Binary files /dev/null and b/doc/tack/v7bugs.pdf differ
diff --git a/doc/tack/val.html b/doc/tack/val.html
new file mode 100644 (file)
index 0000000..f7f666b
--- /dev/null
@@ -0,0 +1,2352 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:13 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title></title>
+</head>
+<body>
+
+<hr>
+
+<p align=center><b>Pascal Validation Suite Report</b></p>
+
+<p><b>Pascal processor identification</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The ACK-Pascal compiler produces code for an EM machine
+as defined in [1]. It is up to the implementor of the EM
+machine whether errors like integer overflow, undefined
+operand and range bound error are recognized or not.
+Therefore it depends on the EM machine implementation
+whether these errors are recognized in Pascal programs or
+not. The validation suite results of all known
+implementations are given.</p>
+<!-- INDENTATION -->
+<p>There does not (yet) exist a hardware EM machine.
+Therefore, EM programs must be interpreted, or translated
+into instructions for a target machine. The following
+implementations currently exist:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: an interpreter running on a PDP-11
+(using UNIX). The normal mode of operation for this
+interpreter is to check for undefined integers, overflow,
+range errors etc.</p>
+<!-- INDENTATION -->
+<p>Implementation 2: a translator into PDP-11 instructions
+(using UNIX). Less checks are performed than in the
+interpreter, because the translator is intended to speed up
+the execution of well-debugged programs.</p></td>
+</table>
+
+<p><b>Test Conditions</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Tester: E.G. Keizer<br>
+Date: October 1983<br>
+Validation Suite version: 3.0</p>
+<!-- INDENTATION -->
+<p>The final test run is made with a slightly modified
+validation suite.</p>
+<!-- INDENTATION -->
+<p><b>Erroneous programs</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Some test did not conform to the standard proposal of
+February 1979. It is this version of the standard proposal
+that is used by the authors of the validation suite.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.7-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The semicolon between high and integer on line 17 is
+replaced by a colon.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-13:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The div operator on line 14 replaced by mod.</p></td>
+</table>
+
+<p><b>Conformance tests</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of tests passed = 150<br>
+Number of tests failed = 6</p>
+<!-- INDENTATION -->
+<p><b>Details of failed tests</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.2-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Character sequences starting with the 8 characters
+&rsquo;procedur&rsquo; or &rsquo;function&rsquo; are
+erroneously classified as the word-symbols
+&rsquo;procedure&rsquo; and &rsquo;function&rsquo;.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.3-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Identifiers identical in the first eight characters, but
+differing in ninth or higher numbered characters are treated
+as identical.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.1-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>ACK-Pascal requires all formal program parameters to be
+declared with type <i>file</i>.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.5-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Gives run-time error eof seen at call to eoln. A have a
+hunch that this is a error in the suit.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.4.1-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Redefining the names of some standard procedures leads to
+incorrect behaviour of the runtime system. In this case it
+crashes without a sensible error message.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.5.1-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>This test can not be translated by our compiler because
+two non-identical variables are used in the same block with
+the same first eight characters. The test passed after
+replacement of one of those names.</p></td>
+</table>
+
+<p><b>Deviance tests</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of deviations correctly detected = 120<br>
+Number of tests not detecting deviations = 20</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p><b>Details of deviations</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The following tests are compiled without a proper error
+indication although they do not conform to the standard.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.6-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>ACK-Pascal allows labels in the range 0..32767. A warning
+is produced when testing for deviations from the
+standard.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.8-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>A missing space between a number and a word symbol is not
+detected.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.2-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.3-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.1-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.1-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.1-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Undetected scope error. The scope of an identifier should
+start at the beginning of the block in which it is declared.
+In the ACK-Pascal compiler the scope starts just after the
+declaration, however.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The values of fields from one variant are accessible from
+another variant. The correlation is exact.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.3-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The passing as a variable parameter of the selector of a
+variant part is not detected. A runtime error is produced
+because the variant selector is not initialized.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.4-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.4-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.4-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.4-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.4-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The ACK-Pascal compiler does not restrict the places from
+where a jump to a label by means of a goto-statement is
+allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-16:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>There are no errors produced for assignments to a
+variable in use as control-variable of a
+for-statement.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-9:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Use of a controlled variable after leaving the loop
+without intervening initialization is not detected.</p></td>
+</table>
+
+<p><b>Error handling</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The results depend on the EM implementation.</p>
+<!-- INDENTATION -->
+<p>Number of errors correctly detected =</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: 32<br>
+Implementation 2: 17</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of errors not detected =</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: 21<br>
+Implementation 2: 36</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of errors incorrectly detected =</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: 2<br>
+Implementation 2: 2</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p><b>Details of errors not detected</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The following test fails because the ACK-Pascal compiler
+only generates a warning that does not prevent to run the
+tests.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.2-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>A warning is produced if there is no assignment to a
+function-identifier.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>With this test the ACK-Pascal compiler issues an error
+message for a legal construct not directly related to the
+error to be detected.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.5-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Program does not compile. Buffer variable of text file is
+not allowed as variable parameter.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>The following errors are not detected at all.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.1-11:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Implementation 2: The use of an undefined integer is not
+caught as an error.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-11:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-12:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-13:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The notion of &rsquo;current variant&rsquo; is not
+implemented, not even if a tagfield is present.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.5-15:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.6-9:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.6-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.6-11:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.3.2-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Implementation 2: Subrange bounds are not checked.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.6-12:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.6-13:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.4-4:</p></td>
+</table>
+
+<p>If the base-type of a set is a subrange, then the set
+elements are not checked against the bounds of the subrange.
+Only the host-type of this subrange-type is relevant for
+ACK-Pascal.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.4-1:</p></td>
+</table>
+
+<p>Implementation 2: Nil pointers are not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.4-2:</p></td>
+</table>
+
+<p>Implementation 2: Undefined pointers are not
+detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.5-3:</p></td>
+</table>
+
+<p>Changing the file position while the window is in use as
+actual variable parameter or as an element of the record
+variable list of a with-statement is not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.2-9:</p></td>
+</table>
+
+<p>An undefined function result is not detected, because it
+is never used in an expression.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-7:</p></td>
+</table>
+
+<p>Disposing a variable while it is in use as actual
+variable parameter or as an element of the record variable
+list of a with-statement is not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-9:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-10:</p></td>
+</table>
+
+<p>It is not detected that a record variable, created with
+the variant form of new, is used as an operand in an
+expression or as the variable in an assignment or as an
+actual value parameter.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-11:</p></td>
+</table>
+
+<p>Use of a variable that is not reinitialized after a
+dispose is not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.4-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.4-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.4-7:</p></td>
+</table>
+
+<p>Implementation 2: There are no range checks for pred,
+succ and chr.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.5-6:</p></td>
+</table>
+
+<p>ACK-Pascal considers a rewrite of a file as a defining
+occurence.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-9:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-12:</p></td>
+</table>
+
+<p>Implementation 2: Division by 0 or integer overflow
+is</p>
+
+<p>not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-18:</p></td>
+</table>
+
+<p>The use of the some control variable in two nested for
+statements in not detected.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-19:</p></td>
+</table>
+
+<p>Access of a control variable after leaving the loop
+results in the final-value, although an error should be
+produced.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.2-3:</p></td>
+</table>
+
+<p>The program stops with a file not open error. The
+rewrite before the write is missing in the program.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.2-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.2-5:</p></td>
+</table>
+
+<p>Illegal FracDigits values are not detected.</p>
+
+<p><b>Implementation dependence</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of tests run = 14<br>
+Number of tests incorrectly handled = 0</p>
+<!-- INDENTATION -->
+<p><b>Details of implementation dependence</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.9-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Alternate comment delimiters are implemented</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.9-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The equivalent symbols @ for ^, (. for [ and .) for ] are
+not implemented.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.2.2-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Maxint = 32767</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.4-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Only elements with non-negative ordinal value are allowed
+in sets.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.1-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Standard procedures and functions are not allowed as
+parameters.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-11:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Details of the machine characteristics regarding real
+numbers:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<pre>beta =       2
+t =         56
+rnd =        1
+ngrd =       0
+
+
+<p>machep = -56<br>
+negep = -56<br>
+iexp = 8<br>
+minexp = -128<br>
+maxexp = 127<br>
+eps = 1.387779e-17<br>
+epsneg = 1.387779e-17<br>
+xmin = 2.938736e-39<br>
+xmax = 1.701412e+38</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.3-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.3-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>All operands of boolean expressions are evaluated.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.2-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.2-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The expression in an assignment statement is evaluated
+before the variable selection if this involves pointer
+dereferencing or array indexing.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.2.3-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Actual parameters are evaluated in reverse order.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.2-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The default width for integer, Boolean and real are 6, 5
+and 13.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.5.1-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The number of digits written in an exponent is 2.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.6-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The representations of true and false are ( true) and
+(false). The parenthesis serve to indicate width.</p></td>
+</table>
+
+<p><b>Quality measurement</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of tests run = 60<br>
+Number of tests handled incorrectly = 1</p>
+<!-- INDENTATION -->
+<p><b>Results of tests</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Several test perform operations on reals on indicate the
+error introduced by these operations. For each of these
+tests the following two quality measures are extracted:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>maxRE: maximum relative error<br>
+rmsRE: root-mean-square relative error</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 1.2-1:</p></td>
+</table>
+
+<p>Implementation 1: 25 thousand Whetstone instructions per
+second.<br>
+Implementation 2: 169 thousand Whetstone instructions per
+second.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 1.2-2:</p></td>
+</table>
+
+<p>The value of (TRUEACC-ACC)*2^56/100000 is 1.4 . This is
+well within the bounds specified in [3].<br>
+The GAMM measure is:<br>
+Implementation 1: 238 microseconds<br>
+Implementation 2: 26.3 microseconds.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 1.2-3:</p></td>
+</table>
+
+<p>The number of procedure calls calculated in this test
+exceeds the maximum integer value. The program stops
+indicating overflow.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.3-3:</p></td>
+</table>
+
+<p>The number of significant characters for identifiers is
+8.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.5-8:</p></td>
+</table>
+
+<p>There is no maximum to the line length.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.5-9:</p></td>
+</table>
+
+<p>The error message &quot;too many digits&quot; is given
+for numbers larger than maxint.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.5-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.5-11:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.5-12:</p></td>
+</table>
+
+<p>Normal values are allowed for real constants and
+variables.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.7-14:</p></td>
+</table>
+
+<p>A reasonably large number of strings is allowed.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.8-6:</p></td>
+</table>
+
+<p>No warning is given for possibly unclosed comments.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.1-12:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.1-13:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.1-14:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.2.1-15:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.1-2:</p></td>
+</table>
+
+<p>Large lists of declarations are possible in each
+block.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.2-6:</p></td>
+</table>
+
+<p>An &rsquo;array[integer] of&rsquo; is not allowed.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.2-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.2-8:</p></td>
+</table>
+
+<p>Large values are allowed for arrays and indices.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-14:</p></td>
+</table>
+
+<p>Large amounts of case-constant values are allowed in
+variants.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-15:</p></td>
+</table>
+
+<p>Large amounts of record sections can appear in the fixed
+part of a record.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.3-16:</p></td>
+</table>
+
+<p>Large amounts of variants are allowed in a record.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.4.3.4-4:</p></td>
+</table>
+
+<p>Size and speed of Warshall&rsquo;s algorithm depend on
+the implementation of EM:</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>Implementation 1:<br>
+size: 122 bytes<br>
+speed: 5.2 seconds</p>
+<!-- INDENTATION -->
+<p>Implementation 2:<br>
+size: 196 bytes<br>
+speed: 0.7 seconds</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.3.2-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Deep nesting of array indices is allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.3.2-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.5.3.2-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Arrays can have at least 8 dimensions.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.1-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Deep static nesting of procedure is allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.1-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Large amounts of formal parameters are allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.5.3-12:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Dispose is fully implemented.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-6:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test sqrt(x): no errors. The error is within acceptable
+bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -55.50<br>
+rmsRE: 2 ** -57.53</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test arctan(x): may cause underflow or overflow errors.
+The error is within acceptable bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -55.00<br>
+rmsRE: 2 ** -56.36</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test exp(x): may cause underflow or overflow errors. The
+error is not within acceptable bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -50.03<br>
+rmsRE: 2 ** -51.03</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-9:</p></td>
+</table>
+
+<p>Test sin(x): may cause underflow errors. The error is
+not within acceptable bounds.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -38.20<br>
+rmsRE: 2 ** -43.68</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test cos(x): may cause underflow errors. The error is not
+within acceptable bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -41.33<br>
+rmsRE: 2 ** -46.62</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.6.2-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test ln(x): The error is not within acceptable
+bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -54.05<br>
+rmsRE: 2 ** -55.77</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.1-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.1-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.1-5:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Complex nested expressions are allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-14:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Test real division: The error is within acceptable
+bounds.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 0<br>
+rmsRE: 0</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.2.2-15:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Operations of reals in the integer range are exact.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.7.3-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.2-1:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.4-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.5-15:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.7-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.8-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.9-20:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.10-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Static deep nesting of function calls, compound
+statements, if statements, case statements, repeat loops,
+while loops, for loops and with statements is possible.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.2-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Large amounts of statements are allowed in a compound
+statement.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.5-12:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The compiler requires case constants to be compatible
+with the case selector.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.5-13:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.5-14:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Large case statements are possible.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9-2:</p></td>
+</table>
+
+<p>Recursive IO on the same file is well-behaved.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.1-6:</p></td>
+</table>
+
+<p>The reading of real values from a text file is done with
+sufficient accuracy.</p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -54.61<br>
+rmsRE: 2 ** -56.32</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.1-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.2-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3-3:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.4-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Read, readln, write and writeln may have large amounts of
+parameters.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.1-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The loss of precision for reals written on a text file
+and read back is:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 2 ** -53.95<br>
+rmsRE: 2 ** -55.90</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>File IO buffers without trailing marker are correctly
+flushed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.9.3.5.2-2:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Reals are written with sufficient accuracy.</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="32%"></td>
+<td width="67%">
+<p>maxRE: 0<br>
+rmsRE: 0</p></td>
+</table>
+
+<p><b>Level 1 conformance tests</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of test passed = 4<br>
+Number of tests failed = 1</p>
+<!-- INDENTATION -->
+<p><b>Details of failed tests</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.7-4:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>An expression indicated by parenthesis whose value is a
+conformant array is not allowed.</p></td>
+</table>
+
+<p><b>Level 1 deviance tests</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of deviations correctly detected = 4<br>
+Number of tests not detecting deviations = 0</p></td>
+</table>
+
+<p><b>Level 1 error handling</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>The results depend on the EM implementation.</p>
+<!-- INDENTATION -->
+<p>Number of errors correctly detected =</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: 1<br>
+Implementation 2: 0</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of errors not detected =</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Implementation 1: 0<br>
+Implementation 2: 1</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p><b>Details of errors not detected</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.7-9:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Implementation 2: Subrange bounds are not
+checked.</p></td>
+</table>
+
+<p><b>Level 1 quality measurement</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of tests run = 1</p>
+<!-- INDENTATION -->
+<p><b>Results of test</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.6.3.7-10:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>Large conformant arrays are allowed.</p></td>
+</table>
+
+<p><b>Extensions</b></p>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="7%"></td>
+<td width="91%">
+<p>Number of tests run = 3</p>
+<!-- INDENTATION -->
+<p><b>Details</b></p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.9-7:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The alternative relational operators are not allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.1.9-8:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The alternative symbols for colon, semicolon and
+assignment are not allowed.</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="16%"></td>
+<td width="83%">
+<p>Test 6.8.3.5-16:</p></td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="24%"></td>
+<td width="75%">
+<p>The otherwise selector in case statements is not
+allowed.</p></td>
+</table>
+
+<p><b>References</b></p>
+
+<p>[1] A.S.Tanenbaum, E.G.Keizer, J.W.Stevenson, Hans van
+Staveren, &quot;Description of a machine architecture for
+use with block structured languages&quot;, Informatica
+rapport IR-81. [2] ISO standard proposal ISO/TC97/SC5-N462,
+dated February 1979. The same proposal, in slightly modified
+form, can be found in: A.M.Addyman e.a., &quot;A draft
+description of Pascal&quot;, Software, practice and
+experience, May 1979. An improved version, received March
+1980, is followed as much as possible for the current
+ACK-Pascal. [3] B. A. Wichman and J du Croz, A program to
+calculate the GAMM measure, Computer Journal, November
+1979.</p>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/val.pdf b/doc/tack/val.pdf
new file mode 100644 (file)
index 0000000..66a69dd
Binary files /dev/null and b/doc/tack/val.pdf differ
diff --git a/doc/tack/z80.html b/doc/tack/z80.html
new file mode 100644 (file)
index 0000000..e0174cc
--- /dev/null
@@ -0,0 +1,298 @@
+<!-- Creator     : groff version 1.18.1 -->
+<!-- CreationDate: Fri Feb 11 22:17:17 2005 -->
+<html>
+<head>
+<meta name="generator" content="groff -Thtml, see www.gnu.org">
+<meta name="Content-Style" content="text/css">
+<title>THE Z80 BACK END TABLE</title>
+</head>
+<body>
+
+<h1 align=center>THE Z80 BACK END TABLE</h1>
+<a href="#1. INTRODUCTION">1. INTRODUCTION</a><br>
+<a href="#2. IMPLEMENTATION">2. IMPLEMENTATION</a><br>
+
+<hr>
+<a name="1. INTRODUCTION"></a>
+<h2>1. INTRODUCTION</h2>
+
+<p>This table was written to make it run, not to make it
+clever! The effect is, that the table written for the intel
+8080, which was made very clever runs faster and requiers
+less space!! So, for anyone to run programs on a z80
+machine: n attempt could be made to make this table as
+clever as the one for the i80, or the i80 table could be
+used, for that can run on every z80 too.</p>
+<a name="2. IMPLEMENTATION"></a>
+<h2>2. IMPLEMENTATION</h2>
+
+<p>It will not be possible to run the entire Amsterdam
+Compiler Kit on a Z80-based computer system. One has to
+write a program on another system, a system where the
+compiler kit runs on. This program may be a mixture of
+high-level languages, such as C or Pascal, EM and z80
+assembly code. The program should be compiled using the
+compiler kit, producing z80 machine code. This code should
+come available to the z80 machine for example by downloading
+or by storing it in ROM (Read Only Memory). Depending on the
+characteristics of the particular z80 based system, some
+adaptions have to be made:</p>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>1)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>In <i>head_em</i>: the base address, which is the
+address where the first z80 instruction will be stored, and
+the initial value of the stackpointer are set to 0x1000 and
+0x7ffe respectivally. The latter because it could run on a
+32K machine as well. Other systems require other values.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>2)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>In <i>head_em</i>: before calling &quot;__m_a_i_n&quot;,
+the environment pointer, argument vector and argument count
+will have to be pushed onto the stack. Since this back-end
+is tested on a system without any knowledge of these things,
+dummies are pushed now.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>3)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>In <i>tail_em</i>: proper routines &quot;putchar&quot;
+and &quot;getchar&quot; should be provided. They should
+write resp. read a character on/from the monitor. Maybe some
+conversions will have to be made. The ones for the Nascom
+and Hermac z80 micro&rsquo;s are to be found in the
+EM-library.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>4)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>In <i>head_em</i>: an application program returns
+control to the monitor by jumping to address 0x20. Thie may
+have to be changed on different systems. For an CPM-machine
+for example this should be 0x5, to provide a warm boot.</p>
+</td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="3" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="4%">
+
+<p>5)</p>
+</td>
+<td width="6%"></td>
+<td width="90%">
+
+<p>In <i>tail_em</i>: the current version of the z80
+back-end has very limited I/O capabilities, because it was
+tested on a system that had no knowlegde of files. So the
+implementation of the EM-instruction <i>mon</i> is very
+simple; it can only do the following things:</p>
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<pre>        Monitor call 1:
+</pre>
+</td>
+</table>
+<!-- TABS -->
+
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>Exit</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Monitor call 3:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>read, always reads from the monitor.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>echos the read character.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>ignores file descriptor.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Monitor call 4:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>write, always writes on the monitor.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>ignores file descriptor.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Monitor call 5:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>open file, returns file descriptor -1.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Monitor call 6:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>close file, returns error code = 0.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>Monitor call 54:</p></td>
+</table>
+<!-- TABS -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="4" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="29%"></td>
+<td width="10%">
+
+<p>io-control, returns error code = 0.</p>
+</td>
+<td width="10%"></td>
+<td width="49%">
+</td>
+</table>
+<!-- INDENTATION -->
+<table width="100%" border=0 rules="none" frame="void"
+       cols="2" cellspacing="0" cellpadding="0">
+<tr valign="top" align="left">
+<td width="9%"></td>
+<td width="90%">
+<p>If the system should do file-handling the routine
+&quot;.mon&quot; should be extended thoroughly.</p>
+</td>
+</table>
+<hr>
+</body>
+</html>
diff --git a/doc/tack/z80.pdf b/doc/tack/z80.pdf
new file mode 100644 (file)
index 0000000..7ce2445
Binary files /dev/null and b/doc/tack/z80.pdf differ
index b3ff7a1..0f621bd 100644 (file)
@@ -31,68 +31,78 @@ SOBJS=      strees.o slocal.o slocal2.o sallo.o sorder.o stable.o
 FFILES=        freader.c fallo.c fmatch.c ftable.c forder.c flocal2.c fcomm2.c
 FOBJS= freader.o fallo.o fmatch.o ftable.o forder.o flocal2.o fcomm2.o
 
-P1INCS=        $M/pass1.h macdefs.h $M/manifest.h pcclocal.h $M/config.h $M/ndu.h \
-       /usr/include/stdio.h
-P1ONEP=        $(P1INCS) $M/onepass.h
+P1INCS=        $M/pass1.h macdefs.h $M/manifest.h pcclocal.h $M/config.h $M/ndu.h
+# \
+#      /usr/include/stdio.h
 P2INCS=        $M/pass2.h macdefs.h mac2defs.h $M/manifest.h pcclocal.h $M/config.h \
-       $M/ndu.h /usr/include/stdio.h
-P2ONEP=        $(P2INCS) $M/onepass.h
+       $M/ndu.h
+# /usr/include/stdio.h
 
-M=../mip
+#M=../mip
+M=.
 TESTDIR = .
 
-all: ccom sccom f1
+#all: ccom sccom f1
+all: ccom
 
 #
 # 'ccom' is a one-pass C compiler.
 #
-ccom: rodata.o cgram.o xdefs.o scan.o pftn.o trees.o optim.o code.o local.o \
+# rodata.o
+ccom: cgram.o xdefs.o scan.o pftn.o trees.o optim.o code.o local.o \
        reader.o local2.o order.o match.o allo.o comm1.o table.o stab.o
-       $(CC) $(LDFLAGS) rodata.o cgram.o xdefs.o scan.o pftn.o trees.o \
+# rodata.o
+       $(CC) $(LDFLAGS) cgram.o xdefs.o scan.o pftn.o trees.o \
                optim.o code.o local.o reader.o local2.o order.o match.o \
                allo.o comm1.o table.o stab.o -o $(TESTDIR)/ccom
-trees.o: $(P1ONEP) $M/trees.c
+trees.o: $(P1INCS) $M/trees.c
        $(CC) -c $(COPTS) $M/trees.c
-optim.o: $(P1ONEP) $M/optim.c
+optim.o: $(P1INCS) $M/optim.c
        $(CC) -c $(COPTS) $M/optim.c
-pftn.o: $(P1ONEP) $M/pftn.c
+pftn.o: $(P1INCS) $M/pftn.c
        $(CC) -c $(COPTS) $M/pftn.c
-code.o: $(P1ONEP) code.c
+code.o: $(P1INCS) code.c
        $(CC) -c $(COPTS) code.c
-local.o: $(P1ONEP) local.c
+local.o: $(P1INCS) local.c
        $(CC) -c $(COPTS) local.c
-scan.o: $(P1ONEP) $M/scan.c
+scan.o: $(P1INCS) $M/scan.c
        $(CC) -c $(COPTS) $M/scan.c
-xdefs.o: $(P1ONEP) $M/xdefs.c
+xdefs.o: $(P1INCS) $M/xdefs.c
        $(CC) -c $(COPTS) $M/xdefs.c
-cgram.o: $(P1ONEP) cgram.c
+cgram.o: $(P1INCS) cgram.c
        $(CC) -c $(COPTS) cgram.c
-rodata.o: rodata.c
-       $(CC) -c $(COPTS) -R rodata.c
-rodata.c cgram.c: $M/cgram.y pcctokens
-       cat pcctokens $M/cgram.y > gram.in
-       $(YACC) gram.in
-       $(RM) rodata.c
-       sh ./:yyfix yyexca yyact yypact yypgo yyr1 yyr2 yychk yydef
+#rodata.o: rodata.c
+#      $(CC) -c $(COPTS) -R rodata.c
+#rodata.c
+cgram.c: $M/cgram.y
+# pcctokens
+#      cat pcctokens $M/cgram.y > gram.in
+#      $(YACC) gram.in
+       $(YACC) $M/cgram.y
+#      $(RM) rodata.c
+#      sh ./:yyfix yyexca yyact yypact yypgo yyr1 yyr2 yychk yydef
        mv y.tab.c cgram.c
-comm1.o: $(P1ONEP) $M/common.c
-       $(LN) $M/common.c comm1.c
-       $(CC) -c $(COPTS) -DPASS1COMMON comm1.c
-       $(RM) comm1.c
-stab.o: $(P1ONEP) stab.c \
-       /usr/include/stab.h /usr/include/a.out.h /usr/include/sys/types.h
+#comm1.o: $(P1INCS) $M/common.c
+#      $(LN) $M/common.c comm1.c
+#      $(CC) -c $(COPTS) -DPASS1COMMON comm1.c
+#      $(RM) comm1.c
+comm1.o: $(P1INCS) comm1.c
+       $(CC) -c $(COPTS) -R comm1.c
+stab.o: $(P1INCS) stab.c
+# \
+#      /usr/include/stab.h /usr/include/a.out.h /usr/include/sys/types.h
        $(CC) -c $(COPTS) stab.c
-table.o: $(P2ONEP) table.c
+table.o: $(P2INCS) table.c
        $(CC) -c $(COPTS) -R table.c
-reader.o: $(P2ONEP) $M/reader.c
+reader.o: $(P2INCS) $M/reader.c
        $(CC) -c $(COPTS) $M/reader.c
-local2.o: $(P2ONEP) local2.c
+local2.o: $(P2INCS) local2.c
        $(CC) -c $(COPTS) local2.c
-order.o: $(P2ONEP) order.c
+order.o: $(P2INCS) order.c
        $(CC) -c $(COPTS) order.c
-match.o: $(P2ONEP) $M/match.c
+match.o: $(P2INCS) $M/match.c
        $(CC) -c $(COPTS) $M/match.c
-allo.o: $(P2ONEP) $M/allo.c
+allo.o: $(P2INCS) $M/allo.c
        $(CC) -c $(COPTS) $M/allo.c
 
 #
@@ -104,27 +114,27 @@ sccom: rodata.o cgram.o xdefs.o scan.o pftn.o strees.o optim.o code.o slocal.o \
        $(CC) $(LDFLAGS) rodata.o cgram.o xdefs.o scan.o pftn.o strees.o \
                optim.o code.o slocal.o reader.o slocal2.o sorder.o match.o \
                sallo.o comm1.o stable.o stab.o -o $(TESTDIR)/sccom
-strees.o: $(P1ONEP) $M/trees.c
+strees.o: $(P1INCS) $M/trees.c
        $(LN) $M/trees.c strees.c
        $(CC) -c $(SCOPTS) strees.c
        $(RM) strees.c
-slocal.o: $(P1ONEP) local.c
+slocal.o: $(P1INCS) local.c
        $(LN) local.c slocal.c
        $(CC) -c $(SCOPTS) slocal.c
        $(RM) slocal.c
-slocal2.o: $(P2ONEP) local2.c
+slocal2.o: $(P2INCS) local2.c
        $(LN) local2.c slocal2.c
        $(CC) -c $(SCOPTS) slocal2.c
        $(RM) slocal2.c
-sallo.o: $(P2ONEP) $M/allo.c
+sallo.o: $(P2INCS) $M/allo.c
        $(LN) $M/allo.c sallo.c
        $(CC) -c $(SCOPTS) sallo.c
        $(RM) sallo.c
-sorder.o: $(P2ONEP) order.c
+sorder.o: $(P2INCS) order.c
        $(LN) order.c sorder.c
        $(CC) -c $(SCOPTS) sorder.c
        $(RM) sorder.c
-stable.o: $(P2ONEP) table.c
+stable.o: $(P2INCS) table.c
        $(LN) table.c stable.c
        $(CC) -c $(SCOPTS) -R stable.c
        $(RM) stable.c
@@ -174,20 +184,25 @@ install: all
 
 GREP=  egrep
 
-pcclocal.h: localdefs.h /usr/include/pcc.h
-       $(RM) pcclocal.h
-       cat /usr/include/pcc.h localdefs.h | $(GREP) '^#[       ]*(define[      ][      ]*PCC(F|T|TM|OM)?_|ifdef|ifndef|endif)' | sed -e 's/PCC[A-Z]*_//' > pcclocal.h 
-
-pcctokens: localdefs.h /usr/include/pcc.h
-       $(RM) pcctokens
-       cat /usr/include/pcc.h localdefs.h | $(GREP) '^#[       ]*define[       ][      ]*PCC_' | sed -e 's/^#[         ]*define[       ][      ]*PCC_/%term    /' > pcctokens
+##pcclocal.h: localdefs.h /usr/include/pcc.h
+#pcclocal.h: localdefs.h $M/pcc.h
+#      $(RM) pcclocal.h
+##     cat /usr/include/pcc.h localdefs.h | $(GREP) '^#[       ]*(define[      ][      ]*PCC(F|T|TM|OM)?_|ifdef|ifndef|endif)' | sed -e 's/PCC[A-Z]*_//' > pcclocal.h 
+#      cat $M/pcc.h localdefs.h | $(GREP) '^#[         ]*(define[      ][      ]*PCC(F|T|TM|OM)?_|ifdef|ifndef|endif)' | sed -e 's/PCC[A-Z]*_//' > pcclocal.h 
+#
+##pcctokens: localdefs.h /usr/include/pcc.h
+#pcctokens: localdefs.h $M/pcc.h
+#      $(RM) pcctokens
+##     cat /usr/include/pcc.h localdefs.h | $(GREP) '^#[       ]*define[       ][      ]*PCC_' | sed -e 's/^#[         ]*define[       ][      ]*PCC_/%term    /' > pcctokens
+#      cat $M/pcc.h localdefs.h | $(GREP) '^#[         ]*define[       ][      ]*PCC_' | sed -e 's/^#[         ]*define[       ][      ]*PCC_/%term    /' > pcctokens
 
 DUMMIES=       $(SFILES) $(FFILES)
 
 shrink:
        $(RM) *.o ccom sccom f1 $(DUMMIES)
 clean:
-       $(RM) *.o ccom sccom f1 cgram.c rodata.c pcctokens pcclocal.h gram.in $(DUMMIES)
+#      $(RM) *.o ccom sccom f1 cgram.c rodata.c pcctokens pcclocal.h gram.in $(DUMMIES)
+       $(RM) *.o ccom
 sfix:
        $(RM) $(SFILES)
 sclean:
diff --git a/lib/pcc/allo.c b/lib/pcc/allo.c
new file mode 100644 (file)
index 0000000..528d704
--- /dev/null
@@ -0,0 +1,586 @@
+#ifndef lint
+static char *sccsid ="@(#)allo.c       4.8 (Berkeley) 1/8/86";
+#endif lint
+
+# include "pass2.h"
+
+NODE resc[3];
+
+int busy[REGSZ];
+
+int maxa, mina, maxb, minb;
+
+# ifndef ALLO0
+allo0(){ /* free everything */
+
+       register i;
+
+       maxa = maxb = -1;
+       mina = minb = 0;
+
+       REGLOOP(i){
+               busy[i] = 0;
+               if( rstatus[i] & STAREG ){
+                       if( maxa<0 ) mina = i;
+                       maxa = i;
+                       }
+               if( rstatus[i] & STBREG ){
+                       if( maxb<0 ) minb = i;
+                       maxb = i;
+                       }
+               }
+       }
+# endif
+
+# ifndef ALLO
+allo( p, q ) NODE *p; struct optab *q; {
+
+       register n, i, j;
+       int either;
+
+       n = q->needs;
+       either = ( EITHER & n );
+       i = 0;
+
+       while( n & NACOUNT ){
+               resc[i].in.op = REG;
+               resc[i].tn.rval = freereg( p, n&NAMASK );
+               resc[i].tn.lval = 0;
+#ifdef FLEXNAMES
+               resc[i].in.name = "";
+#else
+               resc[i].in.name[0] = '\0';
+#endif
+               n -= NAREG;
+               ++i;
+               }
+
+       if (either) { /* all or nothing at all */
+               for( j = 0; j < i; j++ )
+                       if( resc[j].tn.rval < 0 ) { /* nothing */
+                               i = 0;
+                               break;
+                               }
+               if( i != 0 ) goto ok; /* all */
+               }
+
+       while( n & NBCOUNT ){
+               resc[i].in.op = REG;
+               resc[i].tn.rval = freereg( p, n&NBMASK );
+               resc[i].tn.lval = 0;
+#ifdef FLEXNAMES
+               resc[i].in.name = "";
+#else
+               resc[i].in.name[0] = '\0';
+#endif
+               n -= NBREG;
+               ++i;
+               }
+       if (either) { /* all or nothing at all */
+               for( j = 0; j < i; j++ )
+                       if( resc[j].tn.rval < 0 ) { /* nothing */
+                               i = 0;
+                               break;
+                               }
+               if( i != 0 ) goto ok; /* all */
+               }
+
+       if( n & NTMASK ){
+               resc[i].in.op = OREG;
+               resc[i].tn.rval = TMPREG;
+               if( p->in.op == STCALL || p->in.op == STARG || p->in.op == UNARY STCALL || p->in.op == STASG ){
+                       resc[i].tn.lval = freetemp( (SZCHAR*p->stn.stsize + (SZINT-1))/SZINT );
+                       }
+               else {
+                       resc[i].tn.lval = freetemp( (n&NTMASK)/NTEMP );
+                       }
+#ifdef FLEXNAMES
+               resc[i].in.name = "";
+#else
+               resc[i].in.name[0] = '\0';
+#endif
+
+               resc[i].tn.lval = BITOOR(resc[i].tn.lval);
+               ++i;
+               }
+
+       /* turn off "temporarily busy" bit */
+
+       ok:
+       REGLOOP(j){
+               busy[j] &= ~TBUSY;
+               }
+
+       for( j=0; j<i; ++j ) if( resc[j].tn.rval < 0 ) return(0);
+       return(1);
+
+       }
+# endif
+
+extern unsigned int offsz;
+freetemp( k ){ /* allocate k integers worth of temp space */
+       /* we also make the convention that, if the number of words is more than 1,
+       /* it must be aligned for storing doubles... */
+
+# ifndef BACKTEMP
+       int t;
+
+       if( k>1 ){
+               SETOFF( tmpoff, ALDOUBLE );
+               }
+
+       t = tmpoff;
+       tmpoff += k*SZINT;
+       if( tmpoff > maxoff ) maxoff = tmpoff;
+       if( tmpoff >= offsz )
+               cerror( "stack overflow" );
+       if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
+       return(t);
+
+# else
+       tmpoff += k*SZINT;
+       if( k>1 ) {
+               SETOFF( tmpoff, ALDOUBLE );
+               }
+       if( tmpoff > maxoff ) maxoff = tmpoff;
+       if( tmpoff >= offsz )
+               cerror( "stack overflow" );
+       if( tmpoff-baseoff > maxtemp ) maxtemp = tmpoff-baseoff;
+       return( -tmpoff );
+# endif
+       }
+
+freereg( p, n ) NODE *p; {
+       /* allocate a register of type n */
+       /* p gives the type, if floating */
+
+       register j;
+
+       /* not general; means that only one register (the result) OK for call */
+       if( callop(p->in.op) ){
+               j = callreg(p);
+               if( usable( p, n, j ) ) return( j );
+               /* have allocated callreg first */
+               }
+       j = p->in.rall & ~MUSTDO;
+       if( j!=NOPREF && usable(p,n,j) ){ /* needed and not allocated */
+               return( j );
+               }
+       if( n&NAMASK ){
+               for( j=mina; j<=maxa; ++j ) if( rstatus[j]&STAREG ){
+                       if( usable(p,n,j) ){
+                               return( j );
+                               }
+                       }
+               }
+       else if( n &NBMASK ){
+               for( j=minb; j<=maxb; ++j ) if( rstatus[j]&STBREG ){
+                       if( usable(p,n,j) ){
+                               return(j);
+                               }
+                       }
+               }
+
+       return( -1 );
+       }
+
+# ifndef USABLE
+usable( p, n, r ) NODE *p; {
+       /* decide if register r is usable in tree p to satisfy need n */
+
+       /* checks, for the moment */
+       if( !istreg(r) ) cerror( "usable asked about nontemp register" );
+
+       if( busy[r] > 1 ) return(0);
+       if( isbreg(r) ){
+               if( n&NAMASK ) return(0);
+               }
+       else {
+               if( n & NBMASK ) return(0);
+               }
+       /*
+        * Some special cases that require register pairs...
+        * Have to check for ==, <=, etc. because the result is type int
+        * but need a register pair temp if either side is wide.
+        * For +=, *= etc. where2 lhs is narrow and rhs is wide, the temp
+        * register must be wide.
+        */
+       if( (n&NAMASK) &&
+           (szty(p->in.type) == 2 ||
+            (logop(p->in.op) && (szty(p->in.left->in.type) == 2 ||
+             szty(p->in.right->in.type) == 2)) ||
+            (asgop(p->in.op) && szty(p->in.right->in.type) == 2 &&
+             szty(p->in.left->in.type) == 1))
+       ){
+#ifndef NOEVENODD
+               if( r&01 ) return(0);
+#endif
+               if( !istreg(r+1) ) return( 0 );
+               if( busy[r+1] > 1 ) return( 0 );
+               if( busy[r] == 0 && busy[r+1] == 0  ||
+                   busy[r+1] == 0 && shareit( p, r, n ) ||
+                   busy[r] == 0 && shareit( p, r+1, n ) ){
+                       busy[r] |= TBUSY;
+                       busy[r+1] |= TBUSY;
+                       return(1);
+                       }
+               else return(0);
+               }
+       if( busy[r] == 0 ) {
+               busy[r] |= TBUSY;
+               return(1);
+               }
+
+       /* busy[r] is 1: is there chance for sharing */
+       return( shareit( p, r, n ) );
+
+       }
+# endif
+
+shareit( p, r, n ) NODE *p; {
+       /* can we make register r available by sharing from p
+          given that the need is n */
+       if( (n&(NASL|NBSL)) && ushare( p, 'L', r ) ) return(1);
+       if( (n&(NASR|NBSR)) && ushare( p, 'R', r ) ) return(1);
+       return(0);
+       }
+
+ushare( p, f, r ) NODE *p; {
+       /* can we find a register r to share on the left or right
+               (as f=='L' or 'R', respectively) of p */
+       p = getlr( p, f );
+       if( p->in.op == UNARY MUL ) p = p->in.left;
+       if( p->in.op == OREG ){
+               if( R2TEST(p->tn.rval) ){
+                       return( r==R2UPK1(p->tn.rval) || r==R2UPK2(p->tn.rval) );
+                       }
+               else return( r == p->tn.rval );
+               }
+       if( p->in.op == REG ){
+               return( r == p->tn.rval || ( szty(p->in.type) == 2 && r==p->tn.rval+1 ) );
+               }
+       return(0);
+       }
+
+recl2( p ) register NODE *p; {
+       register r = p->tn.rval;
+#ifndef OLD
+       int op = p->in.op;
+       if (op == REG && r >= REGSZ)
+               op = OREG;
+       if( op == REG ) rfree( r, p->in.type );
+       else if( op == OREG ) {
+               if( R2TEST( r ) ) {
+                       if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
+                       rfree( R2UPK2( r ), INT );
+                       }
+               else {
+                       rfree( r, PTR+INT );
+                       }
+               }
+#else
+       if( p->in.op == REG ) rfree( r, p->in.type );
+       else if( p->in.op == OREG ) {
+               if( R2TEST( r ) ) {
+                       if( R2UPK1( r ) != 100 ) rfree( R2UPK1( r ), PTR+INT );
+                       rfree( R2UPK2( r ), INT );
+                       }
+               else {
+                       rfree( r, PTR+INT );
+                       }
+               }
+#endif
+       }
+
+int rdebug = 0;
+
+# ifndef RFREE
+rfree( r, t ) TWORD t; {
+       /* mark register r free, if it is legal to do so */
+       /* t is the type */
+
+# ifndef BUG3
+       if( rdebug ){
+               printf( "rfree( %s ), size %d\n", rnames[r], szty(t) );
+               }
+# endif
+
+       if( istreg(r) ){
+               if( --busy[r] < 0 ) cerror( "register overfreed");
+               if( szty(t) == 2 ){
+#ifdef NOEVENODD
+                       if( istreg(r) ^ istreg(r+1) ) cerror( "illegal free" );
+#else
+                       if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal free" );
+#endif
+                       if( --busy[r+1] < 0 ) cerror( "register overfreed" );
+                       }
+               }
+       }
+# endif
+
+# ifndef RBUSY
+rbusy(r,t) TWORD t; {
+       /* mark register r busy */
+       /* t is the type */
+
+# ifndef BUG3
+       if( rdebug ){
+               printf( "rbusy( %s ), size %d\n", rnames[r], szty(t) );
+               }
+# endif
+
+       if( istreg(r) ) ++busy[r];
+       if( szty(t) == 2 ){
+               if( istreg(r+1) ) ++busy[r+1];
+#ifdef NOEVENODD
+               if( istreg(r) ^ istreg(r+1) ) cerror( "illegal register pair freed" );
+#else
+               if( (r&01) || (istreg(r)^istreg(r+1)) ) cerror( "illegal register pair freed" );
+#endif
+               }
+       }
+# endif
+
+# ifndef BUG3
+rwprint( rw ){ /* print rewriting rule */
+       register i, flag;
+       static char * rwnames[] = {
+
+               "RLEFT",
+               "RRIGHT",
+               "RESC1",
+               "RESC2",
+               "RESC3",
+               0,
+               };
+
+       if( rw == RNULL ){
+               printf( "RNULL" );
+               return;
+               }
+
+       if( rw == RNOP ){
+               printf( "RNOP" );
+               return;
+               }
+
+       flag = 0;
+       for( i=0; rwnames[i]; ++i ){
+               if( rw & (1<<i) ){
+                       if( flag ) printf( "|" );
+                       ++flag;
+                       printf( rwnames[i] );
+                       }
+               }
+       }
+# endif
+
+reclaim( p, rw, cookie ) NODE *p; {
+       register NODE **qq;
+       register NODE *q;
+       register i;
+       NODE *recres[5];
+       struct respref *r;
+
+       /* get back stuff */
+
+# ifndef BUG3
+       if( rdebug ){
+               printf( "reclaim( %o, ", p );
+               rwprint( rw );
+               printf( ", " );
+               prcook( cookie );
+               printf( " )\n" );
+               }
+# endif
+
+       if( rw == RNOP || ( p->in.op==FREE && rw==RNULL ) ) return;  /* do nothing */
+
+       walkf( p, recl2 );
+
+       if( callop(p->in.op) ){
+               /* check that all scratch regs are free */
+               callchk(p);  /* ordinarily, this is the same as allchk() */
+               }
+
+       if( rw == RNULL || (cookie&FOREFF) ){ /* totally clobber, leaving nothing */
+               tfree(p);
+               return;
+               }
+
+       /* handle condition codes specially */
+
+       if( (cookie & FORCC) && (rw&RESCC)) {
+               /* result is CC register */
+               tfree(p);
+               p->in.op = CCODES;
+               p->tn.lval = 0;
+               p->tn.rval = 0;
+               return;
+               }
+
+       /* locate results */
+
+       qq = recres;
+
+       if( rw&RLEFT) *qq++ = getlr( p, 'L' );;
+       if( rw&RRIGHT ) *qq++ = getlr( p, 'R' );
+       if( rw&RESC1 ) *qq++ = &resc[0];
+       if( rw&RESC2 ) *qq++ = &resc[1];
+       if( rw&RESC3 ) *qq++ = &resc[2];
+
+       if( qq == recres ){
+               cerror( "illegal reclaim");
+               }
+
+       *qq = NIL;
+
+       /* now, select the best result, based on the cookie */
+
+       for( r=respref; r->cform; ++r ){
+               if( cookie & r->cform ){
+                       for( qq=recres; (q= *qq) != NIL; ++qq ){
+                               if( tshape( q, r->mform ) ) goto gotit;
+                               }
+                       }
+               }
+
+       /* we can't do it; die */
+       cerror( "cannot reclaim");
+
+       gotit:
+
+       if( p->in.op == STARG ) p = p->in.left;  /* STARGs are still STARGS */
+
+       q->in.type = p->in.type;  /* to make multi-register allocations work */
+               /* maybe there is a better way! */
+       q = tcopy(q);
+
+       tfree(p);
+
+       p->in.op = q->in.op;
+       p->tn.lval = q->tn.lval;
+       p->tn.rval = q->tn.rval;
+#ifdef FLEXNAMES
+       p->in.name = q->in.name;
+#ifdef ONEPASS
+       p->in.stalign = q->in.stalign;
+#endif
+#else
+       for( i=0; i<NCHNAM; ++i )
+               p->in.name[i] = q->in.name[i];
+#endif
+
+       q->in.op = FREE;
+
+       /* if the thing is in a register, adjust the type */
+
+       switch( p->in.op ){
+
+       case REG:
+               if( !rtyflg ){
+                       /* the C language requires intermediate results to change type */
+                       /* this is inefficient or impossible on some machines */
+                       /* the "T" command in match supresses this type changing */
+                       if( p->in.type == CHAR || p->in.type == SHORT ) p->in.type = INT;
+                       else if( p->in.type == UCHAR || p->in.type == USHORT ) p->in.type = UNSIGNED;
+#if !defined(FORT) && !defined(SPRECC)
+                       else if( p->in.type == FLOAT ) p->in.type = DOUBLE;
+#endif
+                       }
+               if( ! (p->in.rall & MUSTDO ) ) return;  /* unless necessary, ignore it */
+               i = p->in.rall & ~MUSTDO;
+               if( i & NOPREF ) return;
+               if( i != p->tn.rval ){
+                       if( busy[i] || ( szty(p->in.type)==2 && busy[i+1] ) ){
+                               cerror( "faulty register move" );
+                               }
+                       rbusy( i, p->in.type );
+                       rfree( p->tn.rval, p->in.type );
+                       rmove( i, p->tn.rval, p->in.type );
+                       p->tn.rval = i;
+                       }
+
+       case OREG:
+               if( p->in.op == REG || !R2TEST(p->tn.rval) ) {
+                       if( busy[p->tn.rval]>1 && istreg(p->tn.rval) ) cerror( "potential register overwrite");
+                       }
+               else
+                       if( (R2UPK1(p->tn.rval) != 100 && busy[R2UPK1(p->tn.rval)]>1 && istreg(R2UPK1(p->tn.rval)) )
+                               || (busy[R2UPK2(p->tn.rval)]>1 && istreg(R2UPK2(p->tn.rval)) ) )
+                          cerror( "potential register overwrite");
+               }
+
+       }
+
+#ifndef ncopy
+XXXncopy( q, p ) NODE *p, *q; {
+       /* copy the contents of p into q, without any feeling for
+          the contents */
+       /* this code assume that copying rval and lval does the job;
+          in general, it might be necessary to special case the
+          operator types */
+       register i;
+
+       q->in.op = p->in.op;
+       q->in.rall = p->in.rall;
+       q->in.type = p->in.type;
+       q->tn.lval = p->tn.lval;
+       q->tn.rval = p->tn.rval;
+#ifdef FLEXNAMES
+       q->in.name = p->in.name;
+#ifdef ONEPASS
+       q->in.stalign = p->in.stalign;
+#endif
+#else
+       for( i=0; i<NCHNAM; ++i ) q->in.name[i]  = p->in.name[i];
+#endif
+
+       }
+#endif
+
+NODE *
+tcopy( p ) register NODE *p; {
+       /* make a fresh copy of p */
+
+       register NODE *q;
+       register r;
+
+       ncopy( q=talloc(), p );
+
+       r = p->tn.rval;
+       if( p->in.op == REG ) rbusy( r, p->in.type );
+       else if( p->in.op == OREG ) {
+               if( R2TEST(r) ){
+                       if( R2UPK1(r) != 100 ) rbusy( R2UPK1(r), PTR+INT );
+                       rbusy( R2UPK2(r), INT );
+                       }
+               else {
+                       rbusy( r, PTR+INT );
+                       }
+               }
+
+       switch( optype(q->in.op) ){
+
+       case BITYPE:
+               q->in.right = tcopy(p->in.right);
+       case UTYPE:
+               q->in.left = tcopy(p->in.left);
+               }
+
+       return(q);
+       }
+
+allchk(){
+       /* check to ensure that all register are free */
+
+       register i;
+
+       REGLOOP(i){
+               if( istreg(i) && busy[i] ){
+                       cerror( "register allocation error");
+                       }
+               }
+
+       }
diff --git a/lib/pcc/cgram.c b/lib/pcc/cgram.c
new file mode 100644 (file)
index 0000000..2aad878
--- /dev/null
@@ -0,0 +1,1504 @@
+# define TOKENS 0
+# define ERROR 1
+# define FREE 2
+# define STRING 3
+# define ICON 4
+# define FCON 5
+# define DCON 6
+# define NAME 7
+# define REG 8
+# define OREG 9
+# define CCODES 10
+# define FLD 11
+# define PLUS 12
+# define PLUSEQ 13
+# define UPLUS 14
+# define MINUS 15
+# define MINUSEQ 16
+# define UMINUS 17
+# define MUL 18
+# define MULEQ 19
+# define DIV 21
+# define DIVEQ 22
+# define MOD 23
+# define MODEQ 24
+# define INCR 25
+# define DECR 26
+# define ASSIGN 27
+# define AND 28
+# define ANDEQ 29
+# define OR 31
+# define OREQ 32
+# define ER 33
+# define EREQ 34
+# define LS 35
+# define LSEQ 36
+# define RS 37
+# define RSEQ 38
+# define COMPL 39
+# define EQ 40
+# define NE 41
+# define LE 42
+# define LT 43
+# define GE 44
+# define GT 45
+# define ULE 46
+# define ULT 47
+# define UGE 48
+# define UGT 49
+# define QUEST 50
+# define COLON 51
+# define ANDAND 52
+# define OROR 53
+# define NOT 54
+# define CALL 55
+# define UCALL 57
+# define FORTCALL 58
+# define UFORTCALL 60
+# define INLINE 61
+# define UINLINE 63
+# define DEREF 20
+# define ADDROF 30
+# define DOT 64
+# define STREF 65
+# define STASG 66
+# define STARG 67
+# define STCALL 68
+# define USTCALL 70
+# define SCONV 71
+# define PCONV 72
+# define PMCONV 73
+# define PVCONV 74
+# define CAST 75
+# define LB 76
+# define RB 77
+# define COMOP 78
+# define CM 79
+# define FORCE 80
+# define GOTO 81
+# define CBRANCH 82
+# define RETURN 83
+# define INIT 84
+# define TYPE 85
+# define CLASS 86
+# define MAXOP 86
+# define LOCALTOKENS 100
+# define ASOP 100
+# define RELOP 101
+# define EQUOP 102
+# define DIVOP 103
+# define SHIFTOP 104
+# define INCOP 105
+# define UNOP 106
+# define STROP 107
+# define LP 108
+# define RP 109
+# define LC 110
+# define RC 111
+# define STRUCT 112
+# define IF 113
+# define ELSE 114
+# define SWITCH 115
+# define BREAK 116
+# define CONTINUE 117
+# define WHILE 118
+# define DO 119
+# define FOR 120
+# define DEFAULT 121
+# define CASE 122
+# define SIZEOF 123
+# define ENUM 124
+# define SM 125
+
+# line 146 "cgram.y"
+# include "pass1.h"
+#define yyclearin yychar = -1
+#define yyerrok yyerrflag = 0
+extern int yychar;
+extern short yyerrflag;
+#ifndef YYMAXDEPTH
+#define YYMAXDEPTH 150
+#endif
+YYSTYPE yylval, yyval;
+
+# line 165 "cgram.y"
+       static int fake = 0;
+#ifndef FLEXNAMES
+       static char fakename[NCHNAM+1];
+#else
+       static char fakename[24];
+#endif
+# define YYERRCODE 256
+
+# line 899 "cgram.y"
+
+
+NODE *
+mkty( t, d, s ) unsigned t; {
+       return( block( TYPE, NIL, NIL, t, d, s ) );
+       }
+
+NODE *
+bdty( op, p, v ) NODE *p; {
+       register NODE *q;
+
+       q = block( op, p, NIL, INT, 0, INT );
+
+       switch( op ){
+
+       case UNARY MUL:
+       case UNARY CALL:
+               break;
+
+       case LB:
+               q->in.right = bcon(v);
+               break;
+
+       case NAME:
+               q->tn.rval = v;
+               break;
+
+       default:
+               cerror( "bad bdty" );
+               }
+
+       return( q );
+       }
+
+dstash( n ){ /* put n into the dimension table */
+       if( curdim >= DIMTABSZ-1 ){
+               cerror( "dimension table overflow");
+               }
+       dimtab[ curdim++ ] = n;
+       }
+
+savebc() {
+       if( psavbc > & asavbc[BCSZ-4 ] ){
+               cerror( "whiles, fors, etc. too deeply nested");
+               }
+       *psavbc++ = brklab;
+       *psavbc++ = contlab;
+       *psavbc++ = flostat;
+       *psavbc++ = swx;
+       flostat = 0;
+       }
+
+resetbc(mask){
+
+       swx = *--psavbc;
+       flostat = *--psavbc | (flostat&mask);
+       contlab = *--psavbc;
+       brklab = *--psavbc;
+
+       }
+
+addcase(p) NODE *p; { /* add case to switch */
+
+       p = optim( p );  /* change enum to ints */
+       if( p->in.op != ICON ){
+               uerror( "non-constant case expression");
+               return;
+               }
+       if( swp == swtab ){
+               uerror( "case not in switch");
+               return;
+               }
+       if( swp >= &swtab[SWITSZ] ){
+               cerror( "switch table overflow");
+               }
+       swp->sval = p->tn.lval;
+       deflab( swp->slab = getlab() );
+       ++swp;
+       tfree(p);
+       }
+
+adddef(){ /* add default case to switch */
+       if( swtab[swx].slab >= 0 ){
+               uerror( "duplicate default in switch");
+               return;
+               }
+       if( swp == swtab ){
+               uerror( "default not inside switch");
+               return;
+               }
+       deflab( swtab[swx].slab = getlab() );
+       }
+
+swstart(){
+       /* begin a switch block */
+       if( swp >= &swtab[SWITSZ] ){
+               cerror( "switch table overflow");
+               }
+       swx = swp - swtab;
+       swp->slab = -1;
+       ++swp;
+       }
+
+swend(){ /* end a switch block */
+
+       register struct sw *swbeg, *p, *q, *r, *r1;
+       CONSZ temp;
+       int tempi;
+
+       swbeg = &swtab[swx+1];
+
+       /* sort */
+
+       r1 = swbeg;
+       r = swp-1;
+
+       while( swbeg < r ){
+               /* bubble largest to end */
+               for( q=swbeg; q<r; ++q ){
+                       if( q->sval > (q+1)->sval ){
+                               /* swap */
+                               r1 = q+1;
+                               temp = q->sval;
+                               q->sval = r1->sval;
+                               r1->sval = temp;
+                               tempi = q->slab;
+                               q->slab = r1->slab;
+                               r1->slab = tempi;
+                               }
+                       }
+               r = r1;
+               r1 = swbeg;
+               }
+
+       /* it is now sorted */
+
+       for( p = swbeg+1; p<swp; ++p ){
+               if( p->sval == (p-1)->sval ){
+                       uerror( "duplicate case in switch, %d", tempi=p->sval );
+                       return;
+                       }
+               }
+
+       genswitch( swbeg-1, swp-swbeg );
+       swp = swbeg-1;
+       }
+short yyexca[] ={
+-1, 1,
+       0, -1,
+       7, 23,
+       18, 23,
+       108, 23,
+       125, 23,
+       -2, 0,
+-1, 19,
+       79, 82,
+       125, 82,
+       -2, 7,
+-1, 24,
+       79, 81,
+       125, 81,
+       -2, 79,
+-1, 26,
+       79, 85,
+       125, 85,
+       -2, 80,
+-1, 32,
+       110, 46,
+       -2, 44,
+-1, 34,
+       110, 38,
+       -2, 36,
+-1, 110,
+       85, 18,
+       86, 18,
+       112, 18,
+       124, 18,
+       -2, 13,
+-1, 281,
+       85, 16,
+       86, 16,
+       112, 16,
+       124, 16,
+       -2, 14,
+-1, 298,
+       85, 17,
+       86, 17,
+       112, 17,
+       124, 17,
+       -2, 15,
+       };
+# define YYNPROD 188
+# define YYLAST 1291
+short yyact[]={
+
+ 212,  27, 263,  10,   9,  27,  46,  10,   9, 210,
+  77,  66,  21,  94, 201,  27,  21,  95, 133,  99,
+  18, 148, 167,  19,   6, 132,  21,  36, 111, 312,
+  14, 311, 157,  27,  14,  10,  27,  36, 272,  41,
+  43,  24,  16, 289,  21,  97,  16,  21,  10,   9,
+   8,  75, 271, 305, 292, 267, 266, 165,  28,  97,
+  92,  74,  14,  40,  42, 288, 138, 284, 113, 203,
+ 245, 160, 155, 298,  16,  14, 203, 134, 208, 103,
+  53, 251,  57,  35,  33, 149, 153,  16, 108, 141,
+ 142, 143, 144, 145, 146, 137,  31, 139, 140,  96,
+  27, 307,  22,  59, 290, 249,  22, 122,  45, 159,
+ 204,  21,  71, 162, 287, 278,  22, 169, 170, 171,
+ 173, 175, 177, 179, 181, 182, 184, 186, 188, 189,
+ 190, 191, 192, 164,  22, 150, 134,  22,  93, 196,
+ 205, 119,  70,  57, 120, 199,  72, 122, 149,  64,
+  96, 281, 193,  39,  17, 158, 301, 124,  39, 202,
+ 125, 195, 126, 300,  49, 277, 202, 252, 276, 198,
+ 207, 275, 154, 236, 109, 237,  49, 238,   4, 239,
+  49, 240, 274, 154, 241,  38, 242,  52, 243, 209,
+  38,  69, 118, 235,   9, 134,  48,  68, 150,  54,
+ 119,  22,  56, 120, 161, 255, 122,  30,  48, 194,
+ 250, 157,  48, 246, 100, 247, 124, 253, 254, 264,
+ 256, 126, 299, 269, 259, 260, 261, 262, 285, 265,
+ 116, 123, 118, 121, 279, 115, 273,  90,  87,  88,
+  89, 232, 112,  73,  65, 283, 251, 163,  96,  80,
+  98, 280,  78, 103,  26,  47, 282, 101,  51, 213,
+ 250, 270,  79, 286,  98,  20, 197,  60,  90,  87,
+  88,  89, 232, 114,  34, 293, 294, 264, 296, 295,
+  80, 119,  26,  78, 120,  26,  32, 122,   7, 116,
+ 123, 118, 121,  79,  67, 156, 226,  29, 110, 107,
+ 302, 119, 308, 106, 120, 135, 264, 122, 309,  90,
+  87,  88,  89,  86,  50, 223,  25, 222,  90,  87,
+  88,  89, 232, 104,  61,  44, 206, 102,  91,  55,
+  80,  58, 168,  78, 166, 105,  63,  62,  37,  82,
+  81,   3,  84,  79, 111, 257, 223, 227, 222, 231,
+ 220, 221, 228, 229, 230, 234, 233,  83, 119, 224,
+   2, 120, 152,  85, 122,  11,  12,   5,  23,  13,
+  82,  81, 118,  84, 124, 111, 211,  15, 227, 219,
+ 231, 220, 221, 228, 229, 230, 234, 233,  83, 217,
+ 224, 218, 118, 121, 216, 214, 223, 215, 222,   1,
+   0,   0,   0, 119,   0,   0, 120,   0,   0, 122,
+   0,  82,  81,   0,  84,   0,   0,   0, 131, 124,
+  82,  81, 125,  84, 126, 111,   0,   0, 227,  83,
+ 231, 220, 221, 228, 229, 230, 234, 233,  83, 119,
+ 224, 129, 120, 127, 128, 122,   0, 116, 123, 118,
+ 121,   0,   0,   0, 131, 124,   0,   0, 125,   0,
+ 126,  90,  87,  88,  89,  86,   0,   0,   0, 119,
+ 117,   0, 120,  80,   0, 122,  78, 129,   0, 127,
+ 128,   0,   0,   0,   0,   0,  79,   0,   0,   0,
+ 225, 130, 116, 123, 118, 121,   0,  90,  87,  88,
+  89,  86,   0,   0,   0,   0, 117,   0,   0,  80,
+   0,   0,  78,   0,   0,   0, 291,   0,   0,   0,
+ 119, 225,  79, 120,   0,   0, 122, 130, 116, 123,
+ 118, 121,  90,  87,  88,  89,  86,   0,   0,   0,
+   0,   0,   0,  10,  80,   0,   0,  78,   0,   0,
+   0,   0, 258,   0,   0,   0,   0,  79, 116, 123,
+ 118, 121,   0,  82,  81,   0,  84,   0,   0,   0,
+  14, 225,  90,  87,  88,  89,  86,   0,   0,   0,
+   0,  83,  16,   0,  80,   0,   0,  78,   0,   0,
+   0,  90,  87,  88,  89,  86, 187,  79,   0,  82,
+  81,   0,  84,  80,   0,   0,  78,   0,   0, 116,
+   0, 118, 121,   0,   0, 185,  79,  83,   0, 268,
+   0,  90,  87,  88,  89,  86,  90,  87,  88,  89,
+  86,   0,   0,  80,  82,  81,  78,  84,  80, 136,
+   0,  78,   0,   0,   0, 183,  79,   0,   0,   0,
+ 180,  79,  83,   0,  90,  87,  88,  89,  86,   0,
+   0,  90,  87,  88,  89,  86,  80,   0,   0,  78,
+   0,   0,   0,  80,  82,  81,  78,  84, 178,  79,
+   0,   0,   0,   0,   0, 176,  79,   0,   0,   0,
+   0,   0,  83,  82,  81,   0,  84,  90,  87,  88,
+  89,  86,  90,  87,  88,  89,  86,   0,   0,  80,
+   0,  83,  78,   0,  80,   0,   0,  78,   0,   0,
+   0, 174,  79,  82,  81,   0,  84,  79,  82,  81,
+   0,  84,   0,   0,   0,   0,  90,  87,  88,  89,
+  86,  83,   0,   0,   0,   0,  83,   0,  80,   0,
+   0,  78,   0,   0,   0,   0,  82,  81,   0,  84,
+ 172,  79,   0,  82,  81,   0,  84,  90,  87,  88,
+  89,  86,   0,   0,  83,   0,   0,   0,   0,  80,
+   0,  83,  78,   0,   0,   0,  90,  87,  88,  89,
+  86,   0,  79,   0,   0,   0,   0,   0,  80,  82,
+  81,  78,  84,   0,  82,  81,   0,  84, 151,   0,
+   0,  79,  90,  87,  88,  89,  86,  83,   0,   0,
+   0,   0,  83,   0,  80,   0,   0,  78,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,  79,  82,  81,
+   0,  84,   0,   0,   0, 119,   0,   0, 120,   0,
+   0, 122,   0,   0,   0,   0,  83,   0,   0,   0,
+ 131, 124,   0,   0, 125,   0, 126,   0,   0,  82,
+  81,   0,  84,   0,  76,   0,   0,   0, 119,   0,
+   0, 120,   0, 129, 122, 127, 128,  83,  82,  81,
+   0,  84,   0, 131, 124,   0,   0, 125,   0, 126,
+   0,   0,   0,   0,   0,   0,  83,   0,   0,   0,
+   0,   0, 117,   0,  82,  81, 129, 147, 127, 128,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,  83, 130, 116, 123, 118, 121, 119,   0,
+   0, 120, 310,   0, 122, 117,   0,   0,   0,   0,
+   0,   0,   0, 131, 124,   0,   0, 125,   0, 126,
+   0,   0,   0,   0,   0,   0, 130, 116, 123, 118,
+ 121, 119,   0,   0, 120, 306, 129, 122, 127, 128,
+   0,   0, 119,   0,   0, 120, 131, 124, 122,   0,
+ 125,   0, 126,   0,   0,   0,   0, 131, 124,   0,
+   0, 125,   0, 126,   0, 117,   0,   0,   0, 129,
+   0, 127, 128,   0,   0,   0,   0,   0,   0,   0,
+ 129,   0, 127, 128,   0,   0, 130, 116, 123, 118,
+ 121,   0,   0,   0,   0, 304,   0, 119, 117,   0,
+ 120,   0,   0, 122,   0,   0,   0,   0,   0, 117,
+   0,   0, 131, 124,   0,   0, 125,   0, 126, 130,
+ 116, 123, 118, 121,   0,   0,   0,   0, 303,   0,
+ 130, 116, 123, 118, 121, 129, 297, 127, 128, 200,
+ 119,   0,   0, 120,   0,   0, 122,   0,   0,   0,
+   0,   0,   0,   0, 119, 131, 124, 120,   0, 125,
+ 122, 126,   0,   0, 117,   0,   0,   0,   0, 131,
+ 124,   0,   0, 125,   0, 126,   0,   0, 129,   0,
+ 127, 128,   0,   0,   0, 130, 116, 123, 118, 121,
+   0,   0, 129, 244, 127, 128, 119,   0,   0, 120,
+   0,   0, 122,   0,   0, 248,   0, 117,   0,   0,
+   0, 131, 124,   0,   0, 125,   0, 126,   0,   0,
+   0, 117,   0,   0,   0,   0,   0,   0, 130, 116,
+ 123, 118, 121,   0, 129, 119, 127, 128, 120,   0,
+   0, 122, 130, 116, 123, 118, 121,   0,   0, 119,
+ 131, 124, 120,   0, 125, 122, 126,   0, 119,   0,
+   0, 120,   0, 117, 122, 124,   0,   0, 125,   0,
+ 126,   0,   0, 129, 124, 127, 128, 125,   0, 126,
+   0,   0,   0,   0, 130, 116, 123, 118, 121, 127,
+   0,   0,   0,   0,   0,   0, 129,   0, 127, 128,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,   0, 130, 116, 123, 118, 121,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0, 116, 123,
+ 118, 121,   0,   0,   0,   0,   0, 116, 123, 118,
+ 121 };
+short yypact[]={
+
+-1000, -78,-1000,-1000,-1000,  29,-1000, -50, 108,-1000,
+ 122,-1000,-1000, -14, 279, -26, 267,-1000, -42,  77,
+-1000,  93,  93,  -1, 100, 231,-1000,  79,-1000, -50,
+ 114, -50,-1000, 260,-1000,-1000,-1000,-1000,  40, 167,
+ 100,  77,  88,  82,  33,-1000,-1000,-1000,  37, 166,
+ 764,-1000,-1000,-1000,-1000, -65,-1000,  -6, 135,-1000,
+ 230,  -2,-1000, -82,-1000,-1000, 165, 783,-1000,-1000,
+-1000, 266,-1000,-1000, 158,1163, 529, -10, 783, 783,
+ 783, 783, 783, 809, 458, 699,  75,-1000,-1000,-1000,
+-1000, -39, -50, 132,-1000,  77, 104,-1000,-1000, -40,
+ 260,-1000,-1000,  77,-1000,-1000,-1000,-1000,   8, -68,
+-1000,-1000,-1000,1163,-1000,-1000, 783, 783, 733, 694,
+ 658, 651, 623, 783, 618, 588, 569, 783, 783, 783,
+ 783, 783, 130,-1000,1163, 529,-1000,-1000, 783, 259,
+-1000, -10, -10, -10, -10, -10, -10, 458,  36, 970,
+  51,-1000,  31,1163,-1000,-1000,-1000,-1000,-1000,-1000,
+-1000,-1000,-1000, -47,-1000,-1000,-1000, 265, -37, 289,
+1163,-1000, 783,  89, 783,  89, 783, 269, 783,-1000,
+ 783, 508, 457, 783, 188, 783, 346, 783, 129,1177,
+1082,1163,1163, -41, 529, 130,1068,-1000,  -4, 783,
+-1000, 170,  58,  51, 783,-1000,  -6,-1000,-1000, 234,
+-1000,-1000, 427,-1000, 315, 315, 315, 315, 783, 315,
+ -69, -70, 494, 254,-1000, -73, 315,  74,  63,-1000,
+  60,  57,  64, 783, 200,  26,1163,1163,1163,1163,
+1163,1163,1163,1163, 783,-1000,-1000, -44,-1000, 306,
+ -10, 151,-1000,   5, 170,1163,-1000,-1000,-1000, -49,
+-1000,-1000, -75,  -5,1124,-1000,-1000,-1000,-1000, 391,
+ -71,-1000,-1000,-1000, 783, 783, 783, 783,-1000,1025,
+-1000,-1000, -52,1186,-1000,-1000, 145,  55,-1000,  48,
+ 315,-1000,-1000, 959, 926, -72, 866,-1000,-1000,-1000,
+  -8, 783,-1000,-1000,-1000, 783,-1000,-1000, 833, -94,
+ -96,-1000,-1000 };
+short yypgo[]={
+
+   0, 399,  11, 397, 395, 394, 391, 389, 379, 377,
+ 369, 368,   0,   2,  10,  24, 367,  50, 366, 365,
+  21,  14, 363,  13,  17,  41, 362, 360, 341,  20,
+ 338, 337, 336, 259, 335,  22,   9, 334, 332, 138,
+ 288, 331,  19, 103, 329, 328, 202, 326, 325, 265,
+ 324, 316, 314,  25,  18, 305, 303, 299, 298, 296,
+ 294 };
+short yyr1[]={
+
+   0,   1,   1,  27,  27,  28,  28,  30,  28,  31,
+  32,  32,  35,  35,  37,  37,  38,  38,  38,  34,
+  34,  34,  16,  16,  15,  15,  15,  15,  15,  40,
+  17,  17,  17,  17,  17,  18,  18,   9,   9,  41,
+  41,  43,  43,  19,  19,  10,  10,  44,  44,  46,
+  46,  39,  47,  39,  23,  23,  23,  23,  23,  25,
+  25,  25,  25,  25,  25,  24,  24,  24,  24,  24,
+  24,  24,  11,  48,  48,  48,  29,  50,  29,  51,
+  51,  49,  49,  49,  49,  49,  53,  53,  54,  54,
+  42,  42,  45,  45,  52,  52,  55,  33,  33,  56,
+  57,  58,  36,  36,  36,  36,  36,  36,  36,  36,
+  36,  36,  36,  36,  36,  36,  36,  36,  36,  59,
+  59,  59,   7,   4,   3,   5,   6,   8,  60,   2,
+  13,  13,  26,  26,  12,  12,  12,  12,  12,  12,
+  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
+  12,  12,  12,  12,  12,  12,  12,  12,  12,  14,
+  14,  14,  14,  14,  14,  14,  14,  14,  14,  14,
+  14,  14,  14,  14,  14,  14,  14,  14,  20,  21,
+  21,  21,  21,  21,  21,  21,  22,  22 };
+short yyr2[]={
+
+   0,   2,   0,   1,   1,   2,   3,   0,   4,   2,
+   2,   0,   2,   0,   3,   4,   3,   4,   0,   3,
+   2,   2,   1,   0,   2,   2,   1,   1,   3,   1,
+   1,   2,   3,   1,   1,   5,   2,   1,   2,   1,
+   3,   1,   3,   5,   2,   1,   2,   1,   3,   2,
+   1,   1,   0,   4,   1,   1,   3,   2,   1,   2,
+   3,   3,   4,   1,   3,   2,   3,   3,   4,   3,
+   3,   2,   2,   1,   3,   1,   1,   0,   4,   1,
+   1,   1,   1,   3,   6,   1,   1,   3,   1,   4,
+   0,   1,   0,   1,   0,   1,   1,   1,   1,   4,
+   3,   1,   2,   1,   2,   2,   2,   7,   4,   2,
+   2,   2,   2,   3,   3,   1,   2,   2,   2,   2,
+   3,   2,   1,   4,   3,   4,   6,   4,   0,   2,
+   1,   0,   1,   3,   3,   3,   3,   3,   3,   3,
+   3,   3,   3,   3,   3,   3,   3,   4,   4,   4,
+   4,   4,   4,   4,   4,   5,   3,   3,   1,   2,
+   2,   2,   2,   2,   2,   2,   4,   4,   4,   2,
+   3,   3,   1,   1,   1,   1,   1,   3,   2,   0,
+   2,   5,   2,   3,   4,   3,   2,   2 };
+short yychk[]={
+
+-1000,  -1, -27, -28, 256, -16, -15, -40, -17,  86,
+  85, -19, -18, -10, 112,  -9, 124, 125, -29, -24,
+ -49,  18, 108, -11, -25, -51, 256,   7, -17, -40,
+  85, 110,   7, 110,   7, 125,  79, -30, 108,  76,
+ -25, -24, -25, -24, -48, 109,   7, 256, 108,  76,
+ -52,  27, 108, -17,  85, -44, -46, -17, -41, -43,
+   7, -50, -31, -32, 109,  77,  -2, -60, 109, 109,
+ 109,  79, 109,  77,  -2, -12, 110, -14,  18,  28,
+  15, 106, 105, 123, 108, -22,   7,   4,   5,   6,
+   3, -45, 125, -39, -23, -24, -25,  51, 256, -42,
+  79,  27, -49, -24, -33, -34, -56, -57, -15, 256,
+ -58, 110,  77, -12,   7,  77, 101,  79, 103,  12,
+  15, 104,  18, 102,  28,  31,  33,  52,  53,  50,
+ 100,  27, -53, -54, -12, -55, 110, 105,  76, 107,
+ 108, -14, -14, -14, -14, -14, -14, 108, -20, -12,
+ -17, 109, -26, -12, 108, 111, -46,  79,  51,  -2,
+ 111, -43,  -2, -39, 125, 125, -37, -35, -38, -12,
+ -12, -12,  27, -12,  27, -12,  27, -12,  27, -12,
+  27, -12, -12,  27, -12,  27, -12,  27, -12, -12,
+ -12, -12, -12, -42,  79, -53, -12,   7, -20, 109,
+ 109, -21, 108,  18,  79, 109, -47,  -2, 125, -35,
+ -36, 111, -12, -33,  -4,  -3,  -5,  -7,  -6,  -8,
+ 116, 117,  83,  81, 125, 256, -59, 113, 118, 119,
+ 120, 115,   7, 122, 121, -15, -12, -12, -12, -12,
+ -12, -12, -12, -12,  51, 111, -54, -42,  77, 109,
+ -14,  76, 109, -21, -21, -12, -23, 111, 125, -36,
+ -36, -36, -36, -13, -12, -36, 125, 125, 125, -12,
+   7, 125, 111, -36, 108, 108, 108, 108,  51, -12,
+  51, 125, -29, -12, 111,  77,  -2, 109, 114, 118,
+ 109, 125, 125, -12, -12, -13, -12,  51, 125,  77,
+ 108, 108, -36, 109, 109, 125, 109, 109, -12, -13,
+ 109, 125, 125 };
+short yydef[]={
+
+   2,  -2,   1,   3,   4,   0,  22,  26,  27,  29,
+  30,  33,  34,   0,  45,   0,  37,   5,   0,  -2,
+  76,   0,   0,   0,  -2,  94,  -2,  63,  24,  25,
+  31,   0,  -2,   0,  -2,   6,  77,  11,   0, 128,
+  59,  65,   0,   0,   0,  71,  73,  75,   0, 128,
+   0,  95,  72,  28,  32,  92,  47,  50,  90,  39,
+  41,   0,   8,   0,  66,  67,   0,   0,  64,  69,
+  70,   0,  60,  61,   0,  83,   0, 158,   0,   0,
+   0,   0,   0,   0,   0,   0, 172, 173, 174, 175,
+ 176,   0,  93,  49,  51,  54,  55, 128,  58,   0,
+  91, 128,  78,  82,   9,  10,  97,  98,   0,   0,
+  -2, 101,  68, 129,  74,  62,   0,   0,   0,   0,
+   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+   0,   0,  90,  86,  88,   0,  96, 159,   0,   0,
+ 187, 160, 161, 162, 163, 164, 165,   0,   0,   0,
+ 179, 169,   0, 132, 186,  43,  48,  52, 128,  57,
+  35,  40,  42,   0,  20,  21,  13,   0,   0, 134,
+ 135, 136,   0, 137,   0, 138,   0, 139,   0, 140,
+   0, 141, 142,   0, 143,   0, 144,   0, 145, 146,
+   0, 156, 157,   0,  91,  90,   0, 171,   0,   0,
+ 177, 178, 179, 179,   0, 170,   0,  56,  19,   0,
+  12, 100,   0, 103,   0,   0,   0,   0, 131,   0,
+   0,   0,   0,   0, 115,   0,   0,   0,   0, 122,
+   0,   0, 172,   0,   0,   0, 148, 149, 150, 151,
+ 147, 152, 153, 154,   0,  84,  87,   0, 168, 167,
+ 166, 128, 180,   0, 182, 133,  53,  99, 102, 104,
+ 105, 106,   0,   0, 130, 109, 110, 111, 112,   0,
+   0, 116, 117, 118,   0,   0, 131,   0, 119,   0,
+ 121,  -2,   0, 155,  89, 183,   0, 185, 124,   0,
+   0, 113, 114,   0,   0,   0,   0, 120,  -2, 184,
+   0,   0, 108, 123, 125, 131, 127, 181,   0,   0,
+   0, 126, 107 };
+#pragma ifdef __GNUC__
+#pragma pragma GCC diagnostic ignored "-Wunused-label"
+#pragma endif
+#if defined(DOSCCS) && !defined(lint)
+static char yaccpar_sccsid[] = "@(#)yaccpar    4.1     (Berkeley)      2/11/83";
+#endif
+
+#
+# define YYFLAG -1000
+# define YYERROR goto yyerrlab
+# define YYACCEPT return(0)
+# define YYABORT return(1)
+
+/*     parser for yacc output  */
+
+#ifdef YYDEBUG
+int yydebug = 0; /* 1 for debugging */
+#endif
+YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
+int yychar = -1; /* current input token number */
+int yynerrs = 0;  /* number of errors */
+short yyerrflag = 0;  /* error recovery flag */
+
+int yyparse() {
+
+       short yys[YYMAXDEPTH];
+       short yyj, yym;
+       register YYSTYPE *yypvt;
+       register short yystate, *yyps, yyn;
+       register YYSTYPE *yypv;
+       register short *yyxi;
+
+       yystate = 0;
+       yychar = -1;
+       yynerrs = 0;
+       yyerrflag = 0;
+       yyps= &yys[-1];
+       yypv= &yyv[-1];
+
+ yystack:    /* put a state and value onto the stack */
+
+#ifdef YYDEBUG
+       if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
+#endif
+               if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
+               *yyps = yystate;
+               ++yypv;
+               *yypv = yyval;
+
+ yynewstate:
+
+       yyn = yypact[yystate];
+
+       if( yyn<= YYFLAG ) goto yydefault; /* simple state */
+
+       if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
+       if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;
+
+       if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
+               yychar = -1;
+               yyval = yylval;
+               yystate = yyn;
+               if( yyerrflag > 0 ) --yyerrflag;
+               goto yystack;
+               }
+
+ yydefault:
+       /* default state action */
+
+       if( (yyn=yydef[yystate]) == -2 ) {
+               if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
+               /* look through exception table */
+
+               for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */
+
+               while( *(yyxi+=2) >= 0 ){
+                       if( *yyxi == yychar ) break;
+                       }
+               if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
+               }
+
+       if( yyn == 0 ){ /* error */
+               /* error ... attempt to resume parsing */
+
+               switch( yyerrflag ){
+
+               case 0:   /* brand new error */
+
+                       yyerror( "syntax error" );
+               yyerrlab:
+                       ++yynerrs;
+
+               case 1:
+               case 2: /* incompletely recovered error ... try again */
+
+                       yyerrflag = 3;
+
+                       /* find a state where "error" is a legal shift action */
+
+                       while ( yyps >= yys ) {
+                          yyn = yypact[*yyps] + YYERRCODE;
+                          if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
+                             yystate = yyact[yyn];  /* simulate a shift of "error" */
+                             goto yystack;
+                             }
+                          yyn = yypact[*yyps];
+
+                          /* the current yyps has no shift onn "error", pop stack */
+
+#ifdef YYDEBUG
+                          if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
+#endif
+                          --yyps;
+                          --yypv;
+                          }
+
+                       /* there is no state on the stack with an error shift ... abort */
+
+       yyabort:
+                       return(1);
+
+
+               case 3:  /* no shift yet; clobber input char */
+
+#ifdef YYDEBUG
+                       if( yydebug ) printf( "error recovery discards char %d\n", yychar );
+#endif
+
+                       if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
+                       yychar = -1;
+                       goto yynewstate;   /* try again in the same state */
+
+                       }
+
+               }
+
+       /* reduction by production yyn */
+
+#ifdef YYDEBUG
+               if( yydebug ) printf("reduce %d\n",yyn);
+#endif
+               yyps -= yyr2[yyn];
+               yypvt = yypv;
+               yypv -= yyr2[yyn];
+               yyval = yypv[1];
+               yym=yyn;
+                       /* consult goto table to find next state */
+               yyn = yyr1[yyn];
+               yyj = yypgo[yyn] + *yyps + 1;
+               if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
+               switch(yym){
+                       
+case 2:
+# line 175 "cgram.y"
+ftnend(); break;
+case 3:
+# line 178 "cgram.y"
+{ curclass = SNULL;  blevel = 0; } break;
+case 4:
+# line 180 "cgram.y"
+{ curclass = SNULL;  blevel = 0; } break;
+case 5:
+# line 184 "cgram.y"
+{  yypvt[-1].nodep->in.op = FREE; } break;
+case 6:
+# line 186 "cgram.y"
+{  yypvt[-2].nodep->in.op = FREE; } break;
+case 7:
+# line 187 "cgram.y"
+{
+                               defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass==STATIC?STATIC:EXTDEF );
+#ifndef LINT
+                               pfstab(stab[yypvt[-0].nodep->tn.rval].sname);
+#endif
+                               } break;
+case 8:
+# line 193 "cgram.y"
+{  
+                           if( blevel ) cerror( "function level error" );
+                           if( reached ) retstat |= NRETVAL; 
+                           yypvt[-3].nodep->in.op = FREE;
+                           ftnend();
+                           } break;
+case 11:
+# line 204 "cgram.y"
+{  blevel = 1; } break;
+case 13:
+# line 209 "cgram.y"
+{  bccode();
+                           locctr(PROG);
+                           } break;
+case 14:
+# line 215 "cgram.y"
+{  yypvt[-1].nodep->in.op = FREE; 
+#ifndef LINT
+                           plcstab(blevel);
+#endif
+                           } break;
+case 15:
+# line 221 "cgram.y"
+{  yypvt[-2].nodep->in.op = FREE; 
+#ifndef LINT
+                           plcstab(blevel);
+#endif
+                           } break;
+case 16:
+# line 229 "cgram.y"
+{  yypvt[-1].nodep->in.op = FREE; } break;
+case 17:
+# line 231 "cgram.y"
+{  yypvt[-2].nodep->in.op = FREE; } break;
+case 19:
+# line 235 "cgram.y"
+{ curclass = SNULL;  yypvt[-2].nodep->in.op = FREE; } break;
+case 20:
+# line 237 "cgram.y"
+{ curclass = SNULL;  yypvt[-1].nodep->in.op = FREE; } break;
+case 21:
+# line 239 "cgram.y"
+{  curclass = SNULL; } break;
+case 23:
+# line 243 "cgram.y"
+{  yyval.nodep = mkty(INT,0,INT);  curclass = SNULL; } break;
+case 24:
+# line 246 "cgram.y"
+{  yyval.nodep = yypvt[-0].nodep; } break;
+case 26:
+# line 249 "cgram.y"
+{  yyval.nodep = mkty(INT,0,INT); } break;
+case 27:
+# line 251 "cgram.y"
+{ curclass = SNULL ; } break;
+case 28:
+# line 253 "cgram.y"
+{  yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF );
+                           yypvt[-0].nodep->in.op = FREE;
+                           } break;
+case 29:
+# line 260 "cgram.y"
+{  curclass = yypvt[-0].intval; } break;
+case 31:
+# line 265 "cgram.y"
+{  yypvt[-1].nodep->in.type = types( yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type, UNDEF );
+                           yypvt[-0].nodep->in.op = FREE;
+                           } break;
+case 32:
+# line 269 "cgram.y"
+{  yypvt[-2].nodep->in.type = types( yypvt[-2].nodep->in.type, yypvt[-1].nodep->in.type, yypvt[-0].nodep->in.type );
+                           yypvt[-1].nodep->in.op = yypvt[-0].nodep->in.op = FREE;
+                           } break;
+case 35:
+# line 277 "cgram.y"
+{ yyval.nodep = dclstruct(yypvt[-4].intval); } break;
+case 36:
+# line 279 "cgram.y"
+{  yyval.nodep = rstruct(yypvt[-0].intval,0);  stwart = instruct; } break;
+case 37:
+# line 283 "cgram.y"
+{  yyval.intval = bstruct(-1,0); stwart = SEENAME; } break;
+case 38:
+# line 285 "cgram.y"
+{  yyval.intval = bstruct(yypvt[-0].intval,0); stwart = SEENAME; } break;
+case 41:
+# line 293 "cgram.y"
+{  moedef( yypvt[-0].intval ); } break;
+case 42:
+# line 295 "cgram.y"
+{  strucoff = yypvt[-0].intval;  moedef( yypvt[-2].intval ); } break;
+case 43:
+# line 299 "cgram.y"
+{ yyval.nodep = dclstruct(yypvt[-4].intval);  } break;
+case 44:
+# line 301 "cgram.y"
+{  yyval.nodep = rstruct(yypvt[-0].intval,yypvt[-1].intval); } break;
+case 45:
+# line 305 "cgram.y"
+{  yyval.intval = bstruct(-1,yypvt[-0].intval);  stwart=0; } break;
+case 46:
+# line 307 "cgram.y"
+{  yyval.intval = bstruct(yypvt[-0].intval,yypvt[-1].intval);  stwart=0;  } break;
+case 49:
+# line 315 "cgram.y"
+{ curclass = SNULL;  stwart=0; yypvt[-1].nodep->in.op = FREE; } break;
+case 50:
+# line 317 "cgram.y"
+{  if( curclass != MOU ){
+                               curclass = SNULL;
+                               }
+                           else {
+                               sprintf( fakename, "$%dFAKE", fake++ );
+#ifdef FLEXNAMES
+                               /* No need to hash this, we won't look it up */
+                               defid( tymerge(yypvt[-0].nodep, bdty(NAME,NIL,lookup( savestr(fakename), SMOS ))), curclass );
+#else
+                               defid( tymerge(yypvt[-0].nodep, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass );
+#endif
+                               werror("structure typed union member must be named");
+                               }
+                           stwart = 0;
+                           yypvt[-0].nodep->in.op = FREE;
+                           } break;
+case 51:
+# line 337 "cgram.y"
+{ defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass);  stwart = instruct; } break;
+case 52:
+# line 338 "cgram.y"
+{yyval.nodep=yypvt[-2].nodep;} break;
+case 53:
+# line 339 "cgram.y"
+{ defid( tymerge(yypvt[-4].nodep,yypvt[-0].nodep), curclass);  stwart = instruct; } break;
+case 56:
+# line 345 "cgram.y"
+{  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
+                           if( yypvt[-0].intval<0 || yypvt[-0].intval >= FIELD ){
+                               uerror( "illegal field size" );
+                               yypvt[-0].intval = 1;
+                               }
+                           defid( tymerge(yypvt[-3].nodep,yypvt[-2].nodep), FIELD|yypvt[-0].intval );
+                           yyval.nodep = NIL;
+                           } break;
+case 57:
+# line 355 "cgram.y"
+{  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
+                           falloc( stab, yypvt[-0].intval, -1, yypvt[-2].nodep );  /* alignment or hole */
+                           yyval.nodep = NIL;
+                           } break;
+case 58:
+# line 360 "cgram.y"
+{  yyval.nodep = NIL; } break;
+case 59:
+# line 365 "cgram.y"
+{  umul:
+                               yyval.nodep = bdty( UNARY MUL, yypvt[-0].nodep, 0 ); } break;
+case 60:
+# line 368 "cgram.y"
+{  uftn:
+                               yyval.nodep = bdty( UNARY CALL, yypvt[-2].nodep, 0 );  } break;
+case 61:
+# line 371 "cgram.y"
+{  uary:
+                               yyval.nodep = bdty( LB, yypvt[-2].nodep, 0 );  } break;
+case 62:
+# line 374 "cgram.y"
+{  bary:
+                               if( (int)yypvt[-1].intval <= 0 ) werror( "zero or negative subscript" );
+                               yyval.nodep = bdty( LB, yypvt[-3].nodep, yypvt[-1].intval );  } break;
+case 63:
+# line 378 "cgram.y"
+{  yyval.nodep = bdty( NAME, NIL, yypvt[-0].intval );  } break;
+case 64:
+# line 380 "cgram.y"
+{ yyval.nodep=yypvt[-1].nodep; } break;
+case 65:
+# line 383 "cgram.y"
+{  goto umul; } break;
+case 66:
+# line 385 "cgram.y"
+{  goto uftn; } break;
+case 67:
+# line 387 "cgram.y"
+{  goto uary; } break;
+case 68:
+# line 389 "cgram.y"
+{  goto bary; } break;
+case 69:
+# line 391 "cgram.y"
+{ yyval.nodep = yypvt[-1].nodep; } break;
+case 70:
+# line 393 "cgram.y"
+{
+                               if( blevel!=0 ) uerror("function declaration in bad context");
+                               yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-2].intval), 0 );
+                               stwart = 0;
+                               } break;
+case 71:
+# line 399 "cgram.y"
+{
+                               yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,yypvt[-1].intval), 0 );
+                               stwart = 0;
+                               } break;
+case 72:
+# line 406 "cgram.y"
+{
+                               /* turn off typedefs for argument names */
+                               stwart = SEENAME;
+                               if( stab[yypvt[-1].intval].sclass == SNULL )
+                                   stab[yypvt[-1].intval].stype = FTN;
+                               } break;
+case 73:
+# line 415 "cgram.y"
+{ ftnarg( yypvt[-0].intval );  stwart = SEENAME; } break;
+case 74:
+# line 417 "cgram.y"
+{ ftnarg( yypvt[-0].intval );  stwart = SEENAME; } break;
+case 77:
+# line 423 "cgram.y"
+{yyval.nodep=yypvt[-2].nodep;} break;
+case 79:
+# line 427 "cgram.y"
+{  defid( yypvt[-0].nodep = tymerge(yypvt[-1].nodep,yypvt[-0].nodep), curclass);
+                           beginit(yypvt[-0].nodep->tn.rval);
+                           } break;
+case 81:
+# line 434 "cgram.y"
+{  nidcl( tymerge(yypvt[-1].nodep,yypvt[-0].nodep) ); } break;
+case 82:
+# line 436 "cgram.y"
+{  defid( tymerge(yypvt[-1].nodep,yypvt[-0].nodep), uclass(curclass) );
+                           if( paramno > 0 ){
+                               uerror( "illegal argument" );
+                               paramno = 0;
+                               }
+                       } break;
+case 83:
+# line 444 "cgram.y"
+{  doinit( yypvt[-0].nodep );
+                           endinit(); } break;
+case 84:
+# line 447 "cgram.y"
+{  endinit(); } break;
+case 88:
+# line 457 "cgram.y"
+{  doinit( yypvt[-0].nodep ); } break;
+case 89:
+# line 459 "cgram.y"
+{  irbrace(); } break;
+case 94:
+# line 471 "cgram.y"
+{  werror( "old-fashioned initialization: use =" ); } break;
+case 96:
+# line 476 "cgram.y"
+{  ilbrace(); } break;
+case 99:
+# line 486 "cgram.y"
+{  
+#ifndef LINT
+                           prcstab(blevel);
+#endif
+                           --blevel;
+                           if( blevel == 1 ) blevel = 0;
+                           clearst( blevel );
+                           checkst( blevel );
+                           autooff = *--psavbc;
+                           regvar = *--psavbc;
+                           } break;
+case 100:
+# line 500 "cgram.y"
+{  --blevel;
+                           if( blevel == 1 ) blevel = 0;
+                           clearst( blevel );
+                           checkst( blevel );
+                           autooff = *--psavbc;
+                           regvar = *--psavbc;
+                           } break;
+case 101:
+# line 510 "cgram.y"
+{  if( blevel == 1 ) dclargs();
+                           ++blevel;
+                           if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" );
+                           *psavbc++ = regvar;
+                           *psavbc++ = autooff;
+                           } break;
+case 102:
+# line 519 "cgram.y"
+{ ecomp( yypvt[-1].nodep ); } break;
+case 104:
+# line 522 "cgram.y"
+{ deflab(yypvt[-1].intval);
+                          reached = 1;
+                          } break;
+case 105:
+# line 526 "cgram.y"
+{  if( yypvt[-1].intval != NOLAB ){
+                               deflab( yypvt[-1].intval );
+                               reached = 1;
+                               }
+                           } break;
+case 106:
+# line 532 "cgram.y"
+{  branch(  contlab );
+                           deflab( brklab );
+                           if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1;
+                           else reached = 0;
+                           resetbc(0);
+                           } break;
+case 107:
+# line 539 "cgram.y"
+{  deflab( contlab );
+                           if( flostat & FCONT ) reached = 1;
+                           ecomp( buildtree( CBRANCH, buildtree( NOT, yypvt[-2].nodep, NIL ), bcon( yypvt[-6].intval ) ) );
+                           deflab( brklab );
+                           reached = 1;
+                           resetbc(0);
+                           } break;
+case 108:
+# line 547 "cgram.y"
+{  deflab( contlab );
+                           if( flostat&FCONT ) reached = 1;
+                           if( yypvt[-2].nodep ) ecomp( yypvt[-2].nodep );
+                           branch( yypvt[-3].intval );
+                           deflab( brklab );
+                           if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
+                           else reached = 0;
+                           resetbc(0);
+                           } break;
+case 109:
+# line 557 "cgram.y"
+{  if( reached ) branch( brklab );
+                           deflab( yypvt[-1].intval );
+                          swend();
+                           deflab(brklab);
+                           if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
+                           resetbc(FCONT);
+                           } break;
+case 110:
+# line 565 "cgram.y"
+{  if( brklab == NOLAB ) uerror( "illegal break");
+                           else if(reached) branch( brklab );
+                           flostat |= FBRK;
+                           if( brkflag ) goto rch;
+                           reached = 0;
+                           } break;
+case 111:
+# line 572 "cgram.y"
+{  if( contlab == NOLAB ) uerror( "illegal continue");
+                           else branch( contlab );
+                           flostat |= FCONT;
+                           goto rch;
+                           } break;
+case 112:
+# line 578 "cgram.y"
+{  retstat |= NRETVAL;
+                           branch( retlab );
+                       rch:
+                           if( !reached ) werror( "statement not reached");
+                           reached = 0;
+                           } break;
+case 113:
+# line 585 "cgram.y"
+{  register NODE *temp;
+                           idname = curftn;
+                           temp = buildtree( NAME, NIL, NIL );
+                           if(temp->in.type == TVOID)
+                               uerror("void function %s cannot return value",
+                                       stab[idname].sname);
+                           temp->in.type = DECREF( temp->in.type );
+                           temp = buildtree( RETURN, temp, yypvt[-1].nodep );
+                           /* now, we have the type of the RHS correct */
+                           temp->in.left->in.op = FREE;
+                           temp->in.op = FREE;
+                           ecomp( buildtree( FORCE, temp->in.right, NIL ) );
+                           retstat |= RETVAL;
+                           branch( retlab );
+                           reached = 0;
+                           } break;
+case 114:
+# line 602 "cgram.y"
+{  register NODE *q;
+                           q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
+                           q->tn.rval = idname = yypvt[-1].intval;
+                           defid( q, ULABEL );
+                           stab[idname].suse = -lineno;
+                           branch( stab[idname].offset );
+                           goto rch;
+                           } break;
+case 119:
+# line 616 "cgram.y"
+{  register NODE *q;
+                           q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
+                           q->tn.rval = yypvt[-1].intval;
+                           defid( q, LABEL );
+                           reached = 1;
+                           } break;
+case 120:
+# line 623 "cgram.y"
+{  addcase(yypvt[-1].nodep);
+                           reached = 1;
+                           } break;
+case 121:
+# line 627 "cgram.y"
+{  reached = 1;
+                           adddef();
+                           flostat |= FDEF;
+                           } break;
+case 122:
+# line 633 "cgram.y"
+{  savebc();
+                           if( !reached ) werror( "loop not entered at top");
+                           brklab = getlab();
+                           contlab = getlab();
+                           deflab( yyval.intval = getlab() );
+                           reached = 1;
+                           } break;
+case 123:
+# line 642 "cgram.y"
+{  ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( yyval.intval=getlab()) ) ) ;
+                           reached = 1;
+                           } break;
+case 124:
+# line 647 "cgram.y"
+{  if( reached ) branch( yyval.intval = getlab() );
+                           else yyval.intval = NOLAB;
+                           deflab( yypvt[-2].intval );
+                           reached = 1;
+                           } break;
+case 125:
+# line 655 "cgram.y"
+{  savebc();
+                           if( !reached ) werror( "loop not entered at top");
+                           if( yypvt[-1].nodep->in.op == ICON && yypvt[-1].nodep->tn.lval != 0 ) flostat = FLOOP;
+                           deflab( contlab = getlab() );
+                           reached = 1;
+                           brklab = getlab();
+                           if( flostat == FLOOP ) tfree( yypvt[-1].nodep );
+                           else ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) );
+                           } break;
+case 126:
+# line 666 "cgram.y"
+{  if( yypvt[-3].nodep ) ecomp( yypvt[-3].nodep );
+                           else if( !reached ) werror( "loop not entered at top");
+                           savebc();
+                           contlab = getlab();
+                           brklab = getlab();
+                           deflab( yyval.intval = getlab() );
+                           reached = 1;
+                           if( yypvt[-1].nodep ) ecomp( buildtree( CBRANCH, yypvt[-1].nodep, bcon( brklab) ) );
+                           else flostat |= FLOOP;
+                           } break;
+case 127:
+# line 678 "cgram.y"
+{  register NODE *q;
+                       
+                           savebc();
+                           brklab = getlab();
+                           q = yypvt[-1].nodep;
+                           switch( q->in.type ) {
+                           case CHAR:  case UCHAR:
+                           case SHORT: case USHORT:
+                           case INT:   case UNSIGNED:
+                           case MOE:   case ENUMTY:
+                                   break;
+                           default:
+                               werror("switch expression not type int");
+                               q = makety( q, INT, q->fn.cdim, q->fn.csiz );
+                               }
+                           ecomp( buildtree( FORCE, q, NIL ) );
+                           branch( yyval.intval = getlab() );
+                           swstart();
+                           reached = 0;
+                           } break;
+case 128:
+# line 700 "cgram.y"
+{ yyval.intval=instruct; stwart=instruct=0; } break;
+case 129:
+# line 702 "cgram.y"
+{  yyval.intval = icons( yypvt[-0].nodep );  instruct=yypvt[-1].intval; } break;
+case 131:
+# line 706 "cgram.y"
+{ yyval.nodep=0; } break;
+case 133:
+# line 711 "cgram.y"
+{  goto bop; } break;
+case 134:
+# line 715 "cgram.y"
+{
+                       preconf:
+                           if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){
+                           precplaint:
+                               if( hflag ) werror( "precedence confusion possible: parenthesize!" );
+                               }
+                       bop:
+                           yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-2].nodep, yypvt[-0].nodep );
+                           } break;
+case 135:
+# line 725 "cgram.y"
+{  yypvt[-1].intval = COMOP;
+                           goto bop;
+                           } break;
+case 136:
+# line 729 "cgram.y"
+{  goto bop; } break;
+case 137:
+# line 731 "cgram.y"
+{  if(yychar==SHIFTOP) goto precplaint; else goto bop; } break;
+case 138:
+# line 733 "cgram.y"
+{  if(yychar==SHIFTOP ) goto precplaint; else goto bop; } break;
+case 139:
+# line 735 "cgram.y"
+{  if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; } break;
+case 140:
+# line 737 "cgram.y"
+{  goto bop; } break;
+case 141:
+# line 739 "cgram.y"
+{  goto preconf; } break;
+case 142:
+# line 741 "cgram.y"
+{  if( yychar==RELOP||yychar==EQUOP ) goto preconf;  else goto bop; } break;
+case 143:
+# line 743 "cgram.y"
+{  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break;
+case 144:
+# line 745 "cgram.y"
+{  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; } break;
+case 145:
+# line 747 "cgram.y"
+{  goto bop; } break;
+case 146:
+# line 749 "cgram.y"
+{  goto bop; } break;
+case 147:
+# line 751 "cgram.y"
+{  abop:
+                               yyval.nodep = buildtree( ASG yypvt[-2].intval, yypvt[-3].nodep, yypvt[-0].nodep );
+                               } break;
+case 148:
+# line 755 "cgram.y"
+{  goto abop; } break;
+case 149:
+# line 757 "cgram.y"
+{  goto abop; } break;
+case 150:
+# line 759 "cgram.y"
+{  goto abop; } break;
+case 151:
+# line 761 "cgram.y"
+{  goto abop; } break;
+case 152:
+# line 763 "cgram.y"
+{  goto abop; } break;
+case 153:
+# line 765 "cgram.y"
+{  goto abop; } break;
+case 154:
+# line 767 "cgram.y"
+{  goto abop; } break;
+case 155:
+# line 769 "cgram.y"
+{  yyval.nodep=buildtree(QUEST, yypvt[-4].nodep, buildtree( COLON, yypvt[-2].nodep, yypvt[-0].nodep ) );
+                           } break;
+case 156:
+# line 772 "cgram.y"
+{  werror( "old-fashioned assignment operator" );  goto bop; } break;
+case 157:
+# line 774 "cgram.y"
+{  goto bop; } break;
+case 159:
+# line 778 "cgram.y"
+{  yyval.nodep = buildtree( yypvt[-0].intval, yypvt[-1].nodep, bcon(1) ); } break;
+case 160:
+# line 780 "cgram.y"
+{ ubop:
+                           yyval.nodep = buildtree( UNARY yypvt[-1].intval, yypvt[-0].nodep, NIL );
+                           } break;
+case 161:
+# line 784 "cgram.y"
+{  if( ISFTN(yypvt[-0].nodep->in.type) || ISARY(yypvt[-0].nodep->in.type) ){
+                               werror( "& before array or function: ignored" );
+                               yyval.nodep = yypvt[-0].nodep;
+                               }
+                           else goto ubop;
+                           } break;
+case 162:
+# line 791 "cgram.y"
+{  goto ubop; } break;
+case 163:
+# line 793 "cgram.y"
+{
+                           yyval.nodep = buildtree( yypvt[-1].intval, yypvt[-0].nodep, NIL );
+                           } break;
+case 164:
+# line 797 "cgram.y"
+{  yyval.nodep = buildtree( yypvt[-1].intval==INCR ? ASG PLUS : ASG MINUS,
+                                               yypvt[-0].nodep,
+                                               bcon(1)  );
+                           } break;
+case 165:
+# line 802 "cgram.y"
+{  yyval.nodep = doszof( yypvt[-0].nodep ); } break;
+case 166:
+# line 804 "cgram.y"
+{  yyval.nodep = buildtree( CAST, yypvt[-2].nodep, yypvt[-0].nodep );
+                           yyval.nodep->in.left->in.op = FREE;
+                           yyval.nodep->in.op = FREE;
+                           yyval.nodep = yyval.nodep->in.right;
+                           } break;
+case 167:
+# line 810 "cgram.y"
+{  yyval.nodep = doszof( yypvt[-1].nodep ); } break;
+case 168:
+# line 812 "cgram.y"
+{  yyval.nodep = buildtree( UNARY MUL, buildtree( PLUS, yypvt[-3].nodep, yypvt[-1].nodep ), NIL ); } break;
+case 169:
+# line 814 "cgram.y"
+{  yyval.nodep=buildtree(UNARY CALL,yypvt[-1].nodep,NIL); } break;
+case 170:
+# line 816 "cgram.y"
+{  yyval.nodep=buildtree(CALL,yypvt[-2].nodep,yypvt[-1].nodep); } break;
+case 171:
+# line 818 "cgram.y"
+{  if( yypvt[-1].intval == DOT ){
+                               if( notlval( yypvt[-2].nodep ) )uerror("structure reference must be addressable");
+                               yypvt[-2].nodep = buildtree( UNARY AND, yypvt[-2].nodep, NIL );
+                               }
+                           idname = yypvt[-0].intval;
+                           yyval.nodep = buildtree( STREF, yypvt[-2].nodep, buildtree( NAME, NIL, NIL ) );
+                           } break;
+case 172:
+# line 826 "cgram.y"
+{  idname = yypvt[-0].intval;
+                           /* recognize identifiers in initializations */
+                           if( blevel==0 && stab[idname].stype == UNDEF ) {
+                               register NODE *q;
+#ifndef FLEXNAMES
+                               werror( "undeclared initializer name %.8s", stab[idname].sname );
+#else
+                               werror( "undeclared initializer name %s", stab[idname].sname );
+#endif
+                               q = block( FREE, NIL, NIL, INT, 0, INT );
+                               q->tn.rval = idname;
+                               defid( q, EXTERN );
+                               }
+                           yyval.nodep=buildtree(NAME,NIL,NIL);
+                           stab[yypvt[-0].intval].suse = -lineno;
+                       } break;
+case 173:
+# line 843 "cgram.y"
+{  yyval.nodep=bcon(0);
+                           yyval.nodep->tn.lval = lastcon;
+                           yyval.nodep->tn.rval = NONAME;
+                           if( yypvt[-0].intval ) yyval.nodep->fn.csiz = yyval.nodep->in.type = ctype(LONG);
+                           } break;
+case 174:
+# line 849 "cgram.y"
+{  yyval.nodep=buildtree(FCON,NIL,NIL);
+                           yyval.nodep->fpn.fval = fcon;
+                           } break;
+case 175:
+# line 853 "cgram.y"
+{  yyval.nodep=buildtree(DCON,NIL,NIL);
+                           yyval.nodep->dpn.dval = dcon;
+                           } break;
+case 176:
+# line 857 "cgram.y"
+{  yyval.nodep = getstr(); /* get string contents */ } break;
+case 177:
+# line 859 "cgram.y"
+{ yyval.nodep=yypvt[-1].nodep; } break;
+case 178:
+# line 863 "cgram.y"
+{
+                       yyval.nodep = tymerge( yypvt[-1].nodep, yypvt[-0].nodep );
+                       yyval.nodep->in.op = NAME;
+                       yypvt[-1].nodep->in.op = FREE;
+                       } break;
+case 179:
+# line 871 "cgram.y"
+{ yyval.nodep = bdty( NAME, NIL, -1 ); } break;
+case 180:
+# line 873 "cgram.y"
+{ yyval.nodep = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); } break;
+case 181:
+# line 875 "cgram.y"
+{  yyval.nodep = bdty( UNARY CALL, yypvt[-3].nodep, 0 ); } break;
+case 182:
+# line 877 "cgram.y"
+{  goto umul; } break;
+case 183:
+# line 879 "cgram.y"
+{  goto uary; } break;
+case 184:
+# line 881 "cgram.y"
+{  goto bary;  } break;
+case 185:
+# line 883 "cgram.y"
+{ yyval.nodep = yypvt[-1].nodep; } break;
+case 186:
+# line 887 "cgram.y"
+{  if( stab[yypvt[-1].intval].stype == UNDEF ){
+                               register NODE *q;
+                               q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
+                               q->tn.rval = yypvt[-1].intval;
+                               defid( q, EXTERN );
+                               }
+                           idname = yypvt[-1].intval;
+                           yyval.nodep=buildtree(NAME,NIL,NIL);
+                           stab[idname].suse = -lineno;
+                       } break;
+               }
+               goto yystack;  /* stack new state and value */
+
+       }
diff --git a/lib/pcc/cgram.y b/lib/pcc/cgram.y
new file mode 100644 (file)
index 0000000..25c40a0
--- /dev/null
@@ -0,0 +1,1044 @@
+%term  TOKENS  0
+%term  ERROR   1       /* an error node */
+%term  FREE    2       /* an unused node */
+%term  STRING  3       /* a string constant */
+%term  ICON    4       /* an integer constant */
+%term  FCON    5       /* a floating point constant */
+%term  DCON    6       /* a double precision f.p. constant */
+%term  NAME    7       /* an identifier */
+%term  REG             8       /* a register */
+%term  OREG    9       /* register and offset */
+%term  CCODES  10      /* condition codes */
+%term  FLD             11      /* a bit field */
+%term  PLUS    12      /* + */
+%term  PLUSEQ  13      /* += */
+%term  UPLUS   14      /* unary + (for completeness) */
+%term  MINUS   15      /* - */
+%term  MINUSEQ 16      /* -= */
+%term  UMINUS  17      /* unary - */
+%term  MUL             18      /* * */
+%term  MULEQ   19      /* *= */
+%term  DIV             21      /* / */
+%term  DIVEQ   22      /* /= */
+%term  MOD             23      /* % */
+%term  MODEQ   24      /* %= */
+%term  INCR    25      /* ++ */
+%term  DECR    26      /* -- */
+%term  ASSIGN  27      /* = (these last 3 are stretching it) */
+%term  AND             28      /* & */
+%term  ANDEQ   29      /* &= */
+%term  OR              31      /* | */
+%term  OREQ    32      /* |= */
+%term  ER              33      /* ^ */
+%term  EREQ    34      /* ^= */
+%term  LS              35      /* << */
+%term  LSEQ    36      /* <<= */
+%term  RS              37      /* >> */
+%term  RSEQ    38      /* >>= */
+%term  COMPL   39      /* ~ */
+%term  EQ              40      /* == */
+%term  NE              41      /* != */
+%term  LE              42      /* <= */
+%term  LT              43      /* < */
+%term  GE              44      /* >= */
+%term  GT              45      /* > */
+%term  ULE             46      /* unsigned <= */
+%term  ULT             47      /* unsigned < */
+%term  UGE             48      /* unsigned >= */
+%term  UGT             49      /* unsigned > */
+%term  QUEST   50      /* ? (for conditional expressions) */
+%term  COLON   51      /* : (for conditional expressions) */
+%term  ANDAND  52      /* && */
+%term  OROR    53      /* || */
+%term  NOT             54      /* ! */
+%term  CALL    55      /* call by value */
+%term  UCALL   57      /* call with no arguments */
+%term  FORTCALL        58      /* call by reference? */
+%term  UFORTCALL       60      /* ??? */
+%term  INLINE  61      /* inline function */
+%term  UINLINE 63      /* inline with no arguments */
+%term  DEREF   20      /* * */
+%term  ADDROF  30      /* & */
+%term  DOT             64      /* . */
+%term  STREF   65      /* -> */
+%term  STASG   66      /* structure assignment */
+%term  STARG   67      /* an argument of type structure */
+%term  STCALL  68      /* a function of type structure */
+%term  USTCALL 70      /* unary structure function */
+%term  SCONV   71      /* scalar conversion */
+%term  PCONV   72      /* pointer conversion */
+%term  PMCONV  73      /* pointer multiply conversion */
+%term  PVCONV  74      /* pointer divide conversion */
+%term  CAST    75      /* redundant? */
+%term  LB              76      /* [ */
+%term  RB              77      /* ] */
+%term  COMOP   78      /* , (in expressions) */
+%term  CM              79      /* , (in argument lists) */
+%term  FORCE   80      /* result of last expression goes in r0 */
+%term  GOTO    81      /* unconditional goto */
+%term  CBRANCH 82      /* goto label if !test */
+%term  RETURN  83      /* return from function */
+%term  INIT    84      /* initialized data */
+%term  TYPE    85      /* a type */
+%term  CLASS   86      /* a storage class */
+%term  MAXOP   86      /* highest numbered PCC op */
+%term  LOCALTOKENS     100
+%term  ASOP    100     /* assignment ops */
+%term  RELOP   101     /* <=, <, >=, > */
+%term  EQUOP   102     /* ==, != */
+%term  DIVOP   103     /* /, % */
+%term  SHIFTOP 104     /* <<, >> */
+%term  INCOP   105     /* ++, -- */
+%term  UNOP    106     /* !, ~ */
+%term  STROP   107     /* ., -> */
+%term  LP              108     /* ( */
+%term  RP              109     /* ) */
+%term  LC              110     /* { */
+%term  RC              111     /* } */
+%term  STRUCT  112
+%term  IF              113
+%term  ELSE    114
+%term  SWITCH  115
+%term  BREAK   116
+%term  CONTINUE        117
+%term  WHILE   118
+%term  DO              119
+%term  FOR             120
+%term  DEFAULT 121
+%term  CASE    122
+%term  SIZEOF  123
+%term  ENUM    124
+%term  SM              125
+/*     cgram.y 4.4     85/08/22        */
+
+/*
+ * Grammar for the C compiler.
+ *
+ * This grammar requires the definitions of terminals in the file 'pcctokens'.
+ * (YACC doesn't have an 'include' mechanism, unfortunately.)
+ */
+
+
+/* at last count, there were 7 shift/reduce, 1 reduce/reduce conflicts
+/* these involved:
+       if/else
+       recognizing functions in various contexts, including declarations
+       error recovery
+       */
+
+%left CM
+%right ASOP ASSIGN
+%right QUEST COLON
+%left OROR
+%left ANDAND
+%left OR
+%left ER
+%left AND
+%left EQUOP
+%left RELOP
+%left SHIFTOP
+%left PLUS MINUS
+%left MUL DIVOP
+%right UNOP
+%right INCOP SIZEOF
+%left LB LP STROP
+%{
+# include "pass1.h"
+%}
+
+       /* define types */
+%start ext_def_list
+
+%type <intval> con_e ifelprefix ifprefix whprefix forprefix doprefix switchpart
+               enum_head str_head name_lp
+%type <nodep> e .e term attributes oattributes type enum_dcl struct_dcl
+               cast_type null_decl funct_idn declarator fdeclarator nfdeclarator
+               elist
+
+%token <intval> CLASS NAME STRUCT RELOP CM DIVOP PLUS MINUS SHIFTOP MUL AND OR ER ANDAND OROR
+               ASSIGN STROP INCOP UNOP ICON
+%token <nodep> TYPE
+
+%%
+
+%{
+       static int fake = 0;
+#ifndef FLEXNAMES
+       static char fakename[NCHNAM+1];
+#else
+       static char fakename[24];
+#endif
+%}
+
+ext_def_list:     ext_def_list external_def
+               |
+                       =ftnend();
+               ;
+external_def:     data_def
+                       ={ curclass = SNULL;  blevel = 0; }
+               |  error
+                       ={ curclass = SNULL;  blevel = 0; }
+               ;
+data_def:
+                  oattributes  SM
+                       ={  $1->in.op = FREE; }
+               |  oattributes init_dcl_list  SM
+                       ={  $1->in.op = FREE; }
+               |  oattributes fdeclarator {
+                               defid( tymerge($1,$2), curclass==STATIC?STATIC:EXTDEF );
+#ifndef LINT
+                               pfstab(stab[$2->tn.rval].sname);
+#endif
+                               }  function_body
+                       ={  
+                           if( blevel ) cerror( "function level error" );
+                           if( reached ) retstat |= NRETVAL; 
+                           $1->in.op = FREE;
+                           ftnend();
+                           }
+               ;
+
+function_body:    arg_dcl_list compoundstmt
+               ;
+arg_dcl_list:     arg_dcl_list declaration
+               |       ={  blevel = 1; }
+               ;
+
+stmt_list:        stmt_list statement
+               |  /* empty */
+                       ={  bccode();
+                           locctr(PROG);
+                           }
+               ;
+
+r_dcl_stat_list        :  dcl_stat_list attributes SM
+                       ={  $2->in.op = FREE; 
+#ifndef LINT
+                           plcstab(blevel);
+#endif
+                           }
+               |  dcl_stat_list attributes init_dcl_list SM
+                       ={  $2->in.op = FREE; 
+#ifndef LINT
+                           plcstab(blevel);
+#endif
+                           }
+               ;
+
+dcl_stat_list  :  dcl_stat_list attributes SM
+                       ={  $2->in.op = FREE; }
+               |  dcl_stat_list attributes init_dcl_list SM
+                       ={  $2->in.op = FREE; }
+               |  /* empty */
+               ;
+declaration:      attributes declarator_list  SM
+                       ={ curclass = SNULL;  $1->in.op = FREE; }
+               |  attributes SM
+                       ={ curclass = SNULL;  $1->in.op = FREE; }
+               |  error  SM
+                       ={  curclass = SNULL; }
+               ;
+oattributes:     attributes
+               |  /* VOID */
+                       ={  $$ = mkty(INT,0,INT);  curclass = SNULL; }
+               ;
+attributes:       class type
+                       ={  $$ = $2; }
+               |  type class
+               |  class
+                       ={  $$ = mkty(INT,0,INT); }
+               |  type
+                       ={ curclass = SNULL ; }
+               |  type class type
+                       ={  $1->in.type = types( $1->in.type, $3->in.type, UNDEF );
+                           $3->in.op = FREE;
+                           }
+               ;
+
+
+class:           CLASS
+                       ={  curclass = $1; }
+               ;
+
+type:             TYPE
+               |  TYPE TYPE
+                       ={  $1->in.type = types( $1->in.type, $2->in.type, UNDEF );
+                           $2->in.op = FREE;
+                           }
+               |  TYPE TYPE TYPE
+                       ={  $1->in.type = types( $1->in.type, $2->in.type, $3->in.type );
+                           $2->in.op = $3->in.op = FREE;
+                           }
+               |  struct_dcl
+               |  enum_dcl
+               ;
+
+enum_dcl:         enum_head LC moe_list optcomma RC
+                       ={ $$ = dclstruct($1); }
+               |  ENUM NAME
+                       ={  $$ = rstruct($2,0);  stwart = instruct; }
+               ;
+
+enum_head:        ENUM
+                       ={  $$ = bstruct(-1,0); stwart = SEENAME; }
+               |  ENUM NAME
+                       ={  $$ = bstruct($2,0); stwart = SEENAME; }
+               ;
+
+moe_list:         moe
+               |  moe_list CM moe
+               ;
+
+moe:              NAME
+                       ={  moedef( $1 ); }
+               |  NAME ASSIGN con_e
+                       ={  strucoff = $3;  moedef( $1 ); }
+               ;
+
+struct_dcl:       str_head LC type_dcl_list optsemi RC
+                       ={ $$ = dclstruct($1);  }
+               |  STRUCT NAME
+                       ={  $$ = rstruct($2,$1); }
+               ;
+
+str_head:         STRUCT
+                       ={  $$ = bstruct(-1,$1);  stwart=0; }
+               |  STRUCT NAME
+                       ={  $$ = bstruct($2,$1);  stwart=0;  }
+               ;
+
+type_dcl_list:    type_declaration
+               |  type_dcl_list SM type_declaration
+               ;
+
+type_declaration:  type declarator_list
+                       ={ curclass = SNULL;  stwart=0; $1->in.op = FREE; }
+               |  type
+                       ={  if( curclass != MOU ){
+                               curclass = SNULL;
+                               }
+                           else {
+                               sprintf( fakename, "$%dFAKE", fake++ );
+#ifdef FLEXNAMES
+                               /* No need to hash this, we won't look it up */
+                               defid( tymerge($1, bdty(NAME,NIL,lookup( savestr(fakename), SMOS ))), curclass );
+#else
+                               defid( tymerge($1, bdty(NAME,NIL,lookup( fakename, SMOS ))), curclass );
+#endif
+                               werror("structure typed union member must be named");
+                               }
+                           stwart = 0;
+                           $1->in.op = FREE;
+                           }
+               ;
+
+
+declarator_list:   declarator
+                       ={ defid( tymerge($<nodep>0,$1), curclass);  stwart = instruct; }
+               |  declarator_list  CM {$<nodep>$=$<nodep>0;}  declarator
+                       ={ defid( tymerge($<nodep>0,$4), curclass);  stwart = instruct; }
+               ;
+declarator:       fdeclarator
+               |  nfdeclarator
+               |  nfdeclarator COLON con_e
+                       %prec CM
+                       ={  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
+                           if( $3<0 || $3 >= FIELD ){
+                               uerror( "illegal field size" );
+                               $3 = 1;
+                               }
+                           defid( tymerge($<nodep>0,$1), FIELD|$3 );
+                           $$ = NIL;
+                           }
+               |  COLON con_e
+                       %prec CM
+                       ={  if( !(instruct&INSTRUCT) ) uerror( "field outside of structure" );
+                           falloc( stab, $2, -1, $<nodep>0 );  /* alignment or hole */
+                           $$ = NIL;
+                           }
+               |  error
+                       ={  $$ = NIL; }
+               ;
+
+               /* int (a)();   is not a function --- sorry! */
+nfdeclarator:     MUL nfdeclarator             
+                       ={  umul:
+                               $$ = bdty( UNARY MUL, $2, 0 ); }
+               |  nfdeclarator  LP   RP                
+                       ={  uftn:
+                               $$ = bdty( UNARY CALL, $1, 0 );  }
+               |  nfdeclarator LB RB           
+                       ={  uary:
+                               $$ = bdty( LB, $1, 0 );  }
+               |  nfdeclarator LB con_e RB     
+                       ={  bary:
+                               if( (int)$3 <= 0 ) werror( "zero or negative subscript" );
+                               $$ = bdty( LB, $1, $3 );  }
+               |  NAME                 
+                       ={  $$ = bdty( NAME, NIL, $1 );  }
+               |   LP  nfdeclarator  RP                
+                       ={ $$=$2; }
+               ;
+fdeclarator:      MUL fdeclarator
+                       ={  goto umul; }
+               |  fdeclarator  LP   RP
+                       ={  goto uftn; }
+               |  fdeclarator LB RB
+                       ={  goto uary; }
+               |  fdeclarator LB con_e RB
+                       ={  goto bary; }
+               |   LP  fdeclarator  RP
+                       ={ $$ = $2; }
+               |  name_lp  name_list  RP
+                       ={
+                               if( blevel!=0 ) uerror("function declaration in bad context");
+                               $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
+                               stwart = 0;
+                               }
+               |  name_lp RP
+                       ={
+                               $$ = bdty( UNARY CALL, bdty(NAME,NIL,$1), 0 );
+                               stwart = 0;
+                               }
+               ;
+
+name_lp:         NAME LP
+                       ={
+                               /* turn off typedefs for argument names */
+                               stwart = SEENAME;
+                               if( stab[$1].sclass == SNULL )
+                                   stab[$1].stype = FTN;
+                               }
+               ;
+
+name_list:        NAME                 
+                       ={ ftnarg( $1 );  stwart = SEENAME; }
+               |  name_list  CM  NAME 
+                       ={ ftnarg( $3 );  stwart = SEENAME; }
+               | error
+               ;
+               /* always preceeded by attributes: thus the $<nodep>0's */
+init_dcl_list:    init_declarator
+                       %prec CM
+               |  init_dcl_list  CM {$<nodep>$=$<nodep>0;}  init_declarator
+               ;
+               /* always preceeded by attributes */
+xnfdeclarator:    nfdeclarator
+                       ={  defid( $1 = tymerge($<nodep>0,$1), curclass);
+                           beginit($1->tn.rval);
+                           }
+               |  error
+               ;
+               /* always preceeded by attributes */
+init_declarator:   nfdeclarator
+                       ={  nidcl( tymerge($<nodep>0,$1) ); }
+               |  fdeclarator
+                       ={  defid( tymerge($<nodep>0,$1), uclass(curclass) );
+                           if( paramno > 0 ){
+                               uerror( "illegal argument" );
+                               paramno = 0;
+                               }
+                       }
+               |  xnfdeclarator optasgn e
+                       %prec CM
+                       ={  doinit( $3 );
+                           endinit(); }
+               |  xnfdeclarator optasgn LC init_list optcomma RC
+                       ={  endinit(); }
+               | error
+               ;
+
+init_list:        initializer
+                       %prec CM
+               |  init_list  CM  initializer
+               ;
+initializer:      e
+                       %prec CM
+                       ={  doinit( $1 ); }
+               |  ibrace init_list optcomma RC
+                       ={  irbrace(); }
+               ;
+
+optcomma       :       /* VOID */
+               |  CM
+               ;
+
+optsemi                :       /* VOID */
+               |  SM
+               ;
+
+optasgn                :       /* VOID */
+                       ={  werror( "old-fashioned initialization: use =" ); }
+               |  ASSIGN
+               ;
+
+ibrace         : LC
+                       ={  ilbrace(); }
+               ;
+
+/*     STATEMENTS      */
+
+compoundstmt:     dcmpstmt
+               |  cmpstmt
+               ;
+
+dcmpstmt:         begin r_dcl_stat_list stmt_list RC
+                       ={  
+#ifndef LINT
+                           prcstab(blevel);
+#endif
+                           --blevel;
+                           if( blevel == 1 ) blevel = 0;
+                           clearst( blevel );
+                           checkst( blevel );
+                           autooff = *--psavbc;
+                           regvar = *--psavbc;
+                           }
+               ;
+
+cmpstmt:          begin stmt_list RC
+                       ={  --blevel;
+                           if( blevel == 1 ) blevel = 0;
+                           clearst( blevel );
+                           checkst( blevel );
+                           autooff = *--psavbc;
+                           regvar = *--psavbc;
+                           }
+               ;
+
+begin:           LC
+                       ={  if( blevel == 1 ) dclargs();
+                           ++blevel;
+                           if( psavbc > &asavbc[BCSZ-2] ) cerror( "nesting too deep" );
+                           *psavbc++ = regvar;
+                           *psavbc++ = autooff;
+                           }
+               ;
+
+statement:        e   SM
+                       ={ ecomp( $1 ); }
+               |  compoundstmt
+               |  ifprefix statement
+                       ={ deflab($1);
+                          reached = 1;
+                          }
+               |  ifelprefix statement
+                       ={  if( $1 != NOLAB ){
+                               deflab( $1 );
+                               reached = 1;
+                               }
+                           }
+               |  whprefix statement
+                       ={  branch(  contlab );
+                           deflab( brklab );
+                           if( (flostat&FBRK) || !(flostat&FLOOP)) reached = 1;
+                           else reached = 0;
+                           resetbc(0);
+                           }
+               |  doprefix statement WHILE  LP  e  RP   SM
+                       ={  deflab( contlab );
+                           if( flostat & FCONT ) reached = 1;
+                           ecomp( buildtree( CBRANCH, buildtree( NOT, $5, NIL ), bcon( $1 ) ) );
+                           deflab( brklab );
+                           reached = 1;
+                           resetbc(0);
+                           }
+               |  forprefix .e RP statement
+                       ={  deflab( contlab );
+                           if( flostat&FCONT ) reached = 1;
+                           if( $2 ) ecomp( $2 );
+                           branch( $1 );
+                           deflab( brklab );
+                           if( (flostat&FBRK) || !(flostat&FLOOP) ) reached = 1;
+                           else reached = 0;
+                           resetbc(0);
+                           }
+               | switchpart statement
+                       ={  if( reached ) branch( brklab );
+                           deflab( $1 );
+                          swend();
+                           deflab(brklab);
+                           if( (flostat&FBRK) || !(flostat&FDEF) ) reached = 1;
+                           resetbc(FCONT);
+                           }
+               |  BREAK  SM
+                       ={  if( brklab == NOLAB ) uerror( "illegal break");
+                           else if(reached) branch( brklab );
+                           flostat |= FBRK;
+                           if( brkflag ) goto rch;
+                           reached = 0;
+                           }
+               |  CONTINUE  SM
+                       ={  if( contlab == NOLAB ) uerror( "illegal continue");
+                           else branch( contlab );
+                           flostat |= FCONT;
+                           goto rch;
+                           }
+               |  RETURN  SM
+                       ={  retstat |= NRETVAL;
+                           branch( retlab );
+                       rch:
+                           if( !reached ) werror( "statement not reached");
+                           reached = 0;
+                           }
+               |  RETURN e  SM
+                       ={  register NODE *temp;
+                           idname = curftn;
+                           temp = buildtree( NAME, NIL, NIL );
+                           if(temp->in.type == TVOID)
+                               uerror("void function %s cannot return value",
+                                       stab[idname].sname);
+                           temp->in.type = DECREF( temp->in.type );
+                           temp = buildtree( RETURN, temp, $2 );
+                           /* now, we have the type of the RHS correct */
+                           temp->in.left->in.op = FREE;
+                           temp->in.op = FREE;
+                           ecomp( buildtree( FORCE, temp->in.right, NIL ) );
+                           retstat |= RETVAL;
+                           branch( retlab );
+                           reached = 0;
+                           }
+               |  GOTO NAME SM
+                       ={  register NODE *q;
+                           q = block( FREE, NIL, NIL, INT|ARY, 0, INT );
+                           q->tn.rval = idname = $2;
+                           defid( q, ULABEL );
+                           stab[idname].suse = -lineno;
+                           branch( stab[idname].offset );
+                           goto rch;
+                           }
+               |   SM
+               |  error  SM
+               |  error RC
+               |  label statement
+               ;
+label:            NAME COLON
+                       ={  register NODE *q;
+                           q = block( FREE, NIL, NIL, INT|ARY, 0, LABEL );
+                           q->tn.rval = $1;
+                           defid( q, LABEL );
+                           reached = 1;
+                           }
+               |  CASE e COLON
+                       ={  addcase($2);
+                           reached = 1;
+                           }
+               |  DEFAULT COLON
+                       ={  reached = 1;
+                           adddef();
+                           flostat |= FDEF;
+                           }
+               ;
+doprefix:      DO
+                       ={  savebc();
+                           if( !reached ) werror( "loop not entered at top");
+                           brklab = getlab();
+                           contlab = getlab();
+                           deflab( $$ = getlab() );
+                           reached = 1;
+                           }
+               ;
+ifprefix:      IF LP e RP
+                       ={  ecomp( buildtree( CBRANCH, $3, bcon( $$=getlab()) ) ) ;
+                           reached = 1;
+                           }
+               ;
+ifelprefix:      ifprefix statement ELSE
+                       ={  if( reached ) branch( $$ = getlab() );
+                           else $$ = NOLAB;
+                           deflab( $1 );
+                           reached = 1;
+                           }
+               ;
+
+whprefix:        WHILE  LP  e  RP
+                       ={  savebc();
+                           if( !reached ) werror( "loop not entered at top");
+                           if( $3->in.op == ICON && $3->tn.lval != 0 ) flostat = FLOOP;
+                           deflab( contlab = getlab() );
+                           reached = 1;
+                           brklab = getlab();
+                           if( flostat == FLOOP ) tfree( $3 );
+                           else ecomp( buildtree( CBRANCH, $3, bcon( brklab) ) );
+                           }
+               ;
+forprefix:       FOR  LP  .e  SM .e  SM 
+                       ={  if( $3 ) ecomp( $3 );
+                           else if( !reached ) werror( "loop not entered at top");
+                           savebc();
+                           contlab = getlab();
+                           brklab = getlab();
+                           deflab( $$ = getlab() );
+                           reached = 1;
+                           if( $5 ) ecomp( buildtree( CBRANCH, $5, bcon( brklab) ) );
+                           else flostat |= FLOOP;
+                           }
+               ;
+switchpart:       SWITCH  LP  e  RP
+                       ={  register NODE *q;
+                       
+                           savebc();
+                           brklab = getlab();
+                           q = $3;
+                           switch( q->in.type ) {
+                           case CHAR:  case UCHAR:
+                           case SHORT: case USHORT:
+                           case INT:   case UNSIGNED:
+                           case MOE:   case ENUMTY:
+                                   break;
+                           default:
+                               werror("switch expression not type int");
+                               q = makety( q, INT, q->fn.cdim, q->fn.csiz );
+                               }
+                           ecomp( buildtree( FORCE, q, NIL ) );
+                           branch( $$ = getlab() );
+                           swstart();
+                           reached = 0;
+                           }
+               ;
+/*     EXPRESSIONS     */
+con_e:            { $<intval>$=instruct; stwart=instruct=0; } e
+                       %prec CM
+                       ={  $$ = icons( $2 );  instruct=$<intval>1; }
+               ;
+.e:               e
+               |
+                       ={ $$=0; }
+               ;
+elist:            e
+                       %prec CM
+               |  elist  CM  e
+                       ={  goto bop; }
+               ;
+
+e:                e RELOP e
+                       ={
+                       preconf:
+                           if( yychar==RELOP||yychar==EQUOP||yychar==AND||yychar==OR||yychar==ER ){
+                           precplaint:
+                               if( hflag ) werror( "precedence confusion possible: parenthesize!" );
+                               }
+                       bop:
+                           $$ = buildtree( $2, $1, $3 );
+                           }
+               |  e CM e
+                       ={  $2 = COMOP;
+                           goto bop;
+                           }
+               |  e DIVOP e
+                       ={  goto bop; }
+               |  e PLUS e
+                       ={  if(yychar==SHIFTOP) goto precplaint; else goto bop; }
+               |  e MINUS e
+                       ={  if(yychar==SHIFTOP ) goto precplaint; else goto bop; }
+               |  e SHIFTOP e
+                       ={  if(yychar==PLUS||yychar==MINUS) goto precplaint; else goto bop; }
+               |  e MUL e
+                       ={  goto bop; }
+               |  e EQUOP  e
+                       ={  goto preconf; }
+               |  e AND e
+                       ={  if( yychar==RELOP||yychar==EQUOP ) goto preconf;  else goto bop; }
+               |  e OR e
+                       ={  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
+               |  e ER e
+                       ={  if(yychar==RELOP||yychar==EQUOP) goto preconf; else goto bop; }
+               |  e ANDAND e
+                       ={  goto bop; }
+               |  e OROR e
+                       ={  goto bop; }
+               |  e MUL ASSIGN e
+                       ={  abop:
+                               $$ = buildtree( ASG $2, $1, $4 );
+                               }
+               |  e DIVOP ASSIGN e
+                       ={  goto abop; }
+               |  e PLUS ASSIGN e
+                       ={  goto abop; }
+               |  e MINUS ASSIGN e
+                       ={  goto abop; }
+               |  e SHIFTOP ASSIGN e
+                       ={  goto abop; }
+               |  e AND ASSIGN e
+                       ={  goto abop; }
+               |  e OR ASSIGN e
+                       ={  goto abop; }
+               |  e ER ASSIGN e
+                       ={  goto abop; }
+               |  e QUEST e COLON e
+                       ={  $$=buildtree(QUEST, $1, buildtree( COLON, $3, $5 ) );
+                           }
+               |  e ASOP e
+                       ={  werror( "old-fashioned assignment operator" );  goto bop; }
+               |  e ASSIGN e
+                       ={  goto bop; }
+               |  term
+               ;
+term:             term INCOP
+                       ={  $$ = buildtree( $2, $1, bcon(1) ); }
+               |  MUL term
+                       ={ ubop:
+                           $$ = buildtree( UNARY $1, $2, NIL );
+                           }
+               |  AND term
+                       ={  if( ISFTN($2->in.type) || ISARY($2->in.type) ){
+                               werror( "& before array or function: ignored" );
+                               $$ = $2;
+                               }
+                           else goto ubop;
+                           }
+               |  MINUS term
+                       ={  goto ubop; }
+               |  UNOP term
+                       ={
+                           $$ = buildtree( $1, $2, NIL );
+                           }
+               |  INCOP term
+                       ={  $$ = buildtree( $1==INCR ? ASG PLUS : ASG MINUS,
+                                               $2,
+                                               bcon(1)  );
+                           }
+               |  SIZEOF term
+                       ={  $$ = doszof( $2 ); }
+               |  LP cast_type RP term  %prec INCOP
+                       ={  $$ = buildtree( CAST, $2, $4 );
+                           $$->in.left->in.op = FREE;
+                           $$->in.op = FREE;
+                           $$ = $$->in.right;
+                           }
+               |  SIZEOF LP cast_type RP  %prec SIZEOF
+                       ={  $$ = doszof( $3 ); }
+               |  term LB e RB
+                       ={  $$ = buildtree( UNARY MUL, buildtree( PLUS, $1, $3 ), NIL ); }
+               |  funct_idn  RP
+                       ={  $$=buildtree(UNARY CALL,$1,NIL); }
+               |  funct_idn elist  RP
+                       ={  $$=buildtree(CALL,$1,$2); }
+               |  term STROP NAME
+                       ={  if( $2 == DOT ){
+                               if( notlval( $1 ) )uerror("structure reference must be addressable");
+                               $1 = buildtree( UNARY AND, $1, NIL );
+                               }
+                           idname = $3;
+                           $$ = buildtree( STREF, $1, buildtree( NAME, NIL, NIL ) );
+                           }
+               |  NAME
+                       ={  idname = $1;
+                           /* recognize identifiers in initializations */
+                           if( blevel==0 && stab[idname].stype == UNDEF ) {
+                               register NODE *q;
+#ifndef FLEXNAMES
+                               werror( "undeclared initializer name %.8s", stab[idname].sname );
+#else
+                               werror( "undeclared initializer name %s", stab[idname].sname );
+#endif
+                               q = block( FREE, NIL, NIL, INT, 0, INT );
+                               q->tn.rval = idname;
+                               defid( q, EXTERN );
+                               }
+                           $$=buildtree(NAME,NIL,NIL);
+                           stab[$1].suse = -lineno;
+                       }
+               |  ICON
+                       ={  $$=bcon(0);
+                           $$->tn.lval = lastcon;
+                           $$->tn.rval = NONAME;
+                           if( $1 ) $$->fn.csiz = $$->in.type = ctype(LONG);
+                           }
+               |  FCON
+                       ={  $$=buildtree(FCON,NIL,NIL);
+                           $$->fpn.fval = fcon;
+                           }
+               |  DCON
+                       ={  $$=buildtree(DCON,NIL,NIL);
+                           $$->dpn.dval = dcon;
+                           }
+               |  STRING
+                       ={  $$ = getstr(); /* get string contents */ }
+               |   LP  e  RP
+                       ={ $$=$2; }
+               ;
+
+cast_type:       type null_decl
+                       ={
+                       $$ = tymerge( $1, $2 );
+                       $$->in.op = NAME;
+                       $1->in.op = FREE;
+                       }
+               ;
+
+null_decl:        /* empty */
+                       ={ $$ = bdty( NAME, NIL, -1 ); }
+               |  LP RP
+                       ={ $$ = bdty( UNARY CALL, bdty(NAME,NIL,-1),0); }
+               |  LP null_decl RP LP RP
+                       ={  $$ = bdty( UNARY CALL, $2, 0 ); }
+               |  MUL null_decl
+                       ={  goto umul; }
+               |  null_decl LB RB
+                       ={  goto uary; }
+               |  null_decl LB con_e RB
+                       ={  goto bary;  }
+               |  LP null_decl RP
+                       ={ $$ = $2; }
+               ;
+
+funct_idn:        NAME  LP 
+                       ={  if( stab[$1].stype == UNDEF ){
+                               register NODE *q;
+                               q = block( FREE, NIL, NIL, FTN|INT, 0, INT );
+                               q->tn.rval = $1;
+                               defid( q, EXTERN );
+                               }
+                           idname = $1;
+                           $$=buildtree(NAME,NIL,NIL);
+                           stab[idname].suse = -lineno;
+                       }
+               |  term  LP 
+               ;
+%%
+
+NODE *
+mkty( t, d, s ) unsigned t; {
+       return( block( TYPE, NIL, NIL, t, d, s ) );
+       }
+
+NODE *
+bdty( op, p, v ) NODE *p; {
+       register NODE *q;
+
+       q = block( op, p, NIL, INT, 0, INT );
+
+       switch( op ){
+
+       case UNARY MUL:
+       case UNARY CALL:
+               break;
+
+       case LB:
+               q->in.right = bcon(v);
+               break;
+
+       case NAME:
+               q->tn.rval = v;
+               break;
+
+       default:
+               cerror( "bad bdty" );
+               }
+
+       return( q );
+       }
+
+dstash( n ){ /* put n into the dimension table */
+       if( curdim >= DIMTABSZ-1 ){
+               cerror( "dimension table overflow");
+               }
+       dimtab[ curdim++ ] = n;
+       }
+
+savebc() {
+       if( psavbc > & asavbc[BCSZ-4 ] ){
+               cerror( "whiles, fors, etc. too deeply nested");
+               }
+       *psavbc++ = brklab;
+       *psavbc++ = contlab;
+       *psavbc++ = flostat;
+       *psavbc++ = swx;
+       flostat = 0;
+       }
+
+resetbc(mask){
+
+       swx = *--psavbc;
+       flostat = *--psavbc | (flostat&mask);
+       contlab = *--psavbc;
+       brklab = *--psavbc;
+
+       }
+
+addcase(p) NODE *p; { /* add case to switch */
+
+       p = optim( p );  /* change enum to ints */
+       if( p->in.op != ICON ){
+               uerror( "non-constant case expression");
+               return;
+               }
+       if( swp == swtab ){
+               uerror( "case not in switch");
+               return;
+               }
+       if( swp >= &swtab[SWITSZ] ){
+               cerror( "switch table overflow");
+               }
+       swp->sval = p->tn.lval;
+       deflab( swp->slab = getlab() );
+       ++swp;
+       tfree(p);
+       }
+
+adddef(){ /* add default case to switch */
+       if( swtab[swx].slab >= 0 ){
+               uerror( "duplicate default in switch");
+               return;
+               }
+       if( swp == swtab ){
+               uerror( "default not inside switch");
+               return;
+               }
+       deflab( swtab[swx].slab = getlab() );
+       }
+
+swstart(){
+       /* begin a switch block */
+       if( swp >= &swtab[SWITSZ] ){
+               cerror( "switch table overflow");
+               }
+       swx = swp - swtab;
+       swp->slab = -1;
+       ++swp;
+       }
+
+swend(){ /* end a switch block */
+
+       register struct sw *swbeg, *p, *q, *r, *r1;
+       CONSZ temp;
+       int tempi;
+
+       swbeg = &swtab[swx+1];
+
+       /* sort */
+
+       r1 = swbeg;
+       r = swp-1;
+
+       while( swbeg < r ){
+               /* bubble largest to end */
+               for( q=swbeg; q<r; ++q ){
+                       if( q->sval > (q+1)->sval ){
+                               /* swap */
+                               r1 = q+1;
+                               temp = q->sval;
+                               q->sval = r1->sval;
+                               r1->sval = temp;
+                               tempi = q->slab;
+                               q->slab = r1->slab;
+                               r1->slab = tempi;
+                               }
+                       }
+               r = r1;
+               r1 = swbeg;
+               }
+
+       /* it is now sorted */
+
+       for( p = swbeg+1; p<swp; ++p ){
+               if( p->sval == (p-1)->sval ){
+                       uerror( "duplicate case in switch, %d", tempi=p->sval );
+                       return;
+                       }
+               }
+
+       genswitch( swbeg-1, swp-swbeg );
+       swp = swbeg-1;
+       }
diff --git a/lib/pcc/comm1.c b/lib/pcc/comm1.c
new file mode 100644 (file)
index 0000000..24ebd5d
--- /dev/null
@@ -0,0 +1,380 @@
+/*     common.c        4.2     85/08/22        */
+
+#include <varargs.h>
+/*#ifdef PASS1COMMON*/
+#include "pass1.h"
+/*#else*/
+/*#ifdef PASS2COMMON*/
+/*#include "pass2.h"*/
+/*#endif*/
+/*#endif*/
+
+#ifdef FORT
+#undef BUFSTDERR
+#endif
+#ifndef ONEPASS
+#undef BUFSTDERR
+#endif
+
+int nerrors = 0;  /* number of errors */
+
+extern unsigned int offsz;
+
+unsigned caloff(){
+       register i;
+       unsigned int temp;
+       unsigned int off;
+       temp = 1;
+       i = 0;
+       do {
+               temp <<= 1;
+               ++i;
+               } while( temp != 0 );
+       off = 1 << (i-1);
+       return (off);
+       }
+
+NODE *lastfree;  /* pointer to last free node; (for allocator) */
+
+uerror( s, va_alist ) char *s; va_dcl { /* nonfatal error message */
+       va_list argp;
+
+       /* the routine where is different for pass 1 and pass 2;
+       /*  it tells where the error took place */
+
+       ++nerrors;
+       where('u');
+       va_start(argp);
+       vfprintf( stderr, s, argp );
+       va_end(argp);
+       fprintf( stderr, "\n" );
+#ifdef BUFSTDERR
+       fflush(stderr);
+#endif
+       if( nerrors > 30 ) cerror( "too many errors");
+       }
+
+cerror( s, va_alist ) char *s; va_dcl { /* compiler error: die */
+       va_list argp;
+
+       where('c');
+       if( nerrors && nerrors <= 30 ){ /* give the compiler the benefit of the doubt */
+               fprintf( stderr, "cannot recover from earlier errors: goodbye!\n" );
+               }
+       else {
+               fprintf( stderr, "compiler error: " );
+               va_start(argp);
+               fprintf( stderr, s, argp );
+               va_end(argp);
+               fprintf( stderr, "\n" );
+               }
+#ifdef BUFSTDERR
+       fflush(stderr);
+#endif
+       exit(1);
+       }
+
+int Wflag = 0; /* Non-zero means do not print warnings */
+
+werror( s, va_alist ) char *s; va_dcl {  /* warning */
+       va_list argp;
+
+       if(Wflag) return;
+       where('w');
+       fprintf( stderr, "warning: " );
+       va_start(argp);
+       fprintf( stderr, s, argp );
+       va_end(argp);
+       fprintf( stderr, "\n" );
+#ifdef BUFSTDERR
+       fflush(stderr);
+#endif
+       }
+
+tinit(){ /* initialize expression tree search */
+
+       register NODE *p;
+
+       for( p=node; p<= &node[TREESZ-1]; ++p ) p->in.op = FREE;
+       lastfree = node;
+
+       }
+
+# define TNEXT(p) (p== &node[TREESZ-1]?node:p+1)
+
+NODE *
+talloc(){
+       register NODE *p, *q;
+
+       q = lastfree;
+       for( p = TNEXT(q); p!=q; p= TNEXT(p))
+               if( p->in.op ==FREE ) return(lastfree=p);
+
+       cerror( "out of tree space; simplify expression");
+       /* NOTREACHED */
+       }
+
+tcheck(){ /* ensure that all nodes have been freed */
+
+       register NODE *p;
+
+       if( !nerrors )
+               for( p=node; p<= &node[TREESZ-1]; ++p )
+                       if( p->in.op != FREE ) cerror( "wasted space: %o", p );
+       tinit();
+#ifdef FLEXNAMES
+       freetstr();
+#endif
+       }
+tfree( p )  NODE *p; {
+       /* free the tree p */
+       extern tfree1();
+
+       if( p->in.op != FREE ) walkf( p, tfree1 );
+
+       }
+
+tfree1(p)  NODE *p; {
+       if( p == 0 ) cerror( "freeing blank tree!");
+       else p->in.op = FREE;
+       }
+
+fwalk( t, f, down ) register NODE *t; int (*f)(); {
+
+       int down1, down2;
+
+       more:
+       down1 = down2 = 0;
+
+       (*f)( t, down, &down1, &down2 );
+
+       switch( optype( t->in.op ) ){
+
+       case BITYPE:
+               fwalk( t->in.left, f, down1 );
+               t = t->in.right;
+               down = down2;
+               goto more;
+
+       case UTYPE:
+               t = t->in.left;
+               down = down1;
+               goto more;
+
+               }
+       }
+
+#ifndef vax
+walkf( t, f ) register NODE *t;  int (*f)(); {
+       register opty;
+
+       opty = optype(t->in.op);
+
+       if( opty != LTYPE ) walkf( t->in.left, f );
+       if( opty == BITYPE ) walkf( t->in.right, f );
+       (*f)( t );
+       }
+#else
+#define        NR      100
+
+/*
+ * Deliberately avoids recursion -- use this version on machines with
+ * expensive procedure calls.
+ */
+walkf(t, f)
+       register NODE *t;
+       register int (*f)();
+{
+       register int i = 1;
+       register int opty = optype(t->in.op);
+       static NODE *at[NR];
+       static int ao[NR];
+
+#define        PUSH(dir, state) \
+       (ao[i] = state, at[i++] = t, t = t->in.dir, opty = optype(t->in.op))
+#define        POP() \
+       (opty = ao[--i], t = at[i])
+
+       do {
+               switch (opty) {
+               case LTYPE:     (*f)(t); POP(); break;
+               case UTYPE:     PUSH(left, LTYPE); break;
+               case BITYPE:    PUSH(left, BITYPE+1); break;
+               case BITYPE+1:  PUSH(right, LTYPE); break;
+               default:
+                       cerror("bad op type in walkf");
+               }
+               if (i >= NR) {
+                       walkf(t, f);
+                       POP();
+               }
+       } while (i > 0);
+}
+#undef NR
+#undef PUSH
+#undef POP
+#endif
+
+
+
+int dope[ DSIZE ];
+char *opst[DSIZE];
+
+struct dopest { int dopeop; char opst[8]; int dopeval; } indope[] = {
+
+       NAME, "NAME", LTYPE,
+       STRING, "STRING", LTYPE,
+       REG, "REG", LTYPE,
+       OREG, "OREG", LTYPE,
+       ICON, "ICON", LTYPE,
+       FCON, "FCON", LTYPE,
+       DCON, "DCON", LTYPE,
+       CCODES, "CCODES", LTYPE,
+       UNARY MINUS, "U-", UTYPE,
+       UNARY MUL, "U*", UTYPE,
+       UNARY AND, "U&", UTYPE,
+       UNARY CALL, "UCALL", UTYPE|CALLFLG,
+       UNARY FORTCALL, "UFCALL", UTYPE|CALLFLG,
+       NOT, "!", UTYPE|LOGFLG,
+       COMPL, "~", UTYPE,
+       FORCE, "FORCE", UTYPE,
+       INIT, "INIT", UTYPE,
+       SCONV, "SCONV", UTYPE,
+       PCONV, "PCONV", UTYPE,
+       PLUS, "+", BITYPE|FLOFLG|SIMPFLG|COMMFLG,
+       ASG PLUS, "+=", BITYPE|ASGFLG|ASGOPFLG|FLOFLG|SIMPFLG|COMMFLG,
+       MINUS, "-", BITYPE|FLOFLG|SIMPFLG,
+       ASG MINUS, "-=", BITYPE|FLOFLG|SIMPFLG|ASGFLG|ASGOPFLG,
+       MUL, "*", BITYPE|FLOFLG|MULFLG,
+       ASG MUL, "*=", BITYPE|FLOFLG|MULFLG|ASGFLG|ASGOPFLG,
+       AND, "&", BITYPE|SIMPFLG|COMMFLG,
+       ASG AND, "&=", BITYPE|SIMPFLG|COMMFLG|ASGFLG|ASGOPFLG,
+       QUEST, "?", BITYPE,
+       COLON, ":", BITYPE,
+       ANDAND, "&&", BITYPE|LOGFLG,
+       OROR, "||", BITYPE|LOGFLG,
+       CM, ",", BITYPE,
+       COMOP, ",OP", BITYPE,
+       ASSIGN, "=", BITYPE|ASGFLG,
+       DIV, "/", BITYPE|FLOFLG|MULFLG|DIVFLG,
+       ASG DIV, "/=", BITYPE|FLOFLG|MULFLG|DIVFLG|ASGFLG|ASGOPFLG,
+       MOD, "%", BITYPE|DIVFLG,
+       ASG MOD, "%=", BITYPE|DIVFLG|ASGFLG|ASGOPFLG,
+       LS, "<<", BITYPE|SHFFLG,
+       ASG LS, "<<=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
+       RS, ">>", BITYPE|SHFFLG,
+       ASG RS, ">>=", BITYPE|SHFFLG|ASGFLG|ASGOPFLG,
+       OR, "|", BITYPE|COMMFLG|SIMPFLG,
+       ASG OR, "|=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
+       ER, "^", BITYPE|COMMFLG|SIMPFLG,
+       ASG ER, "^=", BITYPE|COMMFLG|SIMPFLG|ASGFLG|ASGOPFLG,
+       INCR, "++", BITYPE|ASGFLG,
+       DECR, "--", BITYPE|ASGFLG,
+       STREF, "->", BITYPE,
+       CALL, "CALL", BITYPE|CALLFLG,
+       FORTCALL, "FCALL", BITYPE|CALLFLG,
+       EQ, "==", BITYPE|LOGFLG,
+       NE, "!=", BITYPE|LOGFLG,
+       LE, "<=", BITYPE|LOGFLG,
+       LT, "<", BITYPE|LOGFLG,
+       GE, ">", BITYPE|LOGFLG,
+       GT, ">", BITYPE|LOGFLG,
+       UGT, "UGT", BITYPE|LOGFLG,
+       UGE, "UGE", BITYPE|LOGFLG,
+       ULT, "ULT", BITYPE|LOGFLG,
+       ULE, "ULE", BITYPE|LOGFLG,
+#ifdef ARS
+       ARS, "A>>", BITYPE,
+#endif
+       TYPE, "TYPE", LTYPE,
+       LB, "[", BITYPE,
+       CBRANCH, "CBRANCH", BITYPE,
+       FLD, "FLD", UTYPE,
+       PMCONV, "PMCONV", BITYPE,
+       PVCONV, "PVCONV", BITYPE,
+       RETURN, "RETURN", BITYPE|ASGFLG|ASGOPFLG,
+       CAST, "CAST", BITYPE|ASGFLG|ASGOPFLG,
+       GOTO, "GOTO", UTYPE,
+       STASG, "STASG", BITYPE|ASGFLG,
+       STARG, "STARG", UTYPE,
+       STCALL, "STCALL", BITYPE|CALLFLG,
+       UNARY STCALL, "USTCALL", UTYPE|CALLFLG,
+
+       -1,     "",     0
+};
+
+mkdope(){
+       register struct dopest *q;
+
+       for( q = indope; q->dopeop >= 0; ++q ){
+               dope[q->dopeop] = q->dopeval;
+               opst[q->dopeop] = q->opst;
+               }
+       }
+# ifndef BUG4
+tprint( t )  TWORD t; { /* output a nice description of the type of t */
+
+       static char * tnames[] = {
+               "undef",
+               "farg",
+               "char",
+               "short",
+               "int",
+               "long",
+               "float",
+               "double",
+               "strty",
+               "unionty",
+               "enumty",
+               "moety",
+               "uchar",
+               "ushort",
+               "unsigned",
+               "ulong",
+               "?", "?"
+               };
+
+       for(;; t = DECREF(t) ){
+
+               if( ISPTR(t) ) printf( "PTR " );
+               else if( ISFTN(t) ) printf( "FTN " );
+               else if( ISARY(t) ) printf( "ARY " );
+               else {
+                       printf( "%s", tnames[t] );
+                       return;
+                       }
+               }
+       }
+# endif
+
+#ifdef FLEXNAMES
+#define        NTSTRBUF        40
+#define        TSTRSZ          2048
+char   itstrbuf[TSTRSZ];
+char   *tstrbuf[NTSTRBUF] = { itstrbuf };
+char   **curtstr = tstrbuf;
+int    tstrused;
+
+char *
+tstr(cp)
+       register char *cp;
+{
+       register int i = strlen(cp);
+       register char *dp;
+       
+       if (tstrused + i >= TSTRSZ) {
+               if (++curtstr >= &tstrbuf[NTSTRBUF])
+                       cerror("out of temporary string space");
+               tstrused = 0;
+               if (*curtstr == 0) {
+                       dp = (char *)malloc(TSTRSZ);
+                       if (dp == 0)
+                               cerror("out of memory (tstr)");
+                       *curtstr = dp;
+               }
+       }
+       strcpy(dp = *curtstr+tstrused, cp);
+       tstrused += i + 1;
+       return (dp);
+}
+#endif
diff --git a/lib/pcc/config.h b/lib/pcc/config.h
new file mode 100644 (file)
index 0000000..0998167
--- /dev/null
@@ -0,0 +1,34 @@
+/*     config.h        4.3     85/08/22        */
+
+#ifndef _CONFIG_
+#define        _CONFIG_
+/*
+ * Compiler configuration definitions.
+ */
+
+/*
+ * These flags control global compiler operation.
+ */
+#define        BUFSTDERR       1               /* buffer output to stderr */
+#define STDPRTREE      1               /* means include prtree */
+#define NESTCALLS      1               /* disallow two concurrent store()'s */
+#define        FLEXNAMES       1               /* arbitrary length identifiers */
+
+/*
+ * Table sizes.
+ */
+#define TREESZ         1000            /* parse tree table size */
+#define BCSZ           100             /* break/continue table size */
+#define SYMTSZ         3000            /* symbol table size */
+#define DIMTABSZ       4200            /* dimension/size table size */
+#define PARAMSZ                300             /* parameter stack size */
+#define SWITSZ         500             /* switch table size */
+#define        DELAYS          20              /* delayed evaluation table size */
+#define NRECUR         (10*TREESZ)     /* maximum eval recursion depth */
+#define        MAXSCOPES       (SYMTSZ/30)     /* maximum active scopes */
+
+/* in case anyone still uses fixed length names */
+#ifndef FLEXNAMES
+#define        NCHNAM          8               /* significant chars of identifier */
+#endif
+#endif
diff --git a/lib/pcc/conflicts.txt b/lib/pcc/conflicts.txt
new file mode 100644 (file)
index 0000000..a3e0772
--- /dev/null
@@ -0,0 +1,44 @@
+allo.c pass1.h
+cgram.c arpa/ftp.h
+cgram.c arpa/telnet.h
+cgram.c arpa/tftp.h
+cgram.c pass2.h
+cgram.c sys/tty.h
+code.c arpa/tftp.h
+code.c pass2.h
+code.c sys/select.h
+comm1.c pass2.h
+comm1.c sys/tty.h
+fort.c pass1.h
+local.c pass2.h
+local2.c pass1.h
+local2.c vax/reg.h
+mac2defs.h pass2.h
+mac2defs.h vax/reg.h
+macdefs.h pass1.h
+macdefs.h pass2.h
+match.c pass1.h
+optim.c pass2.h
+optim.c sys/seg.h
+order.c pass1.h
+order.c vax/reg.h
+pass1.h arpa/tftp.h
+pass1.h pass2.h
+pass2.h pass1.h
+pcclocal.h arpa/ftp.h
+pcclocal.h arpa/telnet.h
+pcclocal.h arpa/tftp.h
+pcclocal.h sys/tty.h
+pftn.c arpa/tftp.h
+pftn.c pass2.h
+reader.c pass1.h
+scan.c arpa/ftp.h
+scan.c arpa/telnet.h
+scan.c pass2.h
+scan.c sys/tty.h
+stab.c pass2.h
+table.c pass1.h
+trees.c arpa/tftp.h
+trees.c pass2.h
+trees.c sys/tty.h
+xdefs.c pass2.h
diff --git a/lib/pcc/fort.c b/lib/pcc/fort.c
new file mode 100644 (file)
index 0000000..fb6f775
--- /dev/null
@@ -0,0 +1,323 @@
+#ifndef lint
+static char *sccsid ="@(#)fort.c       4.7 (Berkeley) 8/22/85";
+#endif lint
+
+# ifndef FORT
+# define FORT
+/* this may force larger trees, etc. */
+# endif
+
+# include "pass2.h"
+# include "fort.h"
+
+/*     masks for unpacking longs */
+
+# ifndef FOP
+# define FOP(x) (int)((x)&0377)
+# endif
+
+# ifndef VAL
+# define VAL(x) (int)(((x)>>8)&0377)
+# endif
+
+# ifndef REST
+# define REST(x) (((x)>>16)&0177777)
+# endif
+
+# ifndef FIXINT
+# if SZINT == SZLONG
+# define FIXINT(x) ((x) == LONG || (x) == ULONG ? (x) - 1 : (x))
+# else
+# if SZINT == SZSHORT
+# define FIXINT(x) ((x) == SHORT || (x) == USHORT ? (x) + 1 : (x))
+# else
+# define FIXINT(x) (x)
+# endif
+# endif
+# endif
+
+FILE * lrd;  /* for default reading routines */
+
+# ifndef NOLNREAD
+#ifdef FLEXNAMES
+char *
+lnread()
+{
+       char buf[BUFSIZ];
+       register char *cp = buf;
+       register char *limit = &buf[BUFSIZ];
+
+       for (;;) {
+               if (fread(cp, sizeof (long), 1, lrd) !=  1)
+                       cerror("intermediate file read error");
+               cp += sizeof (long);
+               if (cp[-1] == 0)
+                       break;
+               if (cp >= limit)
+                       cerror("lnread overran string buffer");
+       }
+       return (tstr(buf));
+}
+#endif
+# endif NOLNREAD
+
+# ifndef NOLREAD
+long lread(){
+       static long x;
+       if( fread( (char *) &x, 4, 1, lrd ) <= 0 ) cerror( "intermediate file read error" );
+       return( x );
+       }
+# endif
+
+# ifndef NOLOPEN
+lopen( s ) char *s; {
+       /* if null, opens the standard input */
+       if( *s ){
+               lrd = fopen( s, "r" );
+               if( lrd == NULL ) cerror( "cannot open intermediate file %s", s );
+               }
+       else  lrd = stdin;
+       }
+# endif
+
+# ifndef NOLCREAD
+lcread( cp, n ) char *cp; {
+       if( n > 0 ){
+               if( fread( cp, 4, n, lrd ) != n ) cerror( "intermediate file read error" );
+               }
+       }
+# endif
+
+# ifndef NOLCCOPY
+lccopy( n ) register n; {
+       register i;
+       static char fbuf[BUFSIZ];
+       if( n > 0 ){
+               if( n > BUFSIZ/4 ) cerror( "lccopy asked to copy too much" );
+               if( fread( fbuf, 4, n, lrd ) != n ) cerror( "intermediate file read error" );
+               for( i=4*n; fbuf[i-1] == '\0' && i>0; --i ) { /* VOID */ }
+               if( i ) {
+                       if( fwrite( fbuf, 1, i, stdout ) != i ) cerror( "output file error" );
+                       }
+               }
+       }
+# endif
+
+/*     stack for reading nodes in postfix form */
+
+# define NSTACKSZ 250
+
+NODE * fstack[NSTACKSZ];
+NODE ** fsp;  /* points to next free position on the stack */
+
+unsigned int offsz;
+unsigned int caloff();
+mainp2( argc, argv ) char *argv[]; {
+       int files;
+       register long x;
+       register NODE *p;
+
+       offsz = caloff();
+       files = p2init( argc, argv );
+       tinit();
+
+               
+       if( files ){
+               while( files < argc && argv[files][0] == '-' ) {
+                       ++files;
+                       }
+               if( files > argc ) return( nerrors );
+               lopen( argv[files] );
+               }
+       else lopen( "" );
+
+       fsp = fstack;
+
+       for(;;){
+               /* read nodes, and go to work... */
+               x = lread();
+
+       if( x2debug ) fprintf( stderr, "op=%d, val = %d, rest = 0%o\n", FOP(x), VAL(x), (int)REST(x) );
+               switch( (int)FOP(x) ){  /* switch on opcode */
+
+               case 0:
+                       fprintf( stderr, "null opcode ignored\n" );
+                       continue;
+               case FTEXT:
+                       lccopy( VAL(x) );
+                       printf( "\n" );
+                       continue;
+
+               case FLBRAC:
+                       tmpoff = baseoff = lread();
+                       maxtreg = VAL(x);
+                       if( ftnno != REST(x) ){
+                               /* beginning of function */
+                               maxoff = baseoff;
+                               ftnno = REST(x);
+                               maxtemp = 0;
+                               }
+                       else {
+                               if( baseoff > maxoff ) maxoff = baseoff;
+                               /* maxoff at end of ftn is max of autos and temps 
+                                  over all blocks in the function */
+                               }
+                       setregs();
+                       continue;
+
+               case FRBRAC:
+                       SETOFF( maxoff, ALSTACK );
+                       eobl2();
+                       continue;
+
+               case FEOF:
+                       return( nerrors );
+
+               case FSWITCH:
+                       uerror( "switch not yet done" );
+                       for( x=VAL(x); x>0; --x ) lread();
+                       continue;
+
+               case ICON:
+                       p = talloc();
+                       p->in.op = ICON;
+                       p->in.type = FIXINT(REST(x));
+                       p->tn.rval = 0;
+                       p->tn.lval = lread();
+                       if( VAL(x) ){
+#ifndef FLEXNAMES
+                               lcread( p->in.name, 2 );
+#else
+                               p->in.name = lnread();
+#endif
+                               }
+#ifndef FLEXNAMES
+                       else p->in.name[0] = '\0';
+#else
+                       else p->in.name = "";
+#endif
+
+               bump:
+                       p->in.su = 0;
+                       p->in.rall = NOPREF;
+                       *fsp++ = p;
+                       if( fsp >= &fstack[NSTACKSZ] ) uerror( "expression depth exceeded" );
+                       continue;
+
+               case NAME:
+                       p = talloc();
+                       p->in.op = NAME;
+                       p->in.type = FIXINT(REST(x));
+                       p->tn.rval = 0;
+                       if( VAL(x) ) p->tn.lval = lread();
+                       else p->tn.lval = 0;
+#ifndef FLEXNAMES
+                       lcread( p->in.name, 2 );
+#else
+                       p->in.name = lnread();
+#endif
+                       goto bump;
+
+               case OREG:
+                       p = talloc();
+                       p->in.op = OREG;
+                       p->in.type = FIXINT(REST(x));
+                       p->tn.rval = VAL(x);
+                       rbusy( p->tn.rval, PTR | p->in.type );
+                       p->tn.lval = lread();
+#ifndef FLEXNAMES
+                       lcread( p->in.name, 2 );
+#else
+                       p->in.name = lnread();
+#endif
+                       goto bump;
+
+               case REG:
+                       p = talloc();
+                       p->in.op = REG;
+                       p->in.type = FIXINT(REST(x));
+                       p->tn.rval = VAL(x);
+                       rbusy( p->tn.rval, p->in.type );
+                       p->tn.lval = 0;
+#ifndef FLEXNAMES
+                       p->in.name[0] = '\0';
+#else
+                       p->in.name = "";
+#endif
+                       goto bump;
+
+               case FEXPR:
+                       lineno = REST(x);
+                       if( VAL(x) ) lcread( ftitle, VAL(x) );
+                       if( fsp == fstack ) continue;  /* ftitle only */
+                       if( --fsp != fstack ) uerror( "expression poorly formed" );
+                       if( lflag ) lineid( lineno, ftitle );
+                       tmpoff = baseoff;
+                       p = fstack[0];
+                       if( e2debug ) fwalk( p, e2print, 0 );
+# ifdef MYREADER
+                       MYREADER(p);
+# endif
+
+                       nrecur = 0;
+                       delay( p );
+                       reclaim( p, RNULL, 0 );
+
+                       allchk();
+                       tcheck();
+                       continue;
+
+               case FLABEL:
+                       if( VAL(x) ){
+                               tlabel();
+                               }
+                       else {
+                               label( (int) REST(x) );
+                               }
+                       continue;
+
+               case GOTO:
+                       if( VAL(x) ) {
+                               cbgen( 0, (int) REST(x), 'I' );  /* unconditional branch */
+                               continue;
+                               }
+                       /* otherwise, treat as unary */
+                       goto def;
+
+               case STASG:
+               case STARG:
+               case STCALL:
+               case UNARY STCALL:
+                           /*
+                            * size and alignment come from next long words
+                            */
+                       p = talloc();
+                       p -> stn.stsize = lread();
+                       p -> stn.stalign = lread();
+                       goto defa;
+               default:
+               def:
+                       p = talloc();
+               defa:
+                       p->in.op = FOP(x);
+                       p->in.type = FIXINT(REST(x));
+
+                       switch( optype( p->in.op ) ){
+
+                       case BITYPE:
+                               p->in.right = *--fsp;
+                               p->in.left = *--fsp;
+                               goto bump;
+
+                       case UTYPE:
+                               p->in.left = *--fsp;
+                               p->tn.rval = 0;
+                               goto bump;
+
+                       case LTYPE:
+                               uerror( "illegal leaf node: %d", p->in.op );
+                               exit( 1 );
+                               }
+                       }
+               }
+       }
diff --git a/lib/pcc/groups.txt b/lib/pcc/groups.txt
new file mode 100644 (file)
index 0000000..2401e20
--- /dev/null
@@ -0,0 +1,17 @@
+allo.c pass2.h
+cgram.c pass1.h
+code.c pass1.h
+comm1.c manifest.h
+fort.c pass2.h
+local.c pass1.h
+local2.c pass2.h
+match.c pass2.h
+optim.c pass1.h
+order.c pass2.h
+pftn.c pass1.h
+reader.c pass2.h
+scan.c pass1.h
+stab.c pass1.h
+table.c pass2.h
+trees.c pass1.h
+xdefs.c pass1.h
index 5df9b30..dba226f 100644 (file)
@@ -13,8 +13,8 @@ int ftlab1, ftlab2;
 
 # define BITMASK(n) ((1L<<n)-1)
 
-where(c){
-       fprintf( stderr, "%s, line %d: ", filename, lineno );
+where2(c){
+       fprintf( stderr, "%s, line %d: ", ftitle, lineno );
        }
 
 lineid( l, fn ) char *fn; {
@@ -195,10 +195,10 @@ zzzcode( p, c ) register NODE *p; {
 
        case 'N':  /* logical ops, turned into 0-1 */
                /* use register given by register 1 */
-               cbgen( 0, m=getlab(), 'I' );
-               deflab( p->bn.label );
+               cbgen( 0, m=get2lab(), 'I' );
+               def2lab( p->bn.label );
                printf( "       clrl    %s\n", rnames[getlr( p, '1' )->tn.rval] );
-               deflab( m );
+               def2lab( m );
                return;
 
        case 'I':
@@ -210,7 +210,7 @@ zzzcode( p, c ) register NODE *p; {
                {
                register NODE *l, *r;
 
-               if (xdebug) eprint(p, 0, &val, &val);
+               if (x2debug) e2print(p, 0, &val, &val);
                r = getlr(p, 'R');
                if (p->in.op == ASSIGN)
                        l = getlr(p, 'L');
@@ -312,8 +312,8 @@ zzzcode( p, c ) register NODE *p; {
                    mixtypes(l, r)) {
                        int label1, label2;
 
-                       label1 = getlab();
-                       label2 = getlab();
+                       label1 = get2lab();
+                       label2 = get2lab();
 
                        putstr("movl\t");
                        adrput(r);
@@ -416,7 +416,7 @@ zzzcode( p, c ) register NODE *p; {
        case 'B':       /* get oreg value in temp register for left shift */
                {
                register NODE *r;
-               if (xdebug) eprint(p, 0, &val, &val);
+               if (x2debug) e2print(p, 0, &val, &val);
                r = p->in.right;
                if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
                        putstr("movl");
@@ -431,9 +431,9 @@ zzzcode( p, c ) register NODE *p; {
        case 'C':       /* num words pushed on arg stack */
                {
                extern int gc_numbytes;
-               extern int xdebug;
+               extern int x2debug;
 
-               if (xdebug) printf("->%d<-",gc_numbytes);
+               if (x2debug) printf("->%d<-",gc_numbytes);
 
                printf("$%d", gc_numbytes/(SZLONG/SZCHAR) );
                return;
@@ -465,13 +465,13 @@ zzzcode( p, c ) register NODE *p; {
        case 'F':       /* register type of right operand */
                {
                register NODE *n;
-               extern int xdebug;
+               extern int x2debug;
                register int ty;
 
                n = getlr( p, 'R' );
                ty = n->in.type;
 
-               if (xdebug) printf("->%d<-", ty);
+               if (x2debug) printf("->%d<-", ty);
 
                if ( ty==DOUBLE) putchar('d');
                else if ( ty==FLOAT ) putchar('f');
@@ -483,10 +483,10 @@ zzzcode( p, c ) register NODE *p; {
        case 'R':       /* type of right operand */
                {
                register NODE *n;
-               extern int xdebug;
+               extern int x2debug;
 
                n = getlr( p, c );
-               if (xdebug) printf("->%d<-", n->in.type);
+               if (x2debug) printf("->%d<-", n->in.type);
 
                prtype(n);
                return;
@@ -755,9 +755,9 @@ shtemp( p ) register NODE *p; {
 
 shumul( p ) register NODE *p; {
        register o;
-       extern int xdebug;
+       extern int x2debug;
 
-       if (xdebug) {
+       if (x2debug) {
                 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
                printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
                }
diff --git a/lib/pcc/localdefs.h b/lib/pcc/localdefs.h
deleted file mode 100644 (file)
index 42728c7..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*     localdefs.h     4.1     85/03/19        */
-/*
- * Definitions of symbols local to PCC.
- *
- * This file is not included directly by PCC sources -- instead it is
- *     preprocessed along with <pcc.h> to yield two files, pcclocal.h
- *     and pcctokens.  The preprocessing strips off the PCC_ prefix
- *     from all the symbols, since the PCC has no potential clashes...
- */
-
-
-# ifndef       PCC_LOCALTOKENS
-
-# define       PCC_LOCALTOKENS 100
-
-# ifdef        _PASS1_
-
-/*
- * Leftover operators.
- */
-# define       PCC_ASOP        100     /* assignment ops */
-# define       PCC_RELOP       101     /* <=, <, >=, > */
-# define       PCC_EQUOP       102     /* ==, != */
-# define       PCC_DIVOP       103     /* /, % */
-# define       PCC_SHIFTOP     104     /* <<, >> */
-# define       PCC_INCOP       105     /* ++, -- */
-# define       PCC_UNOP        106     /* !, ~ */
-# define       PCC_STROP       107     /* ., -> */
-
-# define       PCC_LP          108     /* ( */
-# define       PCC_RP          109     /* ) */
-# define       PCC_LC          110     /* { */
-# define       PCC_RC          111     /* } */
-
-# endif        _PASS1_
-
-/*
- * C keywords.
- */
-# define       PCC_STRUCT      112
-# define       PCC_IF          113
-# define       PCC_ELSE        114
-# define       PCC_SWITCH      115
-# define       PCC_BREAK       116
-# define       PCC_CONTINUE    117
-# define       PCC_WHILE       118
-# define       PCC_DO          119
-# define       PCC_FOR         120
-# define       PCC_DEFAULT     121
-# define       PCC_CASE        122
-# define       PCC_SIZEOF      123
-# define       PCC_ENUM        124
-# define       PCC_SM          125
-
-# endif        PCC_LOCALTOKENS
index 25f517a..9d592fd 100644 (file)
@@ -64,7 +64,7 @@ extern        int maxargs;
 #define        shltype(o, p) \
        ((o) == REG || (o) == NAME || (o) == ICON || \
         (o) == OREG || ((o) == UNARY MUL && shumul((p)->in.left)))
-#define        ncopy(q, p)     ((q)->in = (p)->in)
+/*#define      ncopy(q, p)     ((q)->in = (p)->in)*/
 
 #define MYREADER(p) myreader(p)
 int    optim2();
index c4fc45d..f14ea55 100644 (file)
@@ -62,7 +62,7 @@ typedef       long    OFFSZ;          /* size in which offsets are kept */
 #define ADDROREG
 #define FIXDEF(p) outstab(p)
 #define FIXARG(p) fixarg(p)
-#ifndef ncopy
+/*#ifndef ncopy*/
 #define        ncopy(q, p)     ((q)->in = (p)->in)
-#endif
+/*#endif*/
 #endif
diff --git a/lib/pcc/manifest.h b/lib/pcc/manifest.h
new file mode 100644 (file)
index 0000000..b5ee1b8
--- /dev/null
@@ -0,0 +1,104 @@
+/*     manifest.h      4.1     85/03/19        */
+
+#ifndef _MANIFEST_
+#define        _MANIFEST_
+
+#include <stdio.h>
+#include "pcclocal.h"
+#include "config.h"
+
+#define DSIZE  (MAXOP+1)       /* DSIZE is the size of the dope array */
+
+#define NOLAB  (-1)            /* no label with constant */
+
+/*
+ * Node types
+ */
+#define LTYPE  02              /* leaf */
+#define UTYPE  04              /* unary */
+#define BITYPE 010             /* binary */
+
+/*
+ * Bogus type values
+ */
+#define TNULL  PTR             /* pointer to UNDEF */
+#define TVOID  FTN             /* function returning UNDEF (for void) */
+
+/*
+ * Type packing constants
+ */
+#define TMASK  060             /* mask for 1st component of compound type */
+#define TMASK1 0300            /* mask for 2nd component of compound type */
+#define TMASK2 0360            /* mask for 3rd component of compound type */
+#define BTMASK 017             /* basic type mask */
+#define BTSHIFT        4               /* basic type shift */
+#define TSHIFT 2               /* shift count to get next type component */
+
+/*
+ * Type manipulation macros
+ */
+#define MODTYPE(x,y)   x = ((x)&(~BTMASK))|(y) /* set basic type of x to y */
+#define BTYPE(x)       ((x)&BTMASK)            /* basic type of x */
+#define ISUNSIGNED(x)  ((x)<=ULONG&&(x)>=UCHAR)
+#define UNSIGNABLE(x)  ((x)<=LONG&&(x)>=CHAR)
+#define ENUNSIGN(x)    ((x)+(UNSIGNED-INT))
+#define DEUNSIGN(x)    ((x)+(INT-UNSIGNED))
+#define ISPTR(x)       (((x)&TMASK)==PTR)
+#define ISFTN(x)       (((x)&TMASK)==FTN)      /* is x a function type */
+#define ISARY(x)       (((x)&TMASK)==ARY)      /* is x an array type */
+#define INCREF(x)      ((((x)&~BTMASK)<<TSHIFT)|PTR|((x)&BTMASK))
+#define DECREF(x)      ((((x)>>TSHIFT)&~BTMASK)|( (x)&BTMASK))
+/* advance x to a multiple of y */
+#define SETOFF(x,y)    if ((x)%(y) != 0) (x) = (((x)/(y) + 1) * (y))
+/* can y bits be added to x without overflowing z */
+#define NOFIT(x,y,z)   (((x)%(z) + (y)) > (z))
+
+/*
+ * Pack and unpack field descriptors (size and offset)
+ */
+#define PKFIELD(s,o)   (((o)<<6)| (s))
+#define UPKFSZ(v)      ((v) &077)
+#define UPKFOFF(v)     ((v)>>6)
+
+/*
+ * Operator information
+ */
+#define TYFLG  016
+#define ASGFLG 01
+#define LOGFLG 020
+
+#define SIMPFLG        040
+#define COMMFLG        0100
+#define DIVFLG 0200
+#define FLOFLG 0400
+#define LTYFLG 01000
+#define CALLFLG        02000
+#define MULFLG 04000
+#define SHFFLG 010000
+#define ASGOPFLG 020000
+
+#define SPFLG  040000
+
+#define optype(o)      (dope[o]&TYFLG)
+#define asgop(o)       (dope[o]&ASGFLG)
+#define logop(o)       (dope[o]&LOGFLG)
+#define callop(o)      (dope[o]&CALLFLG)
+
+/*
+ * External declarations, typedefs and the like
+ */
+#ifdef FLEXNAMES
+char   *hash();
+char   *savestr();
+char   *tstr();
+extern int tstrused;
+extern char *tstrbuf[];
+extern char **curtstr;
+#define        freetstr()      curtstr = tstrbuf, tstrused = 0
+#endif
+
+extern int nerrors;            /* number of errors seen so far */
+extern int dope[];             /* a vector containing operator information */
+extern char *opst[];           /* a vector containing names for ops */
+
+#endif
diff --git a/lib/pcc/match.c b/lib/pcc/match.c
new file mode 100644 (file)
index 0000000..0dbd817
--- /dev/null
@@ -0,0 +1,644 @@
+#ifndef lint
+static char *sccsid ="@(#)match.c      4.4 (Berkeley) 8/22/85";
+#endif lint
+
+# include "pass2.h"
+
+# ifdef WCARD1
+# ifdef WCARD2
+# define NOINDIRECT
+# endif
+# endif
+
+extern vdebug;
+
+int fldsz, fldshf;
+
+static int mamask[] = { /* masks for matching dope with shapes */
+       SIMPFLG,                /* OPSIMP */
+       SIMPFLG|ASGFLG,         /* ASG OPSIMP */
+       COMMFLG,        /* OPCOMM */
+       COMMFLG|ASGFLG, /* ASG OPCOMM */
+       MULFLG,         /* OPMUL */
+       MULFLG|ASGFLG,  /* ASG OPMUL */
+       DIVFLG,         /* OPDIV */
+       DIVFLG|ASGFLG,  /* ASG OPDIV */
+       UTYPE,          /* OPUNARY */
+       TYFLG,          /* ASG OPUNARY is senseless */
+       LTYPE,          /* OPLEAF */
+       TYFLG,          /* ASG OPLEAF is senseless */
+       0,              /* OPANY */
+       ASGOPFLG|ASGFLG,        /* ASG OPANY */
+       LOGFLG,         /* OPLOG */
+       TYFLG,          /* ASG OPLOG is senseless */
+       FLOFLG,         /* OPFLOAT */
+       FLOFLG|ASGFLG,  /* ASG OPFLOAT */
+       SHFFLG,         /* OPSHFT */
+       SHFFLG|ASGFLG,  /* ASG OPSHIFT */
+       SPFLG,          /* OPLTYPE */
+       TYFLG,          /* ASG OPLTYPE is senseless */
+       };
+
+int sdebug = 0;
+
+tshape( p, shape ) NODE *p; {
+       /* return true if shape is appropriate for the node p
+          side effect for SFLD is to set up fldsz,etc */
+       register o, mask;
+
+       o = p->in.op;
+
+# ifndef BUG3
+       if( sdebug ){
+               printf( "tshape( %o, ", p );
+               prcook( shape );
+               printf( " ) op = %s\n", opst[o] );
+               }
+# endif
+
+       if( shape & SPECIAL ){
+
+               switch( shape ){
+
+               case SZERO:
+               case SONE:
+               case SMONE:
+               case SSCON:
+               case SCCON:
+                       if( o != ICON || p->in.name[0] ) return(0);
+                       if( p->tn.lval == 0 && shape == SZERO ) return(1);
+                       else if( p->tn.lval == 1 && shape == SONE ) return(1);
+                       else if( p->tn.lval == -1 && shape == SMONE ) return(1);
+                       else if( p->tn.lval > -129 && p->tn.lval < 128 && shape == SCCON ) return(1);
+                       else if( p->tn.lval > -32769 && p->tn.lval < 32768 && shape == SSCON ) return(1);
+                       else return(0);
+
+               case SSOREG:    /* non-indexed OREG */
+                       if( o == OREG && !R2TEST(p->tn.rval) ) return(1);
+                       else return(0);
+
+               default:
+# ifdef MULTILEVEL
+                       if( shape & MULTILEVEL )
+                               return( mlmatch(p,shape,0) );
+                       else
+# endif
+                       return( special( p, shape ) );
+                       }
+               }
+
+       if( shape & SANY ) return(1);
+
+       if( (shape&INTEMP) && shtemp(p) ) return(1);
+
+       if( (shape&SWADD) && (o==NAME||o==OREG) ){
+               if( BYTEOFF(p->tn.lval) ) return(0);
+               }
+
+# ifdef WCARD1
+       if( shape & WCARD1 )
+               return( wcard1(p) & shape );
+# endif
+
+# ifdef WCARD2
+       if( shape & WCARD2 )
+               return( wcard2(p) & shape );
+# endif
+       switch( o ){
+
+       case NAME:
+               return( shape&SNAME );
+       case ICON:
+               mask = SCON;
+               return( shape & mask );
+
+       case FLD:
+               if( shape & SFLD ){
+                       if( !flshape( p->in.left ) ) return(0);
+                       /* it is a FIELD shape; make side-effects */
+                       o = p->tn.rval;
+                       fldsz = UPKFSZ(o);
+# ifdef RTOLBYTES
+                       fldshf = UPKFOFF(o);
+# else
+                       fldshf = SZINT - fldsz - UPKFOFF(o);
+# endif
+                       return(1);
+                       }
+               return(0);
+
+       case CCODES:
+               return( shape&SCC );
+
+       case REG:
+               /* distinctions:
+               SAREG   any scalar register
+               STAREG  any temporary scalar register
+               SBREG   any lvalue (index) register
+               STBREG  any temporary lvalue register
+               */
+               mask = isbreg( p->tn.rval ) ? SBREG : SAREG;
+               if( istreg( p->tn.rval ) && busy[p->tn.rval]<=1 ) mask |= mask==SAREG ? STAREG : STBREG;
+               return( shape & mask );
+
+       case OREG:
+               return( shape & SOREG );
+
+# ifndef NOINDIRECT
+       case UNARY MUL:
+               /* return STARNM or STARREG or 0 */
+               return( shumul(p->in.left) & shape );
+# endif
+
+               }
+
+       return(0);
+       }
+
+int t2debug = 0;
+
+ttype( t, tword ) TWORD t; {
+       /* does the type t match tword */
+
+       if( tword & TANY ) return(1);
+
+       if( t == UNDEF ) t=INT; /* void functions eased thru tables */
+# ifndef BUG3
+       if( t2debug ){
+               printf( "ttype( %o, %o )\n", t, tword );
+               }
+# endif
+       if( ISPTR(t) && (tword&TPTRTO) ) {
+               do {
+                       t = DECREF(t);
+               } while ( ISARY(t) );
+                       /* arrays that are left are usually only
+                          in structure references... */
+               return( ttype( t, tword&(~TPTRTO) ) );
+               }
+       if( t != BTYPE(t) ) return( tword & TPOINT ); /* TPOINT means not simple! */
+       if( tword & TPTRTO ) return(0);
+
+       switch( t ){
+
+       case CHAR:
+               return( tword & TCHAR );
+       case SHORT:
+               return( tword & TSHORT );
+       case STRTY:
+       case UNIONTY:
+               return( tword & TSTRUCT );
+       case INT:
+               return( tword & TINT );
+       case UNSIGNED:
+               return( tword & TUNSIGNED );
+       case USHORT:
+               return( tword & TUSHORT );
+       case UCHAR:
+               return( tword & TUCHAR );
+       case ULONG:
+               return( tword & TULONG );
+       case LONG:
+               return( tword & TLONG );
+       case FLOAT:
+               return( tword & TFLOAT );
+       case DOUBLE:
+               return( tword & TDOUBLE );
+               }
+
+       return(0);
+       }
+
+struct optab *rwtable;
+
+struct optab *opptr[DSIZE];
+
+setrew(){
+       /* set rwtable to first value which allows rewrite */
+       register struct optab *q;
+       register int i;
+
+# ifdef MULTILEVEL
+       /* also initialize multi-level tree links */
+       mlinit();
+# endif
+
+       for( q = table; q->op != FREE; ++q ){
+               if( q->needs == REWRITE ){
+                       rwtable = q;
+                       goto more;
+                       }
+               }
+       cerror( "bad setrew" );
+
+
+       more:
+       for( i=0; i<DSIZE; ++i ){
+               if( dope[i] ){ /* there is an op... */
+                       for( q=table; q->op != FREE; ++q ){
+                               /*  beware; things like LTYPE that match
+                                   multiple things in the tree must
+                                   not try to look at the NIL at this
+                                   stage of things!  Put something else
+                                   first in table.c  */
+                               /* at one point, the operator matching was 15% of the
+                                   total comile time; thus, the function
+                                   call that was here was removed...
+                               */
+
+                               if( q->op < OPSIMP ){
+                                       if( q->op==i ) break;
+                                       }
+                               else {
+                                       register opmtemp;
+                                       if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
+                                               if( i==NAME || i==ICON || i==OREG ) break;
+                                               else if( shltype( i, NIL ) ) break;
+                                               }
+                                       else if( (dope[i]&(opmtemp|ASGFLG)) == opmtemp ) break;
+                                       }
+                               }
+                       opptr[i] = q;
+                       }
+               }
+       }
+
+match( p, cookie ) NODE *p; {
+       /* called by: order, gencall
+          look for match in table and generate code if found unless
+          entry specified REWRITE.
+          returns MDONE, MNOPE, or rewrite specification from table */
+
+       register struct optab *q;
+       register NODE *r;
+
+       rcount();
+       if( cookie == FORREW ) q = rwtable;
+       else q = opptr[p->in.op];
+
+       for( ; q->op != FREE; ++q ){
+
+               /* at one point the call that was here was over 15% of the total time;
+                   thus the function call was expanded inline */
+               if( q->op < OPSIMP ){
+                       if( q->op!=p->in.op ) continue;
+                       }
+               else {
+                       register opmtemp;
+                       if((opmtemp=mamask[q->op - OPSIMP])&SPFLG){
+                               if( p->in.op!=NAME && p->in.op!=ICON && p->in.op!= OREG &&
+                                       ! shltype( p->in.op, p ) ) continue;
+                               }
+                       else if( (dope[p->in.op]&(opmtemp|ASGFLG)) != opmtemp ) continue;
+                       }
+
+               if( !(q->visit & cookie ) ) continue;
+               r = getlr( p, 'L' );                    /* see if left child matches */
+               if( !tshape( r, q->lshape ) ) continue;
+               if( !ttype( r->in.type, q->ltype ) ) continue;
+               r = getlr( p, 'R' );                    /* see if right child matches */
+               if( !tshape( r, q->rshape ) ) continue;
+               if( !ttype( r->in.type, q->rtype ) ) continue;
+
+                       /* REWRITE means no code from this match but go ahead
+                          and rewrite node to help future match */
+               if( q->needs & REWRITE ) return( q->rewrite );
+               if( !allo( p, q ) ) continue;                   /* if can't generate code, skip entry */
+
+               /* resources are available */
+
+               expand( p, cookie, q->cstring );                /* generate code */
+               reclaim( p, q->rewrite, cookie );
+
+               return(MDONE);
+
+               }
+
+       return(MNOPE);
+       }
+
+int rtyflg = 0;
+
+expand( p, cookie, cp ) NODE *p;  register char *cp; {
+       /* generate code by interpreting table entry */
+
+# ifdef NEWZZZ
+       register char c;
+# endif
+       CONSZ val;
+
+       rtyflg = 0;
+
+       for( ; *cp; ++cp ){
+               switch( *cp ){
+
+               default:
+                       PUTCHAR( *cp );
+                       continue;  /* this is the usual case... */
+
+               case 'T':
+                       /* rewrite register type is suppressed */
+                       rtyflg = 1;
+                       continue;
+
+               case 'Z':  /* special machine dependent operations */
+# ifdef NEWZZZ
+                       switch( c = *++cp ) {
+
+                       case '1':
+                       case '2':
+                       case '3':
+                       case 'R':
+                       case 'L':       /* get down first */
+                               zzzcode( getlr( p, c ), *++cp );
+                               break;
+                       default:   /* normal zzzcode processing otherwise */
+                               zzzcode( p, c );
+                               break;
+                       }
+# else
+                       zzzcode( p, *++cp );
+# endif
+                       continue;
+
+               case 'F':  /* this line deleted if FOREFF is active */
+                       if( cookie & FOREFF ) while( *++cp != '\n' ) ; /* VOID */
+                       continue;
+
+               case 'S':  /* field size */
+                       printf( "%d", fldsz );
+                       continue;
+
+               case 'H':  /* field shift */
+                       printf( "%d", fldshf );
+                       continue;
+
+               case 'M':  /* field mask */
+               case 'N':  /* complement of field mask */
+                       val = 1;
+                       val <<= fldsz;
+                       --val;
+                       val <<= fldshf;
+                       adrcon( *cp=='M' ? val : ~val );
+                       continue;
+
+               case 'L':  /* output special label field */
+                       printf( "%d", p->bn.label );
+                       continue;
+
+               case 'O':  /* opcode string */
+                       hopcode( *++cp, p->in.op );
+                       continue;
+
+               case 'B':  /* byte offset in word */
+                       val = getlr(p,*++cp)->tn.lval;
+                       val = BYTEOFF(val);
+                       printf( CONFMT, val );
+                       continue;
+
+               case 'C': /* for constant value only */
+                       conput( getlr( p, *++cp ) );
+                       continue;
+
+               case 'I': /* in instruction */
+                       insput( getlr( p, *++cp ) );
+                       continue;
+
+               case 'A': /* address of */
+                       adrput( getlr( p, *++cp ) );
+                       continue;
+
+               case 'U': /* for upper half of address, only */
+                       upput( getlr( p, *++cp ) );
+                       continue;
+
+                       }
+
+               }
+
+       }
+
+NODE *
+getlr( p, c ) NODE *p; {
+
+       /* return the pointer to the left or right side of p, or p itself,
+          depending on the optype of p */
+
+       switch( c ) {
+
+       case '1':
+       case '2':
+       case '3':
+               return( &resc[c-'1'] );
+
+       case 'L':
+               return( optype( p->in.op ) == LTYPE ? p : p->in.left );
+
+       case 'R':
+               return( optype( p->in.op ) != BITYPE ? p : p->in.right );
+
+               }
+       cerror( "bad getlr: %c", c );
+       /* NOTREACHED */
+       }
+# ifdef MULTILEVEL
+
+union mltemplate{
+       struct ml_head{
+               int tag; /* identifies class of tree */
+               int subtag; /* subclass of tree */
+               union mltemplate * nexthead; /* linked by mlinit() */
+               } mlhead;
+       struct ml_node{
+               int op; /* either an operator or op description */
+               int nshape; /* shape of node */
+               /* both op and nshape must match the node.
+                * where2 the work is to be done entirely by
+                * op, nshape can be SANY, visa versa, op can
+                * be OPANY.
+                */
+               int ntype; /* type descriptor from mfile2 */
+               } mlnode;
+       };
+
+# define MLSZ 30
+
+extern union mltemplate mltree[];
+int mlstack[MLSZ];
+int *mlsp; /* pointing into mlstack */
+NODE * ststack[MLSZ];
+NODE **stp; /* pointing into ststack */
+
+mlinit(){
+       union mltemplate **lastlink;
+       register union mltemplate *n;
+       register mlop;
+
+       lastlink = &(mltree[0].nexthead);
+       n = &mltree[0];
+       for( ; (n++)->mlhead.tag != 0;
+               *lastlink = ++n, lastlink = &(n->mlhead.nexthead) ){
+# ifndef BUG3
+               if( vdebug )printf("mlinit: %d\n",(n-1)->mlhead.tag);
+# endif
+       /* wander thru a tree with a stack finding
+        * its structure so the next header can be located.
+        */
+               mlsp = mlstack;
+
+               for( ;; ++n ){
+                       if( (mlop = n->mlnode.op) < OPSIMP ){
+                               switch( optype(mlop) ){
+
+                                       default:
+                                               cerror("(1)unknown opcode: %o",mlop);
+                                       case BITYPE:
+                                               goto binary;
+                                       case UTYPE:
+                                               break;
+                                       case LTYPE:
+                                               goto leaf;
+                                       }
+                               }
+                       else{
+                               if( mamask[mlop-OPSIMP] &
+                                       (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
+                               binary:
+                                       *mlsp++ = BITYPE;
+                                       }
+                               else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
+
+                               leaf:
+                                       if( mlsp == mlstack )
+                                               goto tree_end;
+                                       else if ( *--mlsp != BITYPE )
+                                               cerror("(1)bad multi-level tree descriptor around mltree[%d]",
+                                               n-mltree);
+                                       }
+                               }
+                       }
+               tree_end: /* n points to final leaf */
+               ;
+               }
+# ifndef BUG3
+               if( vdebug > 3 ){
+                       printf("mltree={\n");
+                       for( n= &(mltree[0]); n->mlhead.tag != 0; ++n)
+                               printf("%o: %d, %d, %o,\n",n,
+                               n->mlhead.tag,n->mlhead.subtag,n->mlhead.nexthead);
+                       printf("        }\n");
+                       }
+# endif
+       }
+
+mlmatch( subtree, target, subtarget ) NODE * subtree; int target,subtarget;{
+       /*
+        * does subtree match a multi-level tree with
+        * tag "target"?  Return zero on failure,
+        * non-zero subtag on success (or MDONE if
+        * there is a zero subtag field).
+        */
+       union mltemplate *head; /* current template header */
+       register union mltemplate *n; /* node being matched */
+       NODE * st; /* subtree being matched */
+       register int mlop;
+
+# ifndef BUG3
+       if( vdebug ) printf("mlmatch(%o,%d)\n",subtree,target);
+# endif
+       for( head = &(mltree[0]); head->mlhead.tag != 0;
+               head=head->mlhead.nexthead){
+# ifndef BUG3
+               if( vdebug > 1 )printf("mlmatch head(%o) tag(%d)\n",
+                       head->mlhead.tag);
+# endif
+               if( head->mlhead.tag != target )continue;
+               if( subtarget && head->mlhead.subtag != subtarget)continue;
+# ifndef BUG3
+               if( vdebug ) printf("mlmatch for %d\n",target);
+# endif
+
+               /* potential for match */
+
+               n = head + 1;
+               st = subtree;
+               stp = ststack;
+               mlsp = mlstack;
+               /* compare n->op, ->nshape, ->ntype to
+                * the subtree node st
+                */
+               for( ;; ++n ){ /* for each node in multi-level template */
+                       /* opmatch */
+                       if( n->op < OPSIMP ){
+                               if( st->op != n->op )break;
+                               }
+                       else {
+                               register opmtemp;
+                               if((opmtemp=mamask[n->op-OPSIMP])&SPFLG){
+                                       if(st->op!=NAME && st->op!=ICON && st->op!=OREG && 
+                                               ! shltype(st->op,st)) break;
+                                       }
+                               else if((dope[st->op]&(opmtemp|ASGFLG))!=opmtemp) break;
+                               }
+                       /* check shape and type */
+
+                       if( ! tshape( st, n->mlnode.nshape ) ) break;
+                       if( ! ttype( st->type, n->mlnode.ntype ) ) break;
+
+                       /* that node matched, let's try another */
+                       /* must advance both st and n and halt at right time */
+
+                       if( (mlop = n->mlnode.op) < OPSIMP ){
+                               switch( optype(mlop) ){
+
+                                       default:
+                                               cerror("(2)unknown opcode: %o",mlop);
+                                       case BITYPE:
+                                               goto binary;
+                                       case UTYPE:
+                                               st = st->left;
+                                               break;
+                                       case LTYPE:
+                                               goto leaf;
+                                       }
+                               }
+                       else{
+                               if( mamask[mlop - OPSIMP] &
+                                       (SIMPFLG|COMMFLG|MULFLG|DIVFLG|LOGFLG|FLOFLG|SHFFLG) ){
+                               binary:
+                                       *mlsp++ = BITYPE;
+                                       *stp++ = st;
+                                       st = st->left;
+                                       }
+                               else if( ! (mamask[mlop-OPSIMP] & UTYPE) ){/* includes OPANY */
+
+                               leaf:
+                                       if( mlsp == mlstack )
+                                               goto matched;
+                                       else if ( *--mlsp != BITYPE )
+                                               cerror("(2)bad multi-level tree descriptor around mltree[%d]",
+                                               n-mltree);
+                                       st = (*--stp)->right;
+                                       }
+                               else /* UNARY */ st = st->left;
+                               }
+                       continue;
+
+                       matched:
+                       /* complete multi-level match successful */
+# ifndef BUG3
+                       if( vdebug ) printf("mlmatch() success\n");
+# endif
+                       if( head->mlhead.subtag == 0 ) return( MDONE );
+                       else {
+# ifndef BUG3
+                               if( vdebug )printf("\treturns %d\n",
+                                       head->mlhead.subtag );
+# endif
+                               return( head->mlhead.subtag );
+                               }
+                       }
+               }
+       return( 0 );
+       }
+# endif
diff --git a/lib/pcc/ndu.h b/lib/pcc/ndu.h
new file mode 100644 (file)
index 0000000..827f9ea
--- /dev/null
@@ -0,0 +1,83 @@
+/*     ndu.h   4.1     85/03/19        */
+
+/*
+ * This file defines the basic tree node data structure for the PCC.
+ */
+
+typedef        union ndu NODE;
+typedef        unsigned int TWORD;
+#define NIL    (NODE *)0
+
+union ndu {
+       struct {                /* interior node */
+               int     op;
+               int     rall;
+               TWORD   type;
+               int     su;
+#ifndef FLEXNAMES
+               char    name[NCHNAM];
+#else
+               char    *name;
+               int     stalign;
+#endif
+               NODE    *left;
+               NODE    *right;
+       } in;
+       struct {                /* terminal node */
+               int     op;
+               int     rall;
+               TWORD   type;
+               int     su;
+#ifndef FLEXNAMES
+               char    name[NCHNAM];
+#else
+               char    *name;
+               int     stalign;
+#endif
+               CONSZ   lval;
+               int     rval;
+       } tn;
+       struct {                /* branch node */
+               int     op;
+               int     rall;
+               TWORD   type;
+               int     su;
+               int     label;          /* for use with branching */
+       } bn;
+       struct {                /* structure node */
+               int     op;
+               int     rall;
+               TWORD   type;
+               int     su;
+               int     stsize;         /* sizes of structure objects */
+               int     stalign;        /* alignment of structure objects */
+       } stn;
+       struct {                /* front node */
+               int     op;
+               int     cdim;
+               TWORD   type;
+               int     csiz;
+       } fn;
+       /*
+        * This structure is used when a double precision
+        * floating point constant is being computed
+        */
+       struct {                        /* DCON node */
+               int     op;
+               TWORD   type;
+               int     cdim;
+               int     csiz;
+               double  dval;
+       } dpn;
+       /*
+        * This structure is used when a single precision
+        * floating point constant is being computed
+        */
+       struct {                        /* FCON node */
+               int     op;
+               TWORD   type;
+               int     cdim;
+               int     csiz;
+               float   fval;
+       } fpn;
+};
diff --git a/lib/pcc/optim.c b/lib/pcc/optim.c
new file mode 100644 (file)
index 0000000..3a11fe6
--- /dev/null
@@ -0,0 +1,276 @@
+#ifndef lint
+static char *sccsid ="@(#)optim.c      4.7 (Berkeley) 1/8/86";
+#endif lint
+
+# include "pass1.h"
+
+# define SWAP(p,q) {sp=p; p=q; q=sp;}
+# define RCON(p) (p->in.right->in.op==ICON)
+# define RO(p) p->in.right->in.op
+# define RV(p) p->in.right->tn.lval
+# define LCON(p) (p->in.left->in.op==ICON)
+# define LO(p) p->in.left->in.op
+# define LV(p) p->in.left->tn.lval
+
+       /* is p a constant without a name */
+# define nncon(p)      ((p)->in.op == ICON && (p)->tn.rval == NONAME)
+
+int oflag = 0;
+
+NODE *
+fortarg( p ) NODE *p; {
+       /* fortran function arguments */
+
+       if( p->in.op == CM ){
+               p->in.left = fortarg( p->in.left );
+               p->in.right = fortarg( p->in.right );
+               return(p);
+               }
+
+       while( ISPTR(p->in.type) ){
+               p = buildtree( UNARY MUL, p, NIL );
+               }
+       return( optim(p) );
+       }
+
+       /* mapping relationals when the sides are reversed */
+short revrel[] ={ EQ, NE, GE, GT, LE, LT, UGE, UGT, ULE, ULT };
+NODE *
+optim(p) register NODE *p; {
+       /* local optimizations, most of which are probably machine independent */
+
+       register o, ty;
+       NODE *sp;
+       int i;
+       TWORD t;
+
+       if( (t=BTYPE(p->in.type))==ENUMTY || t==MOETY ) econvert(p);
+       if( oflag ) return(p);
+       ty = optype( o=p->in.op);
+       if( ty == LTYPE ) return(p);
+
+       if( ty == BITYPE ) p->in.right = optim(p->in.right);
+       p->in.left = optim(p->in.left);
+
+       /* collect constants */
+
+       switch(o){
+
+       case SCONV:
+       case PCONV:
+               return( clocal(p) );
+
+       case FORTCALL:
+               p->in.right = fortarg( p->in.right );
+               break;
+
+       case UNARY AND:
+               if( LO(p) != NAME || !andable(p->in.left) ) return(p);
+
+               LO(p) = ICON;
+
+               setuleft:
+               /* paint over the type of the left hand side with the type of the top */
+               p->in.left->in.type = p->in.type;
+               p->in.left->fn.cdim = p->fn.cdim;
+               p->in.left->fn.csiz = p->fn.csiz;
+               p->in.op = FREE;
+               return( p->in.left );
+
+       case UNARY MUL:
+               if( LO(p) != ICON ) break;
+               LO(p) = NAME;
+               goto setuleft;
+
+       case MINUS:
+               if( !nncon(p->in.right) ) break;
+               RV(p) = -RV(p);
+               o = p->in.op = PLUS;
+
+       case MUL:
+       case PLUS:
+       case AND:
+       case OR:
+       case ER:
+               /* commutative ops; for now, just collect constants */
+               /* someday, do it right */
+               if( nncon(p->in.left) || ( LCON(p) && !RCON(p) ) ) SWAP( p->in.left, p->in.right );
+               /* make ops tower to the left, not the right */
+               if( RO(p) == o ){
+                       NODE *t1, *t2, *t3;
+                       t1 = p->in.left;
+                       sp = p->in.right;
+                       t2 = sp->in.left;
+                       t3 = sp->in.right;
+                       /* now, put together again */
+                       p->in.left = sp;
+                       sp->in.left = t1;
+                       sp->in.right = t2;
+                       p->in.right = t3;
+                       }
+               if(o == PLUS && LO(p) == MINUS && RCON(p) && RCON(p->in.left) &&
+                  conval(p->in.right, MINUS, p->in.left->in.right)){
+                       zapleft:
+                       RO(p->in.left) = FREE;
+                       LO(p) = FREE;
+                       p->in.left = p->in.left->in.left;
+               }
+               if( RCON(p) && LO(p)==o && RCON(p->in.left) &&
+                   conval( p->in.right, o, p->in.left->in.right ) ){
+                       goto zapleft;
+                       }
+               else if( LCON(p) && RCON(p) &&
+                        conval( p->in.left, o, p->in.right ) ){
+                       zapright:
+                       RO(p) = FREE;
+                       p->in.left = makety( p->in.left, p->in.type, p->fn.cdim, p->fn.csiz );
+                       p->in.op = FREE;
+                       return( clocal( p->in.left ) );
+                       }
+               /* FALL THROUGH */
+
+       case ASG MUL:
+               /* change muls to adds or shifts */
+
+               if( (o == MUL || o == ASG MUL) &&
+                   nncon(p->in.right) && (i=ispow2(RV(p)))>=0){
+                       if( i == 0 ) /* multiplication by 1 */
+                               goto zapright;
+                       /* c2 will turn 'i << 1' into 'i + i' for us */
+                       else {
+                               p->in.op = (asgop(o) ? ASG LS : LS);
+                               o = p->in.op;
+                               p->in.right->in.type = p->in.right->fn.csiz = INT;
+                               RV(p) = i;
+                               }
+                       }
+
+               /* change +'s of negative consts back to - */
+               if( o==PLUS && nncon(p->in.right) && RV(p)<0 ){
+                       RV(p) = -RV(p);
+                       o = p->in.op = MINUS;
+                       }
+               /* FALL THROUGH */
+       case ASG AND:
+       case ASG PLUS:
+       case ASG MINUS:
+       case RS:
+       case LS:
+               /* Operations with zero */
+               if( nncon(p->in.right) && RV(p) == 0 ) {
+                       if( o == MUL || o == ASG MUL ||
+                           o == AND || o == ASG AND ) {
+                               if( asgop(o) )
+                                       p->in.op = ASSIGN;
+                               else if( optype(LO(p)) == LTYPE ) {
+                                       p->in.op = FREE;
+                                       LO(p) = FREE;
+                                       p = p->in.right;
+                                       }
+                               else
+                                       p->in.op = COMOP; /* side effects */
+                               }
+                       else if( o == PLUS || o == MINUS ||
+                                o == ASG PLUS || o == ASG MINUS ||
+                                o == OR || o == ER ||
+                                o == LS || o == RS )
+                               goto zapright;
+                       }
+               if( o != LS && o != RS )
+                       break;
+               /* FALL THROUGH */
+
+       case ASG RS:
+       case ASG LS:
+               if( !ISUNSIGNED(p->in.left->in.type) )
+                       break;
+               if( p->in.right->in.op == ICON &&
+                   p->in.right->tn.lval < 0 ) {
+                       /*
+                        * Technically negative shifts are illegal
+                        * but we can support them, at least with
+                        * constants; you take potluck with variables.
+                        */
+                       p->in.right->tn.lval = -p->in.right->tn.lval;
+                       switch( o ){
+                       case LS:        p->in.op = RS; break;
+                       case ASG LS:    p->in.op = ASG RS; break;
+                       case RS:        p->in.op = LS; break;
+                       case ASG RS:    p->in.op = ASG LS; break;
+                               }
+                       }
+               break;
+
+       case ASG DIV:
+       case DIV:
+               if( nncon( p->in.right ) ){
+                       if( RV(p) == 0 ) uerror("division by zero");
+                       else if( RV(p) == 1 ) goto zapright;
+                       /* Unsigned division by a power of two */
+                       else if( (i=ispow2(RV(p)))>=0 &&
+                                (ISUNSIGNED(p->in.left->in.type) ||
+                                 ISUNSIGNED(p->in.right->in.type)) ){
+                               p->in.op = (asgop(o) ? ASG RS : RS);
+                               p->in.right->in.type = p->in.right->fn.csiz = INT;
+                               RV(p) = i;
+                               }
+                       }
+               break;
+
+       case ASG MOD:
+       case MOD:
+               if( nncon(p->in.right) ){
+                       if( RV(p) == 0 ) uerror("modulus of zero");
+                       else if( RV(p) == 1 ){ /* mod by one gives zero */
+                               RV(p) = 0;
+                               if( asgop(o) )
+                                       p->in.op = ASSIGN;
+                               else if( optype(LO(p)) == LTYPE ) {
+                                       p->in.op = FREE;
+                                       LO(p) = FREE;
+                                       p = p->in.right;
+                                       }
+                               else
+                                       p->in.op = COMOP; /* side effects */
+                               }
+                       else if ((i=ispow2(RV(p)))>=0 &&
+                                (ISUNSIGNED(p->in.left->in.type) ||
+                                 ISUNSIGNED(p->in.right->in.type)) ){
+                               /* Unsigned mod by a power of two */
+                               p->in.op = (asgop(o) ? ASG AND : AND);
+                               RV(p)--;
+                               }
+                       }
+               break;
+
+       case EQ:
+       case NE:
+       case LT:
+       case LE:
+       case GT:
+       case GE:
+       case ULT:
+       case ULE:
+       case UGT:
+       case UGE:
+               if( !LCON(p) ) break;
+
+               /* exchange operands */
+
+               sp = p->in.left;
+               p->in.left = p->in.right;
+               p->in.right = sp;
+               p->in.op = revrel[p->in.op - EQ ];
+               break;
+
+               }
+
+       return(p);
+       }
+
+ispow2( c ) CONSZ c; {
+       register i;
+       if( c <= 0 || (c&(c-1)) ) return(-1);
+       for( i=0; c>1; ++i) c >>= 1;
+       return(i);
+       }
index 13e074a..11e4acb 100644 (file)
@@ -436,13 +436,13 @@ setasop( p ) register NODE *p; {
        /*NOTREACHED*/
        }
 
-int crslab = 99999;  /* VAX */
+int crs2lab = 99999;  /* VAX */
 
-getlab(){
-       return( crslab-- );
+get2lab(){
+       return( crs2lab-- );
        }
 
-deflab( l ){
+def2lab( l ){
        printf( "L%d:\n", l );
        }
 
diff --git a/lib/pcc/pass1.h b/lib/pcc/pass1.h
new file mode 100644 (file)
index 0000000..c4b2dc9
--- /dev/null
@@ -0,0 +1,233 @@
+/*     pass1.h 4.2     85/08/22        */
+
+#ifndef _PASS1_
+#define        _PASS1_
+
+#include "macdefs.h"
+#include "manifest.h"
+#include "ndu.h"
+
+/*
+ * Symbol table definition.
+ *
+ * Colliding entries are moved down with a standard
+ * probe (no quadratic rehash here) and moved back when
+ * entries are cleared.
+ */
+struct symtab {
+#ifndef FLEXNAMES
+       char    sname[NCHNAM];
+#else
+       char    *sname;
+#endif
+       struct  symtab *snext;  /* link to other symbols in the same scope */
+       TWORD   stype;          /* type word */
+       char    sclass;         /* storage class */
+       char    slevel;         /* scope level */
+       char    sflags;         /* flags, see below */
+       int     offset;         /* offset or value */
+       short   dimoff;         /* offset into the dimension table */
+       short   sizoff;         /* offset into the size table */
+       int     suse;           /* line number of last use of the variable */
+};
+
+/*
+ * Storage classes
+ */
+#define SNULL          0               /* initial value */
+#define AUTO           1               /* automatic (on stack) */
+#define EXTERN         2               /* external reference */
+#define STATIC         3               /* static scope */
+#define REGISTER       4               /* register requested */
+#define EXTDEF         5               /* external definition */
+#define LABEL          6               /* label definition */
+#define ULABEL         7               /* undefined label reference */
+#define MOS            8               /* member of structure */
+#define PARAM          9               /* parameter */
+#define STNAME         10              /* structure name */
+#define MOU            11              /* member of union */
+#define UNAME          12              /* union name */
+#define TYPEDEF                13              /* typedef name */
+#define FORTRAN                14              /* fortran function */
+#define ENAME          15              /* enumeration name */
+#define MOE            16              /* member of enumeration */
+#define UFORTRAN       17              /* undefined fortran reference */
+#define USTATIC                18              /* undefined static reference */
+
+/* field size is ORed in */
+#define FIELD          0100
+#define FLDSIZ         077
+#ifndef BUG1
+extern char *scnames();
+#endif
+
+/*
+ * Symbol table flags
+ */
+#define SMOS           01              /* member of structure */
+#define SHIDDEN                02              /* hidden in current scope */
+#define SHIDES         04              /* hides symbol in outer scope */
+#define SSET           010             /* symbol assigned to */
+#define SREF           020             /* symbol referenced */
+#define SNONUNIQ       040             /* non-unique structure member */
+#define STAG           0100            /* structure tag name */
+
+/*
+ * Location counters
+ */
+#define PROG           0               /* program segment */
+#define DATA           1               /* data segment */
+#define ADATA          2               /* array data segment */
+#define STRNG          3               /* string data segment */
+#define ISTRNG         4               /* initialized string segment */
+#define STAB           5               /* symbol table segment */
+
+#ifndef FIXDEF
+#define FIXDEF(p)
+#endif
+#ifndef FIXARG
+#define FIXARG(p)
+#endif
+#ifndef FIXSTRUCT
+#define FIXSTRUCT(a,b)
+#endif
+
+       /* alignment of initialized quantities */
+#ifndef AL_INIT
+#define        AL_INIT ALINT
+#endif
+
+/*
+ * External definitions
+ */
+struct sw {            /* switch table */
+       CONSZ   sval;   /* case value */
+       int     slab;   /* associated label */
+};
+extern struct sw swtab[];
+extern struct sw *swp;
+extern int swx;
+
+extern int ftnno;
+extern int blevel;
+extern int instruct, stwart;
+
+extern int lineno, nerrors;
+
+extern CONSZ lastcon;
+extern float fcon;
+extern double dcon;
+
+extern char ftitle[];
+extern char ititle[];
+extern struct symtab stab[];
+extern int curftn;
+extern int curclass;
+extern int curdim;
+extern int dimtab[];
+extern int paramstk[];
+extern int paramno;
+extern int autooff, argoff, strucoff;
+extern int regvar;
+extern int minrvar;
+extern int brkflag;
+typedef union {
+       int intval;
+       NODE * nodep;
+       } YYSTYPE;
+extern YYSTYPE yylval;
+extern char yytext[];
+
+extern int strflg;
+
+extern OFFSZ inoff;
+
+extern int reached;
+
+/* tunnel to buildtree for name id's */
+extern int idname;
+
+extern NODE node[];
+extern NODE *lastfree;
+
+extern int cflag, hflag, pflag;
+
+/* various labels */
+extern int brklab;
+extern int contlab;
+extern int flostat;
+extern int retlab;
+extern int retstat;
+extern int asavbc[], *psavbc;
+
+/* declarations of various functions */
+extern NODE
+       *buildtree(),
+       *bdty(),
+       *mkty(),
+       *rstruct(),
+       *dclstruct(),
+       *getstr(),
+       *tymerge(),
+       *stref(),
+       *offcon(),
+       *bcon(),
+       *bpsize(),
+       *convert(),
+       *pconvert(),
+       *oconvert(),
+       *ptmatch(),
+       *tymatch(),
+       *makety(),
+       *block(),
+       *doszof(),
+       *talloc(),
+       *optim(),
+       *fixargs(),
+       *clocal();
+OFFSZ  tsize(),
+       psize();
+TWORD  types();
+double atof();
+char   *exname(), *exdcon();
+
+#define checkst(x)
+
+#ifndef CHARCAST
+/* to make character constants into character connstants */
+/* this is a macro to defend against cross-compilers, etc. */
+#define CHARCAST(x) (char)(x)
+#endif
+
+/*
+ * Flags used in structures/unions
+ */
+#define SEENAME                01
+#define INSTRUCT       02
+#define INUNION                04
+#define FUNNYNAME      010
+#define TAGNAME                020
+
+/*
+ * Flags used in the (elementary) flow analysis ...
+ */
+#define FBRK           02
+#define FCONT          04
+#define FDEF           010
+#define FLOOP          020
+
+/*
+ * Flags used for return status
+ */
+#define RETVAL         1
+#define NRETVAL                2
+
+#define NONAME         040000          /* marks constant w/o name field */
+#define NOOFFSET       (-10201)        /* mark an offset which is undefined */
+
+/* NOPREF must be defined for use in first pass tree machine */
+/* for some reason this is only used in pass1 if it's the one-pass compiler */
+/* see pass2.h for the complete set of bits that can be on in the same word */
+#define NOPREF 020000          /* no preference for register assignment */
+
+#endif
diff --git a/lib/pcc/pass1.txt b/lib/pcc/pass1.txt
new file mode 100644 (file)
index 0000000..841bba4
--- /dev/null
@@ -0,0 +1,9 @@
+code.c
+comm1.c
+local.c
+optim.c
+pftn.c
+scan.c
+stab.c
+trees.c
+xdefs.c
diff --git a/lib/pcc/pass2.h b/lib/pcc/pass2.h
new file mode 100644 (file)
index 0000000..d6e35ab
--- /dev/null
@@ -0,0 +1,225 @@
+/*     pass2.h 4.1     85/03/19        */
+
+#ifndef _PASS2_
+#define        _PASS2_
+
+#include "macdefs.h"
+#include "mac2defs.h"
+#include "manifest.h"
+#include "ndu.h"
+
+/* cookies, used as arguments to codgen */
+#define FOREFF 01              /* compute for effects only */
+#define INAREG 02              /* compute into a register */
+#define INTAREG        04              /* compute into a scratch register */
+#define INBREG 010             /* compute into a lvalue register */
+#define INTBREG 020            /* compute into a scratch lvalue register */
+#define FORCC  040             /* compute for condition codes only */
+#define INTEMP 010000          /* compute into a temporary location */
+#define FORARG 020000          /* compute for an argument of a function */
+#define FORREW 040000          /* search the table for a rewrite rule */
+
+/*
+ * OP descriptors,
+ * the ASG operator may be used on some of these
+ */
+#define OPSIMP 010000          /* +, -, &, |, ^ */
+#define OPCOMM 010002          /* +, &, |, ^ */
+#define OPMUL  010004          /* *, / */
+#define OPDIV  010006          /* /, % */
+#define OPUNARY        010010          /* unary ops */
+#define OPLEAF 010012          /* leaves */
+#define OPANY  010014          /* any op... */
+#define OPLOG  010016          /* logical ops */
+#define OPFLOAT        010020          /* +, -, *, or / (for floats) */
+#define OPSHFT 010022          /* <<, >> */
+#define OPLTYPE        010024          /* leaf type nodes (e.g, NAME, ICON, etc.) */
+
+/* match returns */
+#define MNOPE  010000          /* no match generated */
+#define MDONE  010001          /* done evalution */
+
+/* shapes */
+#define SANY   01              /* same as FOREFF */
+#define SAREG  02              /* same as INAREG */
+#define STAREG 04              /* same as INTAREG */
+#define SBREG  010             /* same as INBREG */
+#define STBREG 020             /* same as INTBREG */
+#define SCC    040             /* same as FORCC */
+#define SNAME  0100            /* name */
+#define SCON   0200            /* constant */
+#define SFLD   0400            /* field */
+#define SOREG  01000           /* offset from register */
+/* indirection or wild card shapes */
+#ifndef WCARD1
+#define STARNM 02000           /* indirect through name */
+#endif
+#ifndef WCARD2
+#define STARREG        04000           /* indirect through register */
+#endif
+#define SWADD  040000          /* word address */
+#define SPECIAL        0100000         /* special stuff (follows) */
+#define SZERO  SPECIAL         /* constant zero */
+#define SONE   (SPECIAL|1)     /* constant +1 */
+#define SMONE  (SPECIAL|2)     /* constant -1 */
+#define SCCON  (SPECIAL|3)     /* -256 <= constant < 256 */
+#define SSCON  (SPECIAL|4)     /* -32768 <= constant < 32768 */
+#define SSOREG (SPECIAL|5)     /* non-indexed OREG */
+/* FORARG and INTEMP are carefully not conflicting with shapes */
+
+/* types */
+#define TCHAR          01      /* char */
+#define TSHORT         02      /* short */
+#define TINT           04      /* int */
+#define TLONG          010     /* long */
+#define TFLOAT         020     /* float */
+#define TDOUBLE                040     /* double */
+#define TPOINT         0100    /* pointer to something */
+#define TUCHAR         0200    /* unsigned char */
+#define TUSHORT                0400    /* unsigned short */
+#define TUNSIGNED      01000   /* unsigned int */
+#define TULONG         02000   /* unsigned long */
+#define TPTRTO         04000   /* pointer to one of the above */
+#define TANY           010000  /* matches anything within reason */
+#define TSTRUCT                020000  /* structure or union */
+
+/* reclamation cookies */
+#define RNULL          0       /* clobber result */
+#define RLEFT          01      /* reclaim left resource */
+#define RRIGHT         02      /* reclaim right resource */
+#define RESC1          04      /* reclaim resource allocated #1 */
+#define RESC2          010     /* reclaim resource allocated #2 */
+#define RESC3          020     /* reclaim resource allocated #3 */
+#define RESCC          04000   /* reclaim condition codes */
+#define RNOP           010000  /* DANGER: can cause loops.. */
+
+/* needs */
+#define NAREG          01      /* need an A register */
+#define NACOUNT                03      /* count mask of A registers */
+#define NAMASK         017     /* A register need field mask */
+#define NASL           04      /* need A register shared with left resource */
+#define NASR           010     /* need A register shared with right resource */
+#define NBREG          020     /* need a B register */
+#define NBCOUNT                060     /* count mask of B register */
+#define NBMASK         0360    /* B register need field mask */
+#define NBSL           0100    /* need B register shared with left resource */
+#define NBSR           0200    /* need B register shared with right resource */
+#define NTEMP          0400    /* need temporary storage location */
+#define NTMASK         07400   /* count mask of temporary storage locations */
+#define REWRITE                010000  /* need rewrite */
+#define EITHER         040000  /* allocate all resources or nothing */
+
+#define MUSTDO         010000  /* force register requirements */
+#ifndef NOPREF
+/* also defined in onepass.h */
+#define NOPREF         020000  /* no preference for register assignment */
+#endif
+
+/* register allocation */
+extern int rstatus[];          /* register status info */
+extern int busy[];             /* register use info */
+extern struct respref {
+       int     cform;
+       int     mform;
+} respref[];                   /* resource preference rules */
+
+#define isbreg(r)      (rstatus[r]&SBREG)
+#define istreg(r)      (rstatus[r]&(STBREG|STAREG))
+#define istnode(p)     (p->in.op==REG && istreg(p->tn.rval))
+
+#define TBUSY          01000   /* register temporarily busy (during alloc) */
+#define REGLOOP(i)     for (i = 0; i < REGSZ; ++i)
+
+extern NODE *deltrees[DELAYS]; /* trees held for delayed evaluation */
+extern int deli;               /* mmmmm */
+
+#define SETSTO(x,y)    (stotree = (x), stocook = (y))
+extern int stocook;
+extern NODE *stotree;
+extern int callflag;
+
+extern int fregs;
+
+extern NODE node[];
+
+/* code tables */
+extern struct optab {
+       int     op;                     /* operator to match */
+       int     visit;                  /* goal to match */
+       int     lshape;                 /* left shape to match */
+       int     ltype;                  /* left type to match */
+       int     rshape;                 /* right shape to match */
+       int     rtype;                  /* right type to match */
+       int     needs;                  /* resource required */
+       int     rewrite;                /* how to rewrite afterwards */
+       char    *cstring;               /* code generation template */
+} table[];
+
+extern NODE resc[];
+
+extern OFFSZ tmpoff;
+extern OFFSZ maxoff;
+extern OFFSZ baseoff;
+extern OFFSZ maxtemp;
+extern int maxtreg;
+extern int ftnno;
+extern int rtyflg;
+extern int nrecur;             /* flag to keep track of recursions */
+
+extern NODE
+       *talloc(),
+       *eread(),
+       *tcopy(),
+       *getlr();
+
+extern CONSZ rdin();
+extern int e2print();
+extern char *rnames[];
+
+extern int lineno;
+extern char ftitle[];
+extern int fldshf, fldsz;
+extern int lflag, x2debug, udebug, e2debug, odebug;
+extern int rdebug, radebug, t2debug, sdebug;
+#ifdef FORT
+extern int Oflag;
+#endif
+
+#ifndef callchk
+#define callchk(x) allchk()
+#endif
+
+#ifndef PUTCHAR
+#define PUTCHAR(x) putchar(x)
+#endif
+
+/* macros for doing double indexing */
+#define R2PACK(x,y,z)  (0200*((x)+1)+y+040000*z)       /* pack 3 regs */
+#define R2UPK1(x)      ((((x)>>7)-1)&0177)             /* unpack reg 1 */
+#define R2UPK2(x)      ((x)&0177)                      /* unpack reg 2 */
+#define R2UPK3(x)      (x>>14)                         /* unpack reg 3 */
+#define R2TEST(x)      ((x)>=0200)                     /* test if packed */
+
+#ifdef MULTILEVEL
+union  mltemplate {
+       struct ml_head {
+               int     tag;                    /* tree class */
+               int     subtag;                 /* subclass of tree */
+               union   mltemplate *nexthead;   /* linked by mlinit() */
+       } mlhead;
+       struct ml_node {
+               int     op;                     /* operator or op description */
+               int     nshape;                 /* node shape */
+               /*
+                * Both op and nshape must match the node.
+                * where2 the work is to be done entirely by
+                * op, nshape can be SANY, visa versa, op can
+                * be OPANY.
+                */
+               int     ntype;                  /* type descriptor */
+       } mlnode;
+};
+extern union mltemplate mltree[];
+#endif
+
+#endif
diff --git a/lib/pcc/pass2.txt b/lib/pcc/pass2.txt
new file mode 100644 (file)
index 0000000..e1ade87
--- /dev/null
@@ -0,0 +1,7 @@
+allo.c
+fort.c
+local2.c
+match.c
+order.c
+reader.c
+table.c
diff --git a/lib/pcc/pcclocal.h b/lib/pcc/pcclocal.h
new file mode 100644 (file)
index 0000000..0e7ce72
--- /dev/null
@@ -0,0 +1,155 @@
+/*#ifndef _H_*/
+/*# ifndef     TOKENS*/
+# define       TOKENS  0
+# define       ERROR   1       /* an error node */
+# define       FREE    2       /* an unused node */
+# define       STRING  3       /* a string constant */
+# define       ICON    4       /* an integer constant */
+# define       FCON    5       /* a floating point constant */
+# define       DCON    6       /* a double precision f.p. constant */
+# define       NAME    7       /* an identifier */
+# define       REG             8       /* a register */
+# define       OREG    9       /* register and offset */
+# define       CCODES  10      /* condition codes */
+# define       FLD             11      /* a bit field */
+# define       PLUS    12      /* + */
+# define       PLUSEQ  13      /* += */
+# define       UPLUS   14      /* unary + (for completeness) */
+# define       MINUS   15      /* - */
+# define       MINUSEQ 16      /* -= */
+# define       UMINUS  17      /* unary - */
+# define       MUL             18      /* * */
+# define       MULEQ   19      /* *= */
+# define       DIV             21      /* / */
+# define       DIVEQ   22      /* /= */
+# define       MOD             23      /* % */
+# define       MODEQ   24      /* %= */
+# define       INCR    25      /* ++ */
+# define       DECR    26      /* -- */
+# define       ASSIGN  27      /* = (these last 3 are stretching it) */
+# define       AND             28      /* & */
+# define       ANDEQ   29      /* &= */
+# define       OR              31      /* | */
+# define       OREQ    32      /* |= */
+# define       ER              33      /* ^ */
+# define       EREQ    34      /* ^= */
+# define       LS              35      /* << */
+# define       LSEQ    36      /* <<= */
+# define       RS              37      /* >> */
+# define       RSEQ    38      /* >>= */
+# define       COMPL   39      /* ~ */
+# define       EQ              40      /* == */
+# define       NE              41      /* != */
+# define       LE              42      /* <= */
+# define       LT              43      /* < */
+# define       GE              44      /* >= */
+# define       GT              45      /* > */
+# define       ULE             46      /* unsigned <= */
+# define       ULT             47      /* unsigned < */
+# define       UGE             48      /* unsigned >= */
+# define       UGT             49      /* unsigned > */
+# define       QUEST   50      /* ? (for conditional expressions) */
+# define       COLON   51      /* : (for conditional expressions) */
+# define       ANDAND  52      /* && */
+# define       OROR    53      /* || */
+# define       NOT             54      /* ! */
+# define       CALL    55      /* call by value */
+# define       UCALL   57      /* call with no arguments */
+# define       FORTCALL        58      /* call by reference? */
+# define       UFORTCALL       60      /* ??? */
+# ifdef INLINE
+# define       INLINE  61      /* inline function */
+# define       UINLINE 63      /* inline with no arguments */
+# endif
+# define       DEREF   20      /* * */
+# define       ADDROF  30      /* & */
+# define       DOT             64      /* . */
+# define       STREF   65      /* -> */
+# define       STASG   66      /* structure assignment */
+# define       STARG   67      /* an argument of type structure */
+# define       STCALL  68      /* a function of type structure */
+# define       USTCALL 70      /* unary structure function */
+# define       SCONV   71      /* scalar conversion */
+# define       PCONV   72      /* pointer conversion */
+# define       PMCONV  73      /* pointer multiply conversion */
+# define       PVCONV  74      /* pointer divide conversion */
+# define       CAST    75      /* redundant? */
+# define       LB              76      /* [ */
+# define       RB              77      /* ] */
+# define       COMOP   78      /* , (in expressions) */
+# define       CM              79      /* , (in argument lists) */
+# define       FORCE   80      /* result of last expression goes in r0 */
+# define       GOTO    81      /* unconditional goto */
+# define       CBRANCH 82      /* goto label if !test */
+# define       RETURN  83      /* return from function */
+# define       INIT    84      /* initialized data */
+# define       TYPE    85      /* a type */
+# define       CLASS   86      /* a storage class */
+# define       MAXOP   86      /* highest numbered PCC op */
+# define       FORTOPS 150
+# define       FTEXT   150     /* pass literal assembler text */
+# define       FEXPR   151     /* a statement */
+# define       FSWITCH 152     /* not implemented */
+# define       FLBRAC  153     /* beginning of subroutine */
+# define       FRBRAC  154     /* end of subroutine */
+# define       FEOF    155     /* end of file */
+# define       FARIF   156     /* not implemented */
+# define       FLABEL  157     /* an f77 label */
+/*# endif*/
+# define       UNDEF   0
+# define       FARG    1       /* function argument */
+# define       CHAR    2
+# define       SHORT   3
+# define       INT     4
+# define       LONG    5
+# define       FLOAT   6
+# define       DOUBLE  7
+# define       STRTY   8
+# define       UNIONTY 9
+# define       ENUMTY  10
+# define       MOETY   11      /* member of enum */
+# define       UCHAR   12
+# define       USHORT  13
+# define       UNSIGNED        14
+# define       ULONG   15
+# define       PTR     020
+# define       FTN     040
+# define       ARY     060
+# define       BASETYPE        017
+# define       TYPESHIFT       2
+# define       ASG     1+
+# define       UNARY   2+
+# define       NOASG   (-1)+
+# define       NOUNARY (-2)+
+/*#endif*/
+/*# ifndef     LOCALTOKENS*/
+# define       LOCALTOKENS     100
+/*# ifdef      _PASS1_*/
+# define       ASOP    100     /* assignment ops */
+# define       RELOP   101     /* <=, <, >=, > */
+# define       EQUOP   102     /* ==, != */
+# define       DIVOP   103     /* /, % */
+# define       SHIFTOP 104     /* <<, >> */
+# define       INCOP   105     /* ++, -- */
+# define       UNOP    106     /* !, ~ */
+# define       STROP   107     /* ., -> */
+# define       LP              108     /* ( */
+# define       RP              109     /* ) */
+# define       LC              110     /* { */
+# define       RC              111     /* } */
+/*# endif      _PASS1_*/
+# define       STRUCT  112
+# define       IF              113
+# define       ELSE    114
+# define       SWITCH  115
+# define       BREAK   116
+# define       CONTINUE        117
+# define       WHILE   118
+# define       DO              119
+# define       FOR             120
+# define       DEFAULT 121
+# define       CASE    122
+# define       SIZEOF  123
+# define       ENUM    124
+# define       SM              125
+/*# endif      LOCALTOKENS*/
diff --git a/lib/pcc/pftn.c b/lib/pcc/pftn.c
new file mode 100644 (file)
index 0000000..a3604d6
--- /dev/null
@@ -0,0 +1,1968 @@
+#ifndef lint
+static char *sccsid ="@(#)pftn.c       1.12 (Berkeley) 4/21/86";
+#endif lint
+
+# include "pass1.h"
+
+unsigned int offsz;
+
+struct symtab *schain[MAXSCOPES];      /* sym chains for clearst */
+int chaintop;                          /* highest active entry */
+
+struct instk {
+       int in_sz;   /* size of array element */
+       int in_x;    /* current index for structure member in structure initializations */
+       int in_n;    /* number of initializations seen */
+       int in_s;    /* sizoff */
+       int in_d;    /* dimoff */
+       TWORD in_t;    /* type */
+       int in_id;   /* stab index */
+       int in_fl;   /* flag which says if this level is controlled by {} */
+       OFFSZ in_off;  /* offset of the beginning of this level */
+       }
+instack[10],
+*pstk;
+
+       /* defines used for getting things off of the initialization stack */
+
+
+struct symtab *relook();
+
+
+int ddebug = 0;
+
+struct symtab * mknonuniq();
+
+defid( q, class ) register NODE *q; register int class; {
+       register struct symtab *p;
+       int idp;
+       register TWORD type;
+       TWORD stp;
+       register int scl;
+       int dsym, ddef;
+       int slev, temp;
+       int changed;
+
+       if( q == NIL ) return;  /* an error was detected */
+
+       if( q < node || q >= &node[TREESZ] ) cerror( "defid call" );
+
+       idp = q->tn.rval;
+
+       if( idp < 0 ) cerror( "tyreduce" );
+       p = &stab[idp];
+
+# ifndef BUG1
+       if( ddebug ){
+#ifndef FLEXNAMES
+               printf( "defid( %.8s (%d), ", p->sname, idp );
+#else
+               printf( "defid( %s (%d), ", p->sname, idp );
+#endif
+               tprint( q->in.type );
+               printf( ", %s, (%d,%d) ), level %d\n", scnames(class), q->fn.cdim, q->fn.csiz, blevel );
+               }
+# endif
+
+       fixtype( q, class );
+
+       type = q->in.type;
+       class = fixclass( class, type );
+
+       stp = p->stype;
+       slev = p->slevel;
+
+# ifndef BUG1
+       if( ddebug ){
+               printf( "       modified to " );
+               tprint( type );
+               printf( ", %s\n", scnames(class) );
+               printf( "       previous def'n: " );
+               tprint( stp );
+               printf( ", %s, (%d,%d) ), level %d\n", scnames(p->sclass), p->dimoff, p->sizoff, slev );
+               }
+# endif
+
+       if( stp == FTN && p->sclass == SNULL )goto enter;
+               /* name encountered as function, not yet defined */
+       if( stp == UNDEF|| stp == FARG ){
+               if( blevel==1 && stp!=FARG ) switch( class ){
+
+               default:
+#ifndef FLEXNAMES
+                       if(!(class&FIELD)) uerror( "declared argument %.8s is missing", p->sname );
+#else
+                       if(!(class&FIELD)) uerror( "declared argument %s is missing", p->sname );
+#endif
+               case MOS:
+               case STNAME:
+               case MOU:
+               case UNAME:
+               case MOE:
+               case ENAME:
+               case TYPEDEF:
+                       ;
+                       }
+               goto enter;
+               }
+
+       if( type != stp ) goto mismatch;
+       /* test (and possibly adjust) dimensions */
+       dsym = p->dimoff;
+       ddef = q->fn.cdim;
+       changed = 0;
+       for( temp=type; temp&TMASK; temp = DECREF(temp) ){
+               if( ISARY(temp) ){
+                       if (dimtab[dsym] == 0) {
+                               dimtab[dsym] = dimtab[ddef];
+                               changed = 1;
+                               }
+                       else if (dimtab[ddef]!=0&&dimtab[dsym]!=dimtab[ddef]) {
+                               goto mismatch;
+                               }
+                       ++dsym;
+                       ++ddef;
+                       }
+               }
+
+       if (changed) {
+               FIXDEF(p);
+               }
+
+       /* check that redeclarations are to the same structure */
+       if( (temp==STRTY||temp==UNIONTY||temp==ENUMTY) && p->sizoff != q->fn.csiz
+                && class!=STNAME && class!=UNAME && class!=ENAME ){
+               goto mismatch;
+               }
+
+       scl = ( p->sclass );
+
+# ifndef BUG1
+       if( ddebug ){
+               printf( "       previous class: %s\n", scnames(scl) );
+               }
+# endif
+
+       if( class&FIELD ){
+               /* redefinition */
+               if( !falloc( p, class&FLDSIZ, 1, NIL ) ) {
+                       /* successful allocation */
+                       psave( idp );
+                       return;
+                       }
+               /* blew it: resume at end of switch... */
+               }
+
+       else switch( class ){
+
+       case EXTERN:
+               switch( scl ){
+               case STATIC:
+               case USTATIC:
+                       if( slev==0 ) return;
+                       break;
+               case EXTDEF:
+               case EXTERN:
+               case FORTRAN:
+               case UFORTRAN:
+                       return;
+                       }
+               break;
+
+       case STATIC:
+               if( scl==USTATIC || (scl==EXTERN && blevel==0) ){
+                       p->sclass = STATIC;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case USTATIC:
+               if( scl==STATIC || scl==USTATIC ) return;
+               break;
+
+       case LABEL:
+               if( scl == ULABEL ){
+                       p->sclass = LABEL;
+                       deflab( p->offset );
+                       return;
+                       }
+               break;
+
+       case TYPEDEF:
+               if( scl == class ) return;
+               break;
+
+       case UFORTRAN:
+               if( scl == UFORTRAN || scl == FORTRAN ) return;
+               break;
+
+       case FORTRAN:
+               if( scl == UFORTRAN ){
+                       p->sclass = FORTRAN;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case MOU:
+       case MOS:
+               if( scl == class ) {
+                       if( oalloc( p, &strucoff ) ) break;
+                       if( class == MOU ) strucoff = 0;
+                       psave( idp );
+                       return;
+                       }
+               break;
+
+       case MOE:
+               if( scl == class ){
+                       if( p->offset!= strucoff++ ) break;
+                       psave( idp );
+                       }
+               break;
+
+       case EXTDEF:
+               if( scl == EXTERN ) {
+                       p->sclass = EXTDEF;
+                       if( ISFTN(type) ) curftn = idp;
+                       return;
+                       }
+               break;
+
+       case STNAME:
+       case UNAME:
+       case ENAME:
+               if( scl != class ) break;
+               if( dimtab[p->sizoff] == 0 ) return;  /* previous entry just a mention */
+               break;
+
+       case ULABEL:
+               if( scl == LABEL || scl == ULABEL ) return;
+       case PARAM:
+       case AUTO:
+       case REGISTER:
+               ;  /* mismatch.. */
+
+               }
+
+       mismatch:
+       /* allow nonunique structure/union member names */
+
+       if( class==MOU || class==MOS || class & FIELD ){/* make a new entry */
+               register int *memp;
+               p->sflags |= SNONUNIQ;  /* old entry is nonunique */
+               /* determine if name has occurred in this structure/union */
+               if (paramno > 0) for( memp = &paramstk[paramno-1];
+                       /* while */ *memp>=0 && stab[*memp].sclass != STNAME
+                               && stab[*memp].sclass != UNAME;
+                       /* iterate */ --memp){ char *cname, *oname;
+                       if( stab[*memp].sflags & SNONUNIQ ){int k;
+                               cname=p->sname;
+                               oname=stab[*memp].sname;
+#ifndef FLEXNAMES
+                               for(k=1; k<=NCHNAM; ++k){
+                                       if(*cname++ != *oname)goto diff;
+                                       if(!*oname++)break;
+                                       }
+#else
+                               if (cname != oname) goto diff;
+#endif
+                               uerror("redeclaration of: %s",p->sname);
+                               break;
+                               diff: continue;
+                               }
+                       }
+               p = mknonuniq( &idp ); /* update p and idp to new entry */
+               goto enter;
+               }
+       if( blevel > slev && class != EXTERN && class != FORTRAN &&
+               class != UFORTRAN && !( class == LABEL && slev >= 2 ) ){
+               q->tn.rval = idp = hide( p );
+               p = &stab[idp];
+               goto enter;
+               }
+#ifndef FLEXNAMES
+       uerror( "redeclaration of %.8s", p->sname );
+#else
+       uerror( "redeclaration of %s", p->sname );
+#endif
+       if( class==EXTDEF && ISFTN(type) ) curftn = idp;
+       return;
+
+       enter:  /* make a new entry */
+
+# ifndef BUG1
+       if( ddebug ) printf( "  new entry made\n" );
+# endif
+       if( type == UNDEF ) uerror("void type for %s",p->sname);
+       p->stype = type;
+       p->sclass = class;
+       p->slevel = blevel;
+       p->offset = NOOFFSET;
+       p->suse = lineno;
+       if( class == STNAME || class == UNAME || class == ENAME ) {
+               p->sizoff = curdim;
+               dstash( 0 );  /* size */
+               dstash( -1 ); /* index to members of str or union */
+               dstash( ALSTRUCT );  /* alignment */
+               dstash( idp );
+               }
+       else {
+               switch( BTYPE(type) ){
+               case STRTY:
+               case UNIONTY:
+               case ENUMTY:
+                       p->sizoff = q->fn.csiz;
+                       break;
+               default:
+                       p->sizoff = BTYPE(type);
+                       }
+               }
+
+       /* copy dimensions */
+
+       p->dimoff = q->fn.cdim;
+
+       /* allocate offsets */
+       if( class&FIELD ){
+               falloc( p, class&FLDSIZ, 0, NIL );  /* new entry */
+               psave( idp );
+               }
+       else switch( class ){
+
+       case AUTO:
+               oalloc( p, &autooff );
+               break;
+       case STATIC:
+       case EXTDEF:
+               p->offset = getlab();
+               if( ISFTN(type) ) curftn = idp;
+               break;
+       case ULABEL:
+       case LABEL:
+               p->offset = getlab();
+               p->slevel = 2;
+               if( class == LABEL ){
+                       locctr( PROG );
+                       deflab( p->offset );
+                       }
+               break;
+
+       case EXTERN:
+       case UFORTRAN:
+       case FORTRAN:
+               p->offset = getlab();
+               p->slevel = 0;
+               break;
+       case MOU:
+       case MOS:
+               oalloc( p, &strucoff );
+               if( class == MOU ) strucoff = 0;
+               psave( idp );
+               break;
+
+       case MOE:
+               p->offset = strucoff++;
+               psave( idp );
+               break;
+       case REGISTER:
+               p->offset = regvar--;
+               if( blevel == 1 ) p->sflags |= SSET;
+               if( regvar < minrvar ) minrvar = regvar;
+               break;
+               }
+
+       {
+               register int l = p->slevel;
+
+               if( l >= MAXSCOPES )
+                       cerror( "scopes nested too deep" );
+
+               p->snext = schain[l];
+               schain[l] = p;
+               if( l >= chaintop )
+                       chaintop = l + 1;
+               }
+
+       /* user-supplied routine to fix up new definitions */
+
+       FIXDEF(p);
+
+# ifndef BUG1
+       if( ddebug ) printf( "  dimoff, sizoff, offset: %d, %d, %d\n", p->dimoff, p->sizoff, p->offset );
+# endif
+
+       }
+
+psave( i ){
+       if( paramno >= PARAMSZ ){
+               cerror( "parameter stack overflow");
+               }
+       paramstk[ paramno++ ] = i;
+       }
+
+ftnend(){ /* end of function */
+       if( retlab != NOLAB ){ /* inside a real function */
+               efcode();
+               }
+       checkst(0);
+       retstat = 0;
+       tcheck();
+       curclass = SNULL;
+       brklab = contlab = retlab = NOLAB;
+       flostat = 0;
+       if( nerrors == 0 ){
+               if( psavbc != & asavbc[0] ) cerror("bcsave error");
+               if( paramno != 0 ) cerror("parameter reset error");
+               if( swx != 0 ) cerror( "switch error");
+               }
+       psavbc = &asavbc[0];
+       paramno = 0;
+       autooff = AUTOINIT;
+       minrvar = regvar = MAXRVAR;
+       reached = 1;
+       swx = 0;
+       swp = swtab;
+       locctr(DATA);
+       }
+
+dclargs(){
+       register i, j;
+       register struct symtab *p;
+       register NODE *q;
+       argoff = ARGINIT;
+# ifndef BUG1
+       if( ddebug > 2) printf("dclargs()\n");
+# endif
+       for( i=0; i<paramno; ++i ){
+               if( (j = paramstk[i]) < 0 ) continue;
+               p = &stab[j];
+# ifndef BUG1
+               if( ddebug > 2 ){
+                       printf("\t%s (%d) ",p->sname, j);
+                       tprint(p->stype);
+                       printf("\n");
+                       }
+# endif
+               if( p->stype == FARG ) {
+                       q = block(FREE,NIL,NIL,INT,0,INT);
+                       q->tn.rval = j;
+                       defid( q, PARAM );
+                       }
+               FIXARG(p); /* local arg hook, eg. for sym. debugger */
+               oalloc( p, &argoff );  /* always set aside space, even for register arguments */
+               }
+       cendarg();
+       locctr(PROG);
+       defalign(ALINT);
+       ftnno = getlab();
+       bfcode( paramstk, paramno );
+       paramno = 0;
+       }
+
+NODE *
+rstruct( idn, soru ){ /* reference to a structure or union, with no definition */
+       register struct symtab *p;
+       register NODE *q;
+       p = &stab[idn];
+       switch( p->stype ){
+
+       case UNDEF:
+       def:
+               q = block( FREE, NIL, NIL, 0, 0, 0 );
+               q->tn.rval = idn;
+               q->in.type = (soru&INSTRUCT) ? STRTY : ( (soru&INUNION) ? UNIONTY : ENUMTY );
+               defid( q, (soru&INSTRUCT) ? STNAME : ( (soru&INUNION) ? UNAME : ENAME ) );
+               break;
+
+       case STRTY:
+               if( soru & INSTRUCT ) break;
+               goto def;
+
+       case UNIONTY:
+               if( soru & INUNION ) break;
+               goto def;
+
+       case ENUMTY:
+               if( !(soru&(INUNION|INSTRUCT)) ) break;
+               goto def;
+
+               }
+       stwart = instruct;
+       return( mkty( p->stype, 0, p->sizoff ) );
+       }
+
+moedef( idn ){
+       register NODE *q;
+
+       q = block( FREE, NIL, NIL, MOETY, 0, 0 );
+       q->tn.rval = idn;
+       if( idn>=0 ) defid( q, MOE );
+       }
+
+bstruct( idn, soru ){ /* begining of structure or union declaration */
+       register NODE *q;
+
+       psave( instruct );
+       psave( curclass );
+       psave( strucoff );
+       strucoff = 0;
+       instruct = soru;
+       q = block( FREE, NIL, NIL, 0, 0, 0 );
+       q->tn.rval = idn;
+       if( instruct==INSTRUCT ){
+               curclass = MOS;
+               q->in.type = STRTY;
+               if( idn >= 0 ) defid( q, STNAME );
+               }
+       else if( instruct == INUNION ) {
+               curclass = MOU;
+               q->in.type = UNIONTY;
+               if( idn >= 0 ) defid( q, UNAME );
+               }
+       else { /* enum */
+               curclass = MOE;
+               q->in.type = ENUMTY;
+               if( idn >= 0 ) defid( q, ENAME );
+               }
+       psave( idn = q->tn.rval );
+       /* the "real" definition is where the members are seen */
+       if ( idn >= 0 ) stab[idn].suse = lineno;
+       return( paramno-4 );
+       }
+
+NODE *
+dclstruct( oparam ){
+       register struct symtab *p;
+       register i, al, sa, j, sz, szindex;
+       register TWORD temp;
+       register high, low;
+
+       /* paramstack contains:
+               paramstack[ oparam ] = previous instruct
+               paramstack[ oparam+1 ] = previous class
+               paramstk[ oparam+2 ] = previous strucoff
+               paramstk[ oparam+3 ] = structure name
+
+               paramstk[ oparam+4, ... ]  = member stab indices
+
+               */
+
+
+       if( (i=paramstk[oparam+3]) < 0 ){
+               szindex = curdim;
+               dstash( 0 );  /* size */
+               dstash( -1 );  /* index to member names */
+               dstash( ALSTRUCT );  /* alignment */
+               dstash( -lineno );      /* name of structure */
+               }
+       else {
+               szindex = stab[i].sizoff;
+               }
+
+# ifndef BUG1
+       if( ddebug ){
+#ifndef FLEXNAMES
+               printf( "dclstruct( %.8s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
+#else
+               printf( "dclstruct( %s ), szindex = %d\n", (i>=0)? stab[i].sname : "??", szindex );
+#endif
+               }
+# endif
+       temp = (instruct&INSTRUCT)?STRTY:((instruct&INUNION)?UNIONTY:ENUMTY);
+       stwart = instruct = paramstk[ oparam ];
+       curclass = paramstk[ oparam+1 ];
+       dimtab[ szindex+1 ] = curdim;
+       al = ALSTRUCT;
+
+       high = low = 0;
+
+       for( i = oparam+4;  i< paramno; ++i ){
+               dstash( j=paramstk[i] );
+               if( j<0 || j>= SYMTSZ ) cerror( "gummy structure member" );
+               p = &stab[j];
+               if( temp == ENUMTY ){
+                       if( p->offset < low ) low = p->offset;
+                       if( p->offset > high ) high = p->offset;
+                       p->sizoff = szindex;
+                       continue;
+                       }
+               sa = talign( p->stype, p->sizoff );
+               if( p->sclass & FIELD ){
+                       sz = p->sclass&FLDSIZ;
+                       }
+               else {
+                       sz = tsize( p->stype, p->dimoff, p->sizoff );
+                       }
+               if( sz == 0 ){
+#ifndef FLEXNAMES
+                       werror( "illegal zero sized structure member: %.8s", p->sname );
+#else
+                       werror( "illegal zero sized structure member: %s", p->sname );
+#endif
+                       }
+               if( sz > strucoff ) strucoff = sz;  /* for use with unions */
+               SETOFF( al, sa );
+               /* set al, the alignment, to the lcm of the alignments of the members */
+               }
+       dstash( -1 );  /* endmarker */
+       SETOFF( strucoff, al );
+
+       if( temp == ENUMTY ){
+               register TWORD ty;
+
+# ifdef ENUMSIZE
+               ty = ENUMSIZE(high,low);
+# else
+               if( (char)high == high && (char)low == low ) ty = ctype( CHAR );
+               else if( (short)high == high && (short)low == low ) ty = ctype( SHORT );
+               else ty = ctype(INT);
+#endif
+               strucoff = tsize( ty, 0, (int)ty );
+               dimtab[ szindex+2 ] = al = talign( ty, (int)ty );
+               }
+
+       if( strucoff == 0 ) uerror( "zero sized structure" );
+       dimtab[ szindex ] = strucoff;
+       dimtab[ szindex+2 ] = al;
+       dimtab[ szindex+3 ] = paramstk[ oparam+3 ];  /* name index */
+
+       FIXSTRUCT( szindex, oparam ); /* local hook, eg. for sym debugger */
+# ifndef BUG1
+       if( ddebug>1 ){
+               printf( "\tdimtab[%d,%d,%d] = %d,%d,%d\n", szindex,szindex+1,szindex+2,
+                               dimtab[szindex],dimtab[szindex+1],dimtab[szindex+2] );
+               for( i = dimtab[szindex+1]; dimtab[i] >= 0; ++i ){
+#ifndef FLEXNAMES
+                       printf( "\tmember %.8s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
+#else
+                       printf( "\tmember %s(%d)\n", stab[dimtab[i]].sname, dimtab[i] );
+#endif
+                       }
+               }
+# endif
+
+       strucoff = paramstk[ oparam+2 ];
+       paramno = oparam;
+
+       return( mkty( temp, 0, szindex ) );
+       }
+
+       /* VARARGS */
+yyerror( s ) char *s; { /* error printing routine in parser */
+
+       uerror( s );
+
+       }
+
+yyaccpt(){
+       ftnend();
+       }
+
+ftnarg( idn ) {
+       switch( stab[idn].stype ){
+
+       case UNDEF:
+               /* this parameter, entered at scan */
+               break;
+       case FARG:
+#ifndef FLEXNAMES
+               uerror("redeclaration of formal parameter, %.8s",
+#else
+               uerror("redeclaration of formal parameter, %s",
+#endif
+                       stab[idn].sname);
+               /* fall thru */
+       case FTN:
+               /* the name of this function matches parm */
+               /* fall thru */
+       default:
+               idn = hide( &stab[idn]);
+               break;
+       case TNULL:
+               /* unused entry, fill it */
+               ;
+               }
+       stab[idn].stype = FARG;
+       stab[idn].sclass = PARAM;
+       psave( idn );
+       }
+
+talign( ty, s) register unsigned ty; register s; {
+       /* compute the alignment of an object with type ty, sizeoff index s */
+
+       register i;
+       if( s<0 && ty!=INT && ty!=CHAR && ty!=SHORT && ty!=UNSIGNED && ty!=UCHAR && ty!=USHORT 
+#ifdef LONGFIELDS
+               && ty!=LONG && ty!=ULONG
+#endif
+                                       ){
+               return( fldal( ty ) );
+               }
+
+       for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+               switch( (ty>>i)&TMASK ){
+
+               case FTN:
+                       cerror( "compiler takes alignment of function");
+               case PTR:
+                       return( ALPOINT );
+               case ARY:
+                       continue;
+               case 0:
+                       break;
+                       }
+               }
+
+       switch( BTYPE(ty) ){
+
+       case UNIONTY:
+       case ENUMTY:
+       case STRTY:
+               return( (unsigned int) dimtab[ s+2 ] );
+       case CHAR:
+       case UCHAR:
+               return( ALCHAR );
+       case FLOAT:
+               return( ALFLOAT );
+       case DOUBLE:
+               return( ALDOUBLE );
+       case LONG:
+       case ULONG:
+               return( ALLONG );
+       case SHORT:
+       case USHORT:
+               return( ALSHORT );
+       default:
+               return( ALINT );
+               }
+       }
+
+OFFSZ
+tsize( ty, d, s )  TWORD ty; {
+       /* compute the size associated with type ty,
+           dimoff d, and sizoff s */
+       /* BETTER NOT BE CALLED WHEN t, d, and s REFER TO A BIT FIELD... */
+
+       int i;
+       OFFSZ mult;
+
+       mult = 1;
+
+       for( i=0; i<=(SZINT-BTSHIFT-1); i+=TSHIFT ){
+               switch( (ty>>i)&TMASK ){
+
+               case FTN:
+                       cerror( "compiler takes size of function");
+               case PTR:
+                       return( SZPOINT * mult );
+               case ARY:
+                       mult *= (unsigned int) dimtab[ d++ ];
+                       continue;
+               case 0:
+                       break;
+
+                       }
+               }
+
+       if( dimtab[s]==0 ) {
+               if( ty == STRTY )
+                       uerror( "undefined structure" );
+               else
+                       uerror( "unknown size");
+               return( SZINT );
+               }
+       return( (unsigned int) dimtab[ s ] * mult );
+       }
+
+inforce( n ) OFFSZ n; {  /* force inoff to have the value n */
+       /* inoff is updated to have the value n */
+       OFFSZ wb;
+       register rest;
+       /* rest is used to do a lot of conversion to ints... */
+
+       if( inoff == n ) return;
+       if( inoff > n ) {
+               cerror( "initialization alignment error");
+               }
+
+       wb = inoff;
+       SETOFF( wb, SZINT );
+
+       /* wb now has the next higher word boundary */
+
+       if( wb >= n ){ /* in the same word */
+               rest = n - inoff;
+               vfdzero( rest );
+               return;
+               }
+
+       /* otherwise, extend inoff to be word aligned */
+
+       rest = wb - inoff;
+       vfdzero( rest );
+
+       /* now, skip full words until near to n */
+
+       rest = (n-inoff)/SZINT;
+       zecode( rest );
+
+       /* now, the remainder of the last word */
+
+       rest = n-inoff;
+       vfdzero( rest );
+       if( inoff != n ) cerror( "inoff error");
+
+       }
+
+vfdalign( n ){ /* make inoff have the offset the next alignment of n */
+       OFFSZ m;
+
+       m = inoff;
+       SETOFF( m, n );
+       inforce( m );
+       }
+
+
+int idebug = 0;
+
+int ibseen = 0;  /* the number of } constructions which have been filled */
+
+int ifull = 0; /* 1 if all initializers have been seen */
+
+int iclass;  /* storage class of thing being initialized */
+
+int ilocctr = 0;  /* location counter for current initialization */
+
+beginit(curid){
+       /* beginning of initilization; set location ctr and set type */
+       register struct symtab *p;
+
+# ifndef BUG1
+       if( idebug >= 3 ) printf( "beginit(), curid = %d\n", curid );
+# endif
+
+       p = &stab[curid];
+
+       iclass = p->sclass;
+       if( curclass == EXTERN || curclass == FORTRAN ) iclass = EXTERN;
+       switch( iclass ){
+
+       case UNAME:
+       case EXTERN:
+               return;
+       case AUTO:
+       case REGISTER:
+               break;
+       case EXTDEF:
+       case STATIC:
+               ilocctr = ISARY(p->stype)?ADATA:DATA;
+               locctr( ilocctr );
+               defalign( talign( p->stype, p->sizoff ) );
+               defnam( p );
+
+               }
+
+       inoff = 0;
+       ibseen = 0;
+       ifull = 0;
+
+       pstk = 0;
+
+       instk( curid, p->stype, p->dimoff, p->sizoff, inoff );
+
+       }
+
+instk( id, t, d, s, off ) OFFSZ off; TWORD t; {
+       /* make a new entry on the parameter stack to initialize id */
+
+       register struct symtab *p;
+
+       for(;;){
+# ifndef BUG1
+               if( idebug ) printf( "instk((%d, %o,%d,%d, %d)\n", id, t, d, s, off );
+# endif
+
+               /* save information on the stack */
+
+               if( !pstk ) pstk = instack;
+               else ++pstk;
+
+               pstk->in_fl = 0;        /* { flag */
+               pstk->in_id =  id ;
+               pstk->in_t =  t ;
+               pstk->in_d =  d ;
+               pstk->in_s =  s ;
+               pstk->in_n = 0;  /* number seen */
+               pstk->in_x =  t==STRTY ?dimtab[s+1] : 0 ;
+               pstk->in_off =  off;   /* offset at the beginning of this element */
+               /* if t is an array, DECREF(t) can't be a field */
+               /* INS_sz has size of array elements, and -size for fields */
+               if( ISARY(t) ){
+                       pstk->in_sz = tsize( DECREF(t), d+1, s );
+                       }
+               else if( stab[id].sclass & FIELD ){
+                       pstk->in_sz = - ( stab[id].sclass & FLDSIZ );
+                       }
+               else {
+                       pstk->in_sz = 0;
+                       }
+
+               if( (iclass==AUTO || iclass == REGISTER ) &&
+                       (ISARY(t) || t==STRTY) ) uerror( "no automatic aggregate initialization" );
+
+               /* now, if this is not a scalar, put on another element */
+
+               if( ISARY(t) ){
+                       t = DECREF(t);
+                       ++d;
+                       continue;
+                       }
+               else if( t == STRTY ){
+                       if( dimtab[pstk->in_s] == 0 ){
+                               uerror( "can't initialize undefined structure" );
+                               iclass = -1;
+                               return;
+                               }
+                       id = dimtab[pstk->in_x];
+                       p = &stab[id];
+                       if( p->sclass != MOS && !(p->sclass&FIELD) ) cerror( "insane structure member list" );
+                       t = p->stype;
+                       d = p->dimoff;
+                       s = p->sizoff;
+                       off += p->offset;
+                       continue;
+                       }
+               else return;
+               }
+       }
+
+NODE *
+getstr(){ /* decide if the string is external or an initializer, and get the contents accordingly */
+
+       register l, temp;
+       register NODE *p;
+
+       if( (iclass==EXTDEF||iclass==STATIC) && (pstk->in_t == CHAR || pstk->in_t == UCHAR) &&
+                       pstk!=instack && ISARY( pstk[-1].in_t ) ){
+               /* treat "abc" as { 'a', 'b', 'c', 0 } */
+               strflg = 1;
+               ilbrace();  /* simulate { */
+               inforce( pstk->in_off );
+               /* if the array is inflexible (not top level), pass in the size and
+                       be prepared to throw away unwanted initializers */
+               lxstr((pstk-1)!=instack?dimtab[(pstk-1)->in_d]:0);  /* get the contents */
+               irbrace();  /* simulate } */
+               return( NIL );
+               }
+       else { /* make a label, and get the contents and stash them away */
+               if( iclass != SNULL ){ /* initializing */
+                       /* fill out previous word, to permit pointer */
+                       vfdalign( ALPOINT );
+                       }
+               temp = locctr( blevel==0?ISTRNG:STRNG ); /* set up location counter */
+               deflab( l = getlab() );
+               strflg = 0;
+               lxstr(0); /* get the contents */
+               locctr( blevel==0?ilocctr:temp );
+               p = buildtree( STRING, NIL, NIL );
+               p->tn.rval = -l;
+               return(p);
+               }
+       }
+
+putbyte( v ){ /* simulate byte v appearing in a list of integer values */
+       register NODE *p;
+       p = bcon(v);
+       incode( p, SZCHAR );
+       tfree( p );
+       gotscal();
+       }
+
+endinit(){
+       register TWORD t;
+       register d, s, n, d1;
+
+# ifndef BUG1
+       if( idebug ) printf( "endinit(), inoff = %d\n", inoff );
+# endif
+
+       switch( iclass ){
+
+       case EXTERN:
+       case AUTO:
+       case REGISTER:
+       case -1:
+               return;
+               }
+
+       pstk = instack;
+
+       t = pstk->in_t;
+       d = pstk->in_d;
+       s = pstk->in_s;
+       n = pstk->in_n;
+
+       if( ISARY(t) ){
+               d1 = dimtab[d];
+
+               vfdalign( pstk->in_sz );  /* fill out part of the last element, if needed */
+               n = inoff/pstk->in_sz;  /* real number of initializers */
+               if( d1 >= n ){
+                       /* once again, t is an array, so no fields */
+                       inforce( tsize( t, d, s ) );
+                       n = d1;
+                       }
+               if( d1!=0 && d1!=n ) uerror( "too many initializers");
+               if( n==0 ) werror( "empty array declaration");
+               dimtab[d] = n;
+               if( d1==0 ) FIXDEF(&stab[pstk->in_id]);
+               }
+
+       else if( t == STRTY || t == UNIONTY ){
+               /* clearly not fields either */
+               inforce( tsize( t, d, s ) );
+               }
+       else if( n > 1 ) uerror( "bad scalar initialization");
+       /* this will never be called with a field element... */
+       else inforce( tsize(t,d,s) );
+
+       paramno = 0;
+       vfdalign( AL_INIT );
+       inoff = 0;
+       iclass = SNULL;
+
+       }
+
+doinit( p ) register NODE *p; {
+
+       /* take care of generating a value for the initializer p */
+       /* inoff has the current offset (last bit written)
+               in the current word being generated */
+
+       register sz, d, s;
+       register TWORD t;
+       int o;
+
+       /* note: size of an individual initializer is assumed to fit into an int */
+
+       if( iclass < 0 ) goto leave;
+       if( iclass == EXTERN || iclass == UNAME ){
+               uerror( "cannot initialize extern or union" );
+               iclass = -1;
+               goto leave;
+               }
+
+       if( iclass == AUTO || iclass == REGISTER ){
+               /* do the initialization and get out, without regard 
+                   for filing out the variable with zeros, etc. */
+               bccode();
+               idname = pstk->in_id;
+               p = buildtree( ASSIGN, buildtree( NAME, NIL, NIL ), p );
+               ecomp(p);
+               return;
+               }
+
+       if( p == NIL ) return;  /* for throwing away strings that have been turned into lists */
+
+       if( ifull ){
+               uerror( "too many initializers" );
+               iclass = -1;
+               goto leave;
+               }
+       if( ibseen ){
+               uerror( "} expected");
+               goto leave;
+               }
+
+# ifndef BUG1
+       if( idebug > 1 ) printf( "doinit(%o)\n", p );
+# endif
+
+       t = pstk->in_t;  /* type required */
+       d = pstk->in_d;
+       s = pstk->in_s;
+       if( pstk->in_sz < 0 ){  /* bit field */
+               sz = -pstk->in_sz;
+               }
+       else {
+               sz = tsize( t, d, s );
+               }
+
+       inforce( pstk->in_off );
+
+       p = buildtree( ASSIGN, block( NAME, NIL,NIL, t, d, s ), p );
+       p->in.left->in.op = FREE;
+       p->in.left = p->in.right;
+       p->in.right = NIL;
+       p->in.left = optim( p->in.left );
+       o = p->in.left->in.op;
+       if( o == UNARY AND ){
+               o = p->in.left->in.op = FREE;
+               p->in.left = p->in.left->in.left;
+               }
+       p->in.op = INIT;
+
+       if( sz < SZINT ){ /* special case: bit fields, etc. */
+               if( o != ICON ) uerror( "illegal initialization" );
+               else incode( p->in.left, sz );
+               }
+       else if( o == FCON ){
+               fincode( p->in.left->fpn.fval, sz );
+               }
+       else if( o == DCON ){
+               fincode( p->in.left->dpn.dval, sz );
+               }
+       else {
+               p = optim(p);
+               if( p->in.left->in.op != ICON ) uerror( "illegal initialization" );
+               else cinit( p, sz );
+               }
+
+       gotscal();
+
+       leave:
+       tfree(p);
+       }
+
+gotscal(){
+       register t, ix;
+       register n, id;
+       struct symtab *p;
+       OFFSZ temp;
+
+       for( ; pstk > instack; ) {
+
+               if( pstk->in_fl ) ++ibseen;
+
+               --pstk;
+               
+               t = pstk->in_t;
+
+               if( t == STRTY ){
+                       ix = ++pstk->in_x;
+                       if( (id=dimtab[ix]) < 0 ) continue;
+
+                       /* otherwise, put next element on the stack */
+
+                       p = &stab[id];
+                       instk( id, p->stype, p->dimoff, p->sizoff, p->offset+pstk->in_off );
+                       return;
+                       }
+               else if( ISARY(t) ){
+                       n = ++pstk->in_n;
+                       if( n >= dimtab[pstk->in_d] && pstk > instack ) continue;
+
+                       /* put the new element onto the stack */
+
+                       temp = pstk->in_sz;
+                       instk( pstk->in_id, (TWORD)DECREF(pstk->in_t), pstk->in_d+1, pstk->in_s,
+                               pstk->in_off+n*temp );
+                       return;
+                       }
+
+               }
+       ifull = 1;
+       }
+
+ilbrace(){ /* process an initializer's left brace */
+       register t;
+       struct instk *temp;
+
+       temp = pstk;
+
+       for( ; pstk > instack; --pstk ){
+
+               t = pstk->in_t;
+               if( t != STRTY && !ISARY(t) ) continue; /* not an aggregate */
+               if( pstk->in_fl ){ /* already associated with a { */
+                       if( pstk->in_n ) uerror( "illegal {");
+                       continue;
+                       }
+
+               /* we have one ... */
+               pstk->in_fl = 1;
+               break;
+               }
+
+       /* cannot find one */
+       /* ignore such right braces */
+
+       pstk = temp;
+       }
+
+irbrace(){
+       /* called when a '}' is seen */
+
+# ifndef BUG1
+       if( idebug ) printf( "irbrace(): paramno = %d on entry\n", paramno );
+# endif
+
+       if( ibseen ) {
+               --ibseen;
+               return;
+               }
+
+       for( ; pstk > instack; --pstk ){
+               if( !pstk->in_fl ) continue;
+
+               /* we have one now */
+
+               pstk->in_fl = 0;  /* cancel { */
+               gotscal();  /* take it away... */
+               return;
+               }
+
+       /* these right braces match ignored left braces: throw out */
+       ifull = 1;
+
+       }
+
+upoff( size, alignment, poff ) register alignment, *poff; {
+       /* update the offset pointed to by poff; return the
+       /* offset of a value of size `size', alignment `alignment',
+       /* given that off is increasing */
+
+       register off;
+
+       off = *poff;
+       SETOFF( off, alignment );
+       if( (offsz-off) <  size ){
+               if( instruct!=INSTRUCT )cerror("too many local variables");
+               else cerror("Structure too large");
+               }
+       *poff = off+size;
+       return( off );
+       }
+
+oalloc( p, poff ) register struct symtab *p; register *poff; {
+       /* allocate p with offset *poff, and update *poff */
+       register al, off, tsz;
+       int noff;
+
+       al = talign( p->stype, p->sizoff );
+       noff = off = *poff;
+       tsz = tsize( p->stype, p->dimoff, p->sizoff );
+#ifdef BACKAUTO
+       if( p->sclass == AUTO ){
+               if( (offsz-off) < tsz ) cerror("too many local variables");
+               noff = off + tsz;
+               SETOFF( noff, al );
+               off = -noff;
+               }
+       else
+#endif
+               if( p->sclass == PARAM && ( tsz < SZINT ) ){
+                       off = upoff( SZINT, ALINT, &noff );
+# ifndef RTOLBYTES
+                       off = noff - tsz;
+#endif
+                       }
+               else
+               {
+               off = upoff( tsz, al, &noff );
+               }
+
+       if( p->sclass != REGISTER ){ /* in case we are allocating stack space for register arguments */
+               if( p->offset == NOOFFSET ) p->offset = off;
+               else if( off != p->offset ) return(1);
+               }
+
+       *poff = noff;
+       return(0);
+       }
+
+falloc( p, w, new, pty )  register struct symtab *p; NODE *pty; {
+       /* allocate a field of width w */
+       /* new is 0 if new entry, 1 if redefinition, -1 if alignment */
+
+       register al,sz,type;
+
+       type = (new<0)? pty->in.type : p->stype;
+
+       /* this must be fixed to use the current type in alignments */
+       switch( new<0?pty->in.type:p->stype ){
+
+       case ENUMTY:
+               {
+                       int s;
+                       s = new<0 ? pty->fn.csiz : p->sizoff;
+                       al = dimtab[s+2];
+                       sz = dimtab[s];
+                       break;
+                       }
+
+       case CHAR:
+       case UCHAR:
+               al = ALCHAR;
+               sz = SZCHAR;
+               break;
+
+       case SHORT:
+       case USHORT:
+               al = ALSHORT;
+               sz = SZSHORT;
+               break;
+
+       case INT:
+       case UNSIGNED:
+               al = ALINT;
+               sz = SZINT;
+               break;
+#ifdef LONGFIELDS
+
+       case LONG:
+       case ULONG:
+               al = ALLONG;
+               sz = SZLONG;
+               break;
+#endif
+
+       default:
+               if( new < 0 ) {
+                       uerror( "illegal field type" );
+                       al = ALINT;
+                       }
+               else {
+                       al = fldal( p->stype );
+                       sz =SZINT;
+                       }
+               }
+
+       if( w > sz ) {
+               uerror( "field too big");
+               w = sz;
+               }
+
+       if( w == 0 ){ /* align only */
+               SETOFF( strucoff, al );
+               if( new >= 0 ) uerror( "zero size field");
+               return(0);
+               }
+
+       if( strucoff%al + w > sz ) SETOFF( strucoff, al );
+       if( new < 0 ) {
+               if( (offsz-strucoff) < w )
+                       cerror("structure too large");
+               strucoff += w;  /* we know it will fit */
+               return(0);
+               }
+
+       /* establish the field */
+
+       if( new == 1 ) { /* previous definition */
+               if( p->offset != strucoff || p->sclass != (FIELD|w) ) return(1);
+               }
+       p->offset = strucoff;
+       if( (offsz-strucoff) < w ) cerror("structure too large");
+       strucoff += w;
+       p->stype = type;
+       fldty( p );
+       return(0);
+       }
+
+nidcl( p ) NODE *p; { /* handle unitialized declarations */
+       /* assumed to be not functions */
+       register class;
+       register commflag;  /* flag for labelled common declarations */
+
+       commflag = 0;
+
+       /* compute class */
+       if( (class=curclass) == SNULL ){
+               if( blevel > 1 ) class = AUTO;
+               else if( blevel != 0 || instruct ) cerror( "nidcl error" );
+               else { /* blevel = 0 */
+                       class = noinit();
+                       if( class == EXTERN ) commflag = 1;
+                       }
+               }
+#ifdef LCOMM
+       /* hack so stab will come at as LCSYM rather than STSYM */
+       if (class == STATIC) {
+               extern int stabLCSYM;
+               stabLCSYM = 1;
+       }
+#endif
+
+       defid( p, class );
+
+#ifndef LCOMM
+       if( class==EXTDEF || class==STATIC )
+#else
+       if (class==STATIC) {
+               register struct symtab *s = &stab[p->tn.rval];
+               extern int stabLCSYM;
+               int sz = tsize(s->stype, s->dimoff, s->sizoff)/SZCHAR;
+               
+               stabLCSYM = 0;
+               if (sz % sizeof (int))
+                       sz += sizeof (int) - (sz % sizeof (int));
+               if (s->slevel > 1)
+                       printf("        .lcomm  L%d,%d\n", s->offset, sz);
+               else
+                       printf("        .lcomm  %s,%d\n", exname(s->sname), sz);
+       }else if (class == EXTDEF)
+#endif
+               {
+               /* simulate initialization by 0 */
+               beginit(p->tn.rval);
+               endinit();
+               }
+       if( commflag ) commdec( p->tn.rval );
+       }
+
+TWORD
+types( t1, t2, t3 ) TWORD t1, t2, t3; {
+       /* return a basic type from basic types t1, t2, and t3 */
+
+       TWORD t[3], noun, adj, unsg;
+       register i;
+
+       t[0] = t1;
+       t[1] = t2;
+       t[2] = t3;
+
+       unsg = INT;  /* INT or UNSIGNED */
+       noun = UNDEF;  /* INT, CHAR, or FLOAT */
+       adj = INT;  /* INT, LONG, or SHORT */
+
+       for( i=0; i<3; ++i ){
+               switch( t[i] ){
+
+               default:
+               bad:
+                       uerror( "illegal type combination" );
+                       return( INT );
+
+               case UNDEF:
+                       continue;
+
+               case UNSIGNED:
+                       if( unsg != INT ) goto bad;
+                       unsg = UNSIGNED;
+                       continue;
+
+               case LONG:
+               case SHORT:
+                       if( adj != INT ) goto bad;
+                       adj = t[i];
+                       continue;
+
+               case INT:
+               case CHAR:
+               case FLOAT:
+                       if( noun != UNDEF ) goto bad;
+                       noun = t[i];
+                       continue;
+                       }
+               }
+
+       /* now, construct final type */
+       if( noun == UNDEF ) noun = INT;
+       else if( noun == FLOAT ){
+               if( unsg != INT || adj == SHORT ) goto bad;
+               return( adj==LONG ? DOUBLE : FLOAT );
+               }
+       else if( noun == CHAR && adj != INT ) goto bad;
+
+       /* now, noun is INT or CHAR */
+       if( adj != INT ) noun = adj;
+       if( unsg == UNSIGNED ) return( noun + (UNSIGNED-INT) );
+       else return( noun );
+       }
+
+NODE *
+tymerge( typ, idp ) NODE *typ, *idp; {
+       /* merge type typ with identifier idp  */
+
+       register unsigned t;
+       register i;
+       extern int eprint();
+
+       if( typ->in.op != TYPE ) cerror( "tymerge: arg 1" );
+       if(idp == NIL ) return( NIL );
+
+# ifndef BUG1
+       if( ddebug > 2 ) fwalk( idp, eprint, 0 );
+# endif
+
+       idp->in.type = typ->in.type;
+       idp->fn.cdim = curdim;
+       tyreduce( idp );
+       idp->fn.csiz = typ->fn.csiz;
+
+       for( t=typ->in.type, i=typ->fn.cdim; t&TMASK; t = DECREF(t) ){
+               if( ISARY(t) ) dstash( dimtab[i++] );
+               }
+
+       /* now idp is a single node: fix up type */
+
+       idp->in.type = ctype( idp->in.type );
+
+       if( (t = BTYPE(idp->in.type)) != STRTY && t != UNIONTY && t != ENUMTY ){
+               idp->fn.csiz = t;  /* in case ctype has rewritten things */
+               }
+
+       return( idp );
+       }
+
+tyreduce( p ) register NODE *p; {
+
+       /* build a type, and stash away dimensions, from a parse tree of the declaration */
+       /* the type is build top down, the dimensions bottom up */
+       register o, temp;
+       register unsigned t;
+
+       o = p->in.op;
+       p->in.op = FREE;
+
+       if( o == NAME ) return;
+
+       t = INCREF( p->in.type );
+       if( o == UNARY CALL ) t += (FTN-PTR);
+       else if( o == LB ){
+               t += (ARY-PTR);
+               temp = p->in.right->tn.lval;
+               p->in.right->in.op = FREE;
+               if( ( temp == 0 ) & ( p->in.left->tn.op == LB ) )
+                       uerror( "Null dimension" );
+               }
+
+       p->in.left->in.type = t;
+       tyreduce( p->in.left );
+
+       if( o == LB ) dstash( temp );
+
+       p->tn.rval = p->in.left->tn.rval;
+       p->in.type = p->in.left->in.type;
+
+       }
+
+fixtype( p, class ) register NODE *p; {
+       register unsigned t, type;
+       register mod1, mod2;
+       /* fix up the types, and check for legality */
+
+       if( (type = p->in.type) == UNDEF ) return;
+       if( mod2 = (type&TMASK) ){
+               t = DECREF(type);
+               while( mod1=mod2, mod2 = (t&TMASK) ){
+                       if( mod1 == ARY && mod2 == FTN ){
+                               uerror( "array of functions is illegal" );
+                               type = 0;
+                               }
+                       else if( mod1 == FTN && ( mod2 == ARY || mod2 == FTN ) ){
+                               uerror( "function returns illegal type" );
+                               type = 0;
+                               }
+                       t = DECREF(t);
+                       }
+               }
+
+       /* detect function arguments, watching out for structure declarations */
+       /* for example, beware of f(x) struct [ int a[10]; } *x; { ... } */
+       /* the danger is that "a" will be converted to a pointer */
+
+       if( class==SNULL && blevel==1 && !(instruct&(INSTRUCT|INUNION)) ) class = PARAM;
+       if( class == PARAM || ( class==REGISTER && blevel==1 ) ){
+               if( type == FLOAT ) type = DOUBLE;
+               else if( ISARY(type) ){
+                       ++p->fn.cdim;
+                       type += (PTR-ARY);
+                       }
+               else if( ISFTN(type) ){
+                       werror( "a function is declared as an argument" );
+                       type = INCREF(type);
+                       }
+
+               }
+
+       if( instruct && ISFTN(type) ){
+               uerror( "function illegal in structure or union" );
+               type = INCREF(type);
+               }
+       p->in.type = type;
+       }
+
+uclass( class ) register class; {
+       /* give undefined version of class */
+       if( class == SNULL ) return( EXTERN );
+       else if( class == STATIC ) return( USTATIC );
+       else if( class == FORTRAN ) return( UFORTRAN );
+       else return( class );
+       }
+
+fixclass( class, type ) TWORD type; {
+
+       /* first, fix null class */
+
+       if( class == SNULL ){
+               if( instruct&INSTRUCT ) class = MOS;
+               else if( instruct&INUNION ) class = MOU;
+               else if( blevel == 0 ) class = EXTDEF;
+               else if( blevel == 1 ) class = PARAM;
+               else class = AUTO;
+
+               }
+
+       /* now, do general checking */
+
+       if( ISFTN( type ) ){
+               switch( class ) {
+               default:
+                       uerror( "function has illegal storage class" );
+               case AUTO:
+                       class = EXTERN;
+               case EXTERN:
+               case EXTDEF:
+               case FORTRAN:
+               case TYPEDEF:
+               case STATIC:
+               case UFORTRAN:
+               case USTATIC:
+                       ;
+                       }
+               }
+
+       if( class&FIELD ){
+               if( !(instruct&INSTRUCT) ) uerror( "illegal use of field" );
+               return( class );
+               }
+
+       switch( class ){
+
+       case MOU:
+               if( !(instruct&INUNION) ) uerror( "illegal class" );
+               return( class );
+
+       case MOS:
+               if( !(instruct&INSTRUCT) ) uerror( "illegal class" );
+               return( class );
+
+       case MOE:
+               if( instruct & (INSTRUCT|INUNION) ) uerror( "illegal class" );
+               return( class );
+
+       case REGISTER:
+               if( blevel == 0 ) uerror( "illegal register declaration" );
+               else if( regvar >= MINRVAR && cisreg( type ) ) return( class );
+               if( blevel == 1 ) return( PARAM );
+               else return( AUTO );
+
+       case AUTO:
+       case LABEL:
+       case ULABEL:
+               if( blevel < 2 ) uerror( "illegal class" );
+               return( class );
+
+       case PARAM:
+               if( blevel != 1 ) uerror( "illegal class" );
+               return( class );
+
+       case UFORTRAN:
+       case FORTRAN:
+# ifdef NOFORTRAN
+                       NOFORTRAN;    /* a condition which can regulate the FORTRAN usage */
+# endif
+               if( !ISFTN(type) ) uerror( "fortran declaration must apply to function" );
+               else {
+                       type = DECREF(type);
+                       if( ISFTN(type) || ISARY(type) || ISPTR(type) ) {
+                               uerror( "fortran function has wrong type" );
+                               }
+                       }
+       case EXTERN:
+       case STATIC:
+       case EXTDEF:
+       case TYPEDEF:
+       case USTATIC:
+               if( blevel == 1 ){
+                       uerror( "illegal class" );
+                       return( PARAM );
+                       }
+       case STNAME:
+       case UNAME:
+       case ENAME:
+               return( class );
+
+       default:
+               cerror( "illegal class: %d", class );
+               /* NOTREACHED */
+
+               }
+       }
+
+struct symtab *
+mknonuniq(idindex) int *idindex; {/* locate a symbol table entry for */
+       /* an occurrence of a nonunique structure member name */
+       /* or field */
+       register i;
+       register struct symtab * sp;
+       char *p,*q;
+
+       sp = & stab[ i= *idindex ]; /* position search at old entry */
+       while( sp->stype != TNULL ){ /* locate unused entry */
+               if( ++i >= SYMTSZ ){/* wrap around symbol table */
+                       i = 0;
+                       sp = stab;
+                       }
+               else ++sp;
+               if( i == *idindex ) cerror("Symbol table full");
+               }
+       sp->sflags = SNONUNIQ | SMOS;
+       p = sp->sname;
+       q = stab[*idindex].sname; /* old entry name */
+#ifdef FLEXNAMES
+       sp->sname = stab[*idindex].sname;
+#endif
+# ifndef BUG1
+       if( ddebug ){
+               printf("\tnonunique entry for %s from %d to %d\n",
+                       q, *idindex, i );
+               }
+# endif
+       *idindex = i;
+#ifndef FLEXNAMES
+       for( i=1; i<=NCHNAM; ++i ){ /* copy name */
+               if( *p++ = *q /* assign */ ) ++q;
+               }
+#endif
+       return ( sp );
+       }
+
+lookup( name, s) char *name; { 
+       /* look up name: must agree with s w.r.t. STAG, SMOS and SHIDDEN */
+
+       register char *p, *q;
+       int i, j, ii;
+       register struct symtab *sp;
+
+       /* compute initial hash index */
+# ifndef BUG1
+       if( ddebug > 2 ){
+               printf( "lookup( %s, %d ), stwart=%d, instruct=%d\n", name, s, stwart, instruct );
+               }
+# endif
+
+       i = 0;
+#ifndef FLEXNAMES
+       for( p=name, j=0; *p != '\0'; ++p ){
+               i += *p;
+               if( ++j >= NCHNAM ) break;
+               }
+#else
+       i = (int)name;
+#endif
+       i = i%SYMTSZ;
+       sp = &stab[ii=i];
+
+       for(;;){ /* look for name */
+
+               if( sp->stype == TNULL ){ /* empty slot */
+                       sp->sflags = s;  /* set STAG, SMOS if needed, turn off all others */
+#ifndef FLEXNAMES
+                       p = sp->sname;
+                       for( j=0; j<NCHNAM; ++j ) if( *p++ = *name ) ++name;
+#else
+                       sp->sname = name;
+#endif
+                       sp->stype = UNDEF;
+                       sp->sclass = SNULL;
+                       return( i );
+                       }
+               if( (sp->sflags & (STAG|SMOS|SHIDDEN)) != s ) goto next;
+               p = sp->sname;
+               q = name;
+#ifndef FLEXNAMES
+               for( j=0; j<NCHNAM;++j ){
+                       if( *p++ != *q ) goto next;
+                       if( !*q++ ) break;
+                       }
+               return( i );
+#else
+               if (p == q)
+                       return ( i );
+#endif
+       next:
+               if( ++i >= SYMTSZ ){
+                       i = 0;
+                       sp = stab;
+                       }
+               else ++sp;
+               if( i == ii ) cerror( "symbol table full" );
+               }
+       }
+
+#ifndef checkst
+/* if not debugging, make checkst a macro */
+XXXcheckst(lev){
+       register int s, i, j;
+       register struct symtab *p, *q;
+
+       for( i=0, p=stab; i<SYMTSZ; ++i, ++p ){
+               if( p->stype == TNULL ) continue;
+               j = lookup( p->sname, p->sflags&(SMOS|STAG) );
+               if( j != i ){
+                       q = &stab[j];
+                       if( q->stype == UNDEF ||
+                           q->slevel <= p->slevel ){
+#ifndef FLEXNAMES
+                               cerror( "check error: %.8s", q->sname );
+#else
+                               cerror( "check error: %s", q->sname );
+#endif
+                               }
+                       }
+#ifndef FLEXNAMES
+               else if( p->slevel > lev ) cerror( "%.8s check at level %d", p->sname, lev );
+#else
+               else if( p->slevel > lev ) cerror( "%s check at level %d", p->sname, lev );
+#endif
+               }
+       }
+#endif
+
+struct symtab *
+relook(p) register struct symtab *p; {  /* look up p again, and see where it lies */
+
+       register struct symtab *q;
+
+       /* I'm not sure that this handles towers of several hidden definitions in all cases */
+       q = &stab[lookup( p->sname, p->sflags&(STAG|SMOS|SHIDDEN) )];
+       /* make relook always point to either p or an empty cell */
+       if( q->stype == UNDEF ){
+               q->stype = TNULL;
+               return(q);
+               }
+       while( q != p ){
+               if( q->stype == TNULL ) break;
+               if( ++q >= &stab[SYMTSZ] ) q=stab;
+               }
+       return(q);
+       }
+
+clearst( lev ) register int lev; {
+       register struct symtab *p, *q;
+       register int temp;
+       struct symtab *clist = 0;
+
+       temp = lineno;
+       aobeg();
+
+       /* step 1: remove entries */
+       while( chaintop-1 > lev ){
+               register int type;
+
+               p = schain[--chaintop];
+               schain[chaintop] = 0;
+               for( ; p; p = q ){
+                       q = p->snext;
+                       type = p->stype;
+                       if( p->stype == TNULL || p->slevel <= lev )
+                               cerror( "schain botch" );
+                       lineno = p->suse < 0 ? -p->suse : p->suse;
+                       if( p->stype==UNDEF || ( p->sclass==ULABEL && lev<2 ) ){
+                               lineno = temp;
+#ifndef FLEXNAMES
+                               uerror( "%.8s undefined", p->sname );
+#else
+                               uerror( "%s undefined", p->sname );
+#endif
+                               }
+                       else aocode(p);
+# ifndef BUG1
+                       if( ddebug ){
+#ifndef FLEXNAMES
+                               printf( "removing %.8s", p->sname );
+#else
+                               printf( "removing %s", p->sname );
+#endif
+                               printf( " from stab[%d], flags %o level %d\n",
+                                       p-stab, p->sflags, p->slevel);
+                               }
+# endif
+                       if( p->sflags & SHIDES )unhide( p );
+                       p->stype = TNULL;
+                       p->snext = clist;
+                       clist = p;
+                       }
+               }
+
+       /* step 2: fix any mishashed entries */
+       p = clist;
+       while( p ){
+               register struct symtab *r, *next;
+
+               q = p;
+               next = p->snext;
+               for(;;){
+                       if( ++q >= &stab[SYMTSZ] )q = stab;
+                       if( q == p || q->stype == TNULL )break;
+                       if( (r = relook(q)) != q ) {
+                               *r = *q;
+                               q->stype = TNULL;
+                               }
+                       }
+               p = next;
+               }
+
+       lineno = temp;
+       aoend();
+       }
+
+hide( p ) register struct symtab *p; {
+       register struct symtab *q;
+       for( q=p+1; ; ++q ){
+               if( q >= &stab[SYMTSZ] ) q = stab;
+               if( q == p ) cerror( "symbol table full" );
+               if( q->stype == TNULL ) break;
+               }
+       *q = *p;
+       p->sflags |= SHIDDEN;
+       q->sflags = (p->sflags&(SMOS|STAG)) | SHIDES;
+#ifndef FLEXNAMES
+       if( hflag ) werror( "%.8s redefinition hides earlier one", p->sname );
+#else
+       if( hflag ) werror( "%s redefinition hides earlier one", p->sname );
+#endif
+# ifndef BUG1
+       if( ddebug ) printf( "  %d hidden in %d\n", p-stab, q-stab );
+# endif
+       return( idname = q-stab );
+       }
+
+unhide( p ) register struct symtab *p; {
+       register struct symtab *q;
+       register s, j;
+
+       s = p->sflags & (SMOS|STAG);
+       q = p;
+
+       for(;;){
+
+               if( q == stab ) q = &stab[SYMTSZ-1];
+               else --q;
+
+               if( q == p ) break;
+
+               if( (q->sflags&(SMOS|STAG)) == s ){
+#ifndef FLEXNAMES
+                       for( j =0; j<NCHNAM; ++j ) if( p->sname[j] != q->sname[j] ) break;
+                       if( j == NCHNAM ) /* found the name */
+#else
+                       if (p->sname == q->sname)
+#endif
+                       {
+                               q->sflags &= ~SHIDDEN;
+# ifndef BUG1
+                               if( ddebug ) printf( "unhide uncovered %d from %d\n", q-stab,p-stab);
+# endif
+                               return;
+                               }
+                       }
+
+               }
+       cerror( "unhide fails" );
+       }
diff --git a/lib/pcc/reader.c b/lib/pcc/reader.c
new file mode 100644 (file)
index 0000000..fd9145c
--- /dev/null
@@ -0,0 +1,1332 @@
+#ifndef lint
+static char *sccsid ="@(#)reader.c     4.4 (Berkeley) 8/22/85";
+#endif lint
+
+# include "pass2.h"
+
+/*     some storage declarations */
+
+#ifndef ONEPASS
+#define EXPR '.'
+#define BBEG '['
+#define BEND ']'
+
+NODE node[TREESZ];
+char ftitle[100] = "";  /* the name of the file */
+int ftnno;  /* number of current function */
+int lineno;
+#endif
+
+int nrecur;
+int lflag;
+#ifdef FORT
+int Oflag = 0;
+#endif
+extern int Wflag;
+int e2debug = 0;
+int x2debug = 0;
+int udebug = 0;
+int vdebug = 0;
+
+OFFSZ tmpoff;  /* offset for first temporary, in bits for current block */
+OFFSZ maxoff;  /* maximum temporary offset over all blocks in current ftn, in bits */
+int maxtreg;
+
+NODE *stotree;
+int stocook;
+
+OFFSZ baseoff = 0;
+OFFSZ maxtemp = 0;
+
+p2init( argc, argv ) char *argv[];{
+       /* set the values of the pass 2 arguments */
+
+       register int c;
+       register char *cp;
+       register files;
+
+       allo0();  /* free all regs */
+       files = 0;
+
+       for( c=1; c<argc; ++c ){
+               if( *(cp=argv[c]) == '-' ){
+                       while( *++cp ){
+                               switch( *cp ){
+
+                               case 'X':  /* pass1 flags */
+                                       while( *++cp ) { /* VOID */ }
+                                       --cp;
+                                       break;
+
+                               case 'l':  /* linenos */
+                                       ++lflag;
+                                       break;
+
+                               case 'e':  /* expressions */
+                                       ++e2debug;
+                                       break;
+
+                               case 'o':  /* orders */
+                                       ++odebug;
+                                       break;
+
+                               case 'r':  /* register allocation */
+                                       ++rdebug;
+                                       break;
+
+                               case 'a':  /* rallo */
+                                       ++radebug;
+                                       break;
+
+                               case 'v':
+                                       ++vdebug;
+                                       break;
+
+                               case 't':  /* ttype calls */
+                                       ++t2debug;
+                                       break;
+
+                               case 's':  /* shapes */
+                                       ++sdebug;
+                                       break;
+
+                               case 'u':  /* Sethi-Ullman testing (machine dependent) */
+                                       ++udebug;
+                                       break;
+
+                               case 'x':  /* general machine-dependent debugging flag */
+                                       ++x2debug;
+                                       break;
+
+                               case 'w':
+                               case 'W':  /* shut up warnings */
+
+                                       ++Wflag;
+                                       break;
+
+#ifdef FORT
+                               case 'O':  /* optimizing */
+                                       ++Oflag;
+                                       break;
+#endif
+
+                               default:
+                                       cerror( "bad option: %c", *cp );
+                                       }
+                               }
+                       }
+               else files = 1;  /* assumed to be a ftitle */
+               }
+
+       mkdope();
+       setrew();
+       return( files );
+
+       }
+
+# if !defined(FORT) && !defined(ONEPASS)
+unsigned int caloff();
+unsigned int offsz;
+mainp2( argc, argv ) char *argv[]; {
+       register files;
+       register temp;
+       register c;
+       register char *cp;
+       register NODE *p;
+
+       offsz = caloff();
+       files = p2init( argc, argv );
+       tinit();
+
+       reread:
+
+       if( files ){
+               while( files < argc && argv[files][0] == '-' ) {
+                       ++files;
+                       }
+               if( files > argc ) return( nerrors );
+               freopen( argv[files], "r", stdin );
+               }
+       while( (c=getchar()) > 0 ) switch( c ){
+       case ')':
+       default:
+               /* copy line unchanged */
+               if ( c != ')' )
+                       PUTCHAR( c );  /*  initial tab  */
+               while( (c=getchar()) > 0 ){
+                       PUTCHAR(c);
+                       if( c == '\n' ) break;
+                       }
+               continue;
+
+       case BBEG:
+               /* beginning of a block */
+               temp = rdin(10);  /* ftnno */
+               tmpoff = baseoff = (unsigned int) rdin(10); /* autooff for block gives max offset of autos in block */
+               maxtreg = rdin(10);
+               if( getchar() != '\n' ) cerror( "intermediate file format error");
+
+               if( temp != ftnno ){ /* beginning of function */
+                       maxoff = baseoff;
+                       ftnno = temp;
+                       maxtemp = 0;
+                       }
+               else {
+                       if( baseoff > maxoff ) maxoff = baseoff;
+                       /* maxoff at end of ftn is max of autos and temps
+                          over all blocks in the function */
+                       }
+               setregs();
+               continue;
+
+       case BEND:  /* end of block */
+               SETOFF( maxoff, ALSTACK );
+               eobl2();
+               while( (c=getchar()) != '\n' ){
+                       if( c <= 0 ) cerror( "intermediate file format eof" );
+                       }
+               continue;
+
+       case EXPR:
+               /* compile code for an expression */
+               lineno = rdin( 10 );
+               for( cp=ftitle; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads ftitle */
+               *cp = '\0';
+               if( lflag ) lineid( lineno, ftitle );
+
+               tmpoff = baseoff;  /* expression at top level reuses temps */
+               p = eread();
+
+# ifndef BUG4
+               if( e2debug ) fwalk( p, e2print, 0 );
+# endif
+
+# ifdef MYREADER
+               MYREADER(p);  /* do your own laundering of the input */
+# endif
+
+               nrecur = 0;
+               delay( p );  /* expression statement  throws out results */
+               reclaim( p, RNULL, 0 );
+
+               allchk();
+               tcheck();
+               continue;
+
+       default:
+               cerror( "intermediate file format error" );
+
+               }
+
+       /* EOF */
+       if( files ) goto reread;
+       return(nerrors);
+
+       }
+# endif
+
+# ifdef ONEPASS
+p2compile( p ) NODE *p; {
+
+       if( lflag ) lineid( lineno, ftitle );
+       tmpoff = baseoff;  /* expression at top level reuses temps */
+       /* generate code for the tree p */
+# ifndef BUG4
+       if( e2debug ) fwalk( p, e2print, 0 );
+# endif
+
+# ifdef MYREADER
+       MYREADER(p);  /* do your own laundering of the input */
+# endif
+       nrecur = 0;
+       delay( p );  /* do the code generation */
+       reclaim( p, RNULL, 0 );
+       allchk();
+       /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
+       /* first pass will do it... */
+       }
+
+p2bbeg( aoff, myreg ) {
+       static int myftn = -1;
+
+       tmpoff = baseoff = (unsigned int) aoff;
+       maxtreg = myreg;
+       if( myftn != ftnno ){ /* beginning of function */
+               maxoff = baseoff;
+               myftn = ftnno;
+               maxtemp = 0;
+               }
+       else {
+               if( baseoff > maxoff ) maxoff = baseoff;
+               /* maxoff at end of ftn is max of autos and temps over all blocks */
+               }
+       setregs();
+       }
+
+p2bend(){
+       SETOFF( maxoff, ALSTACK );
+       eobl2();
+       }
+# endif
+
+NODE *deltrees[DELAYS];
+int deli;
+
+delay( p ) register NODE *p; {
+       /* look in all legal places for COMOP's and ++ and -- ops to delay */
+       /* note; don't delay ++ and -- within calls or things like
+       /* getchar (in their macro forms) will start behaving strangely */
+       register i;
+
+       /* look for visible COMOPS, and rewrite repeatedly */
+
+       while( delay1( p ) ) { /* VOID */ }
+
+       /* look for visible, delayable ++ and -- */
+
+       deli = 0;
+       delay2( p );
+       codgen( p, FOREFF );  /* do what is left */
+       for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF );  /* do the rest */
+       }
+
+delay1( p ) register NODE *p; {  /* look for COMOPS */
+       register o, ty;
+
+       o = p->in.op;
+       ty = optype( o );
+       if( ty == LTYPE ) return( 0 );
+       else if( ty == UTYPE ) return( delay1( p->in.left ) );
+
+       switch( o ){
+
+       case QUEST:
+       case ANDAND:
+       case OROR:
+               /* don't look on RHS */
+               return( delay1(p->in.left ) );
+
+       case COMOP:  /* the meat of the routine */
+               delay( p->in.left );  /* completely evaluate the LHS */
+               /* rewrite the COMOP */
+               { register NODE *q;
+                       q = p->in.right;
+                       ncopy( p, p->in.right );
+                       q->in.op = FREE;
+                       }
+               return( 1 );
+               }
+
+       return( delay1(p->in.left) || delay1(p->in.right ) );
+       }
+
+delay2( p ) register NODE *p; {
+
+       /* look for delayable ++ and -- operators */
+
+       register o, ty;
+       o = p->in.op;
+       ty = optype( o );
+
+       switch( o ){
+
+       case NOT:
+       case QUEST:
+       case ANDAND:
+       case OROR:
+       case CALL:
+       case UNARY CALL:
+       case STCALL:
+       case UNARY STCALL:
+       case FORTCALL:
+       case UNARY FORTCALL:
+       case COMOP:
+       case CBRANCH:
+               /* for the moment, don't delay past a conditional context, or
+               /* inside of a call */
+               return;
+
+       case UNARY MUL:
+               /* if *p++, do not rewrite */
+               if( autoincr( p ) ) return;
+               break;
+
+       case INCR:
+       case DECR:
+               if( deltest( p ) ){
+                       if( deli < DELAYS ){
+                               register NODE *q;
+                               deltrees[deli++] = tcopy(p);
+                               q = p->in.left;
+                               p->in.right->in.op = FREE;  /* zap constant */
+                               ncopy( p, q );
+                               q->in.op = FREE;
+                               return;
+                               }
+                       }
+
+               }
+
+       if( ty == BITYPE ) delay2( p->in.right );
+       if( ty != LTYPE ) delay2( p->in.left );
+       }
+
+codgen( p, cookie ) NODE *p; {
+
+       /* generate the code for p;
+          order may call codgen recursively */
+       /* cookie is used to describe the context */
+
+       for(;;){
+               canon(p);  /* creats OREG from * if possible and does sucomp */
+               stotree = NIL;
+# ifndef BUG4
+               if( e2debug ){
+                       printf( "store called on:\n" );
+                       fwalk( p, e2print, 0 );
+                       }
+# endif
+               store(p);
+               if( stotree==NIL ) break;
+
+               /* because it's minimal, can do w.o. stores */
+
+               order( stotree, stocook );
+               }
+
+       order( p, cookie );
+
+       }
+
+# ifndef BUG4
+char *cnames[] = {
+       "SANY",
+       "SAREG",
+       "STAREG",
+       "SBREG",
+       "STBREG",
+       "SCC",
+       "SNAME",
+       "SCON",
+       "SFLD",
+       "SOREG",
+# ifdef WCARD1
+       "WCARD1",
+# else
+       "STARNM",
+# endif
+# ifdef WCARD2
+       "WCARD2",
+# else
+       "STARREG",
+# endif
+       "INTEMP",
+       "FORARG",
+       "SWADD",
+       0,
+       };
+
+prcook( cookie ){
+
+       /* print a nice-looking description of cookie */
+
+       int i, flag;
+
+       if( cookie & SPECIAL ){
+               if( cookie == SZERO ) printf( "SZERO" );
+               else if( cookie == SONE ) printf( "SONE" );
+               else if( cookie == SMONE ) printf( "SMONE" );
+               else if( cookie == SCCON ) printf( "SCCON" );
+               else if( cookie == SSCON ) printf( "SSCON" );
+               else if( cookie == SSOREG ) printf( "SSOREG" );
+               else printf( "SPECIAL+%d", cookie & ~SPECIAL );
+               return;
+               }
+
+       flag = 0;
+       for( i=0; cnames[i]; ++i ){
+               if( cookie & (1<<i) ){
+                       if( flag ) printf( "|" );
+                       ++flag;
+                       printf( cnames[i] );
+                       }
+               }
+
+       }
+# endif
+
+int odebug = 0;
+
+order(p,cook) NODE *p; {
+
+       register o, ty, m;
+       int m1;
+       int cookie;
+       NODE *p1, *p2;
+
+       cookie = cook;
+       rcount();
+       canon(p);
+       rallo( p, p->in.rall );
+       goto first;
+       /* by this time, p should be able to be generated without stores;
+          the only question is how */
+
+       again:
+
+       if ( p->in.op == FREE )
+               return;         /* whole tree was done */
+       cookie = cook;
+       rcount();
+       canon(p);
+       rallo( p, p->in.rall );
+       /* if any rewriting and canonicalization has put
+        * the tree (p) into a shape that cook is happy
+        * with (exclusive of FOREFF, FORREW, and INTEMP)
+        * then we are done.
+        * this allows us to call order with shapes in
+        * addition to cookies and stop short if possible.
+        */
+       if( tshape(p, cook &(~(FOREFF|FORREW|INTEMP))) )return;
+
+       first:
+# ifndef BUG4
+       if( odebug ){
+               printf( "order( %o, ", p );
+               prcook( cookie );
+               printf( " )\n" );
+               fwalk( p, e2print, 0 );
+               }
+# endif
+
+       o = p->in.op;
+       ty = optype(o);
+
+       /* first of all, for most ops, see if it is in the table */
+
+       /* look for ops */
+
+       switch( m = p->in.op ){
+
+       default:
+               /* look for op in table */
+               for(;;){
+                       if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
+                       else if( m == MNOPE ){
+                               if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
+                               continue;
+                               }
+                       else break;
+                       }
+               break;
+
+       case COMOP:
+       case FORCE:
+       case CBRANCH:
+       case QUEST:
+       case ANDAND:
+       case OROR:
+       case NOT:
+       case UNARY CALL:
+       case CALL:
+       case UNARY STCALL:
+       case STCALL:
+       case UNARY FORTCALL:
+       case FORTCALL:
+               /* don't even go near the table... */
+               ;
+
+               }
+       /* get here to do rewriting if no match or
+          fall through from above for hard ops */
+
+       p1 = p->in.left;
+       if( ty == BITYPE ) p2 = p->in.right;
+       else p2 = NIL;
+       
+# ifndef BUG4
+       if( odebug ){
+               printf( "order( %o, ", p );
+               prcook( cook );
+               printf( " ), cookie " );
+               prcook( cookie );
+               printf( ", rewrite %s\n", opst[m] );
+               }
+# endif
+       switch( m ){
+       default:
+               nomat:
+               cerror( "no table entry for op %s", opst[p->in.op] );
+
+       case COMOP:
+               codgen( p1, FOREFF );
+               p2->in.rall = p->in.rall;
+               codgen( p2, cookie );
+               ncopy( p, p2 );
+               p2->in.op = FREE;
+               goto cleanup;
+
+       case FORCE:
+               /* recurse, letting the work be done by rallo */
+               p = p->in.left;
+               cook = INTAREG|INTBREG;
+               goto again;
+
+       case CBRANCH:
+               o = p2->tn.lval;
+               cbranch( p1, -1, o );
+               p2->in.op = FREE;
+               p->in.op = FREE;
+               return;
+
+       case QUEST:
+               cbranch( p1, -1, m=get2lab() );
+               p2->in.left->in.rall = p->in.rall;
+               codgen( p2->in.left, INTAREG|INTBREG );
+               /* force right to compute result into same reg used by left */
+               p2->in.right->in.rall = p2->in.left->tn.rval|MUSTDO;
+               reclaim( p2->in.left, RNULL, 0 );
+               cbgen( 0, m1 = get2lab(), 'I' );
+               def2lab( m );
+               codgen( p2->in.right, INTAREG|INTBREG );
+               def2lab( m1 );
+               p->in.op = REG;  /* set up node describing result */
+               p->tn.lval = 0;
+               p->tn.rval = p2->in.right->tn.rval;
+               p->in.type = p2->in.right->in.type;
+               tfree( p2->in.right );
+               p2->in.op = FREE;
+               goto cleanup;
+
+       case ANDAND:
+       case OROR:
+       case NOT:  /* logical operators */
+               /* if here, must be a logical operator for 0-1 value */
+               cbranch( p, -1, m=get2lab() );
+               p->in.op = CCODES;
+               p->bn.label = m;
+               order( p, INTAREG );
+               goto cleanup;
+
+       case FLD:       /* fields of funny type */
+               if ( p1->in.op == UNARY MUL ){
+                       offstar( p1->in.left );
+                       goto again;
+                       }
+
+       case UNARY MINUS:
+               order( p1, INBREG|INAREG );
+               goto again;
+
+       case NAME:
+               /* all leaves end up here ... */
+               if( o == REG ) goto nomat;
+               order( p, INTAREG|INTBREG );
+               goto again;
+
+       case INIT:
+               uerror( "illegal initialization" );
+               return;
+
+       case UNARY FORTCALL:
+               p->in.right = NIL;
+       case FORTCALL:
+               o = p->in.op = UNARY FORTCALL;
+               if( genfcall( p, cookie ) ) goto nomat;
+               goto cleanup;
+
+       case UNARY CALL:
+               p->in.right = NIL;
+       case CALL:
+               o = p->in.op = UNARY CALL;
+               if( gencall( p, cookie ) ) goto nomat;
+               goto cleanup;
+
+       case UNARY STCALL:
+               p->in.right = NIL;
+       case STCALL:
+               o = p->in.op = UNARY STCALL;
+               if( genscall( p, cookie ) ) goto nomat;
+               goto cleanup;
+
+               /* if arguments are passed in register, care must be taken that reclaim
+               /* not throw away the register which now has the result... */
+
+       case UNARY MUL:
+               if( cook == FOREFF ){
+                       /* do nothing */
+                       order( p->in.left, FOREFF );
+                       p->in.op = FREE;
+                       return;
+                       }
+               offstar( p->in.left );
+               goto again;
+
+       case INCR:  /* INCR and DECR */
+               if( setincr(p) ) goto again;
+
+               /* x++ becomes (x += 1) -1; */
+
+               if( cook & FOREFF ){  /* result not needed so inc or dec and be done with it */
+                       /* x++ => x += 1 */
+                       p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
+                       goto again;
+                       }
+
+               p1 = tcopy(p);
+               reclaim( p->in.left, RNULL, 0 );
+               p->in.left = p1;
+               p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
+               p->in.op = (p->in.op==INCR)?MINUS:PLUS;
+               goto again;
+
+       case STASG:
+               if( setstr( p ) ) goto again;
+               goto nomat;
+
+       case ASG PLUS:  /* and other assignment ops */
+               if( setasop(p) ) goto again;
+
+               /* there are assumed to be no side effects in LHS */
+
+               p2 = tcopy(p);
+               p->in.op = ASSIGN;
+               reclaim( p->in.right, RNULL, 0 );
+               p->in.right = p2;
+               canon(p);
+               rallo( p, p->in.rall );
+
+# ifndef BUG4
+               if( odebug ) fwalk( p, e2print, 0 );
+# endif
+
+               order( p2->in.left, INTBREG|INTAREG );
+               order( p2, INTBREG|INTAREG );
+               goto again;
+
+       case ASSIGN:
+               if( setasg( p ) ) goto again;
+               goto nomat;
+
+
+       case BITYPE:
+               if( setbin( p ) ) goto again;
+               /* try to replace binary ops by =ops */
+               switch(o){
+
+               case PLUS:
+               case MINUS:
+               case MUL:
+               case DIV:
+               case MOD:
+               case AND:
+               case OR:
+               case ER:
+               case LS:
+               case RS:
+                       p->in.op = ASG o;
+                       goto again;
+                       }
+               goto nomat;
+
+               }
+
+       cleanup:
+
+       /* if it is not yet in the right state, put it there */
+
+       if( cook & FOREFF ){
+               reclaim( p, RNULL, 0 );
+               return;
+               }
+
+       if( p->in.op==FREE ) return;
+
+       if( tshape( p, cook ) ) return;
+
+       if( (m=match(p,cook) ) == MDONE ) return;
+
+       /* we are in bad shape, try one last chance */
+       if( lastchance( p, cook ) ) goto again;
+
+       goto nomat;
+       }
+
+int callflag;
+int fregs;
+
+store( p ) register NODE *p; {
+
+       /* find a subtree of p which should be stored */
+
+       register o, ty;
+
+       o = p->in.op;
+       ty = optype(o);
+
+       if( ty == LTYPE ) return;
+
+       switch( o ){
+
+       case UNARY CALL:
+       case UNARY FORTCALL:
+       case UNARY STCALL:
+               ++callflag;
+               break;
+
+       case UNARY MUL:
+               if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
+               break;
+
+       case CALL:
+       case FORTCALL:
+       case STCALL:
+               store( p->in.left );
+               stoarg( p->in.right, o );
+               ++callflag;
+               return;
+
+       case COMOP:
+               markcall( p->in.right );
+               if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
+               store( p->in.left );
+               return;
+
+       case ANDAND:
+       case OROR:
+       case QUEST:
+               markcall( p->in.right );
+               if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
+       case CBRANCH:   /* to prevent complicated expressions on the LHS from being stored */
+       case NOT:
+               constore( p->in.left );
+               return;
+
+               }
+
+       if( ty == UTYPE ){
+               store( p->in.left );
+               return;
+               }
+
+       if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );
+
+       if( p->in.su>fregs ){ /* must store */
+               mkadrs( p );  /* set up stotree and stocook to subtree
+                                that must be stored */
+               }
+
+       store( p->in.right );
+       store( p->in.left );
+       }
+
+constore( p ) register NODE *p; {
+
+       /* store conditional expressions */
+       /* the point is, avoid storing expressions in conditional
+          conditional context, since the evaluation order is predetermined */
+
+       switch( p->in.op ) {
+
+       case ANDAND:
+       case OROR:
+       case QUEST:
+               markcall( p->in.right );
+       case NOT:
+               constore( p->in.left );
+               return;
+
+               }
+
+       store( p );
+       }
+
+markcall( p ) register NODE *p; {  /* mark off calls below the current node */
+
+       again:
+       switch( p->in.op ){
+
+       case UNARY CALL:
+       case UNARY STCALL:
+       case UNARY FORTCALL:
+       case CALL:
+       case STCALL:
+       case FORTCALL:
+               ++callflag;
+               return;
+
+               }
+
+       switch( optype( p->in.op ) ){
+
+       case BITYPE:
+               markcall( p->in.right );
+       case UTYPE:
+               p = p->in.left;
+               /* eliminate recursion (aren't I clever...) */
+               goto again;
+       case LTYPE:
+               return;
+               }
+
+       }
+
+stoarg( p, calltype ) register NODE *p; {
+       /* arrange to store the args */
+
+       if( p->in.op == CM ){
+               stoarg( p->in.left, calltype );
+               p = p->in.right ;
+               }
+       if( calltype == CALL ){
+               STOARG(p);
+               }
+       else if( calltype == STCALL ){
+               STOSTARG(p);
+               }
+       else {
+               STOFARG(p);
+               }
+       callflag = 0;
+       store(p);
+# ifndef NESTCALLS
+       if( callflag ){ /* prevent two calls from being active at once  */
+               SETSTO(p,INTEMP);
+               store(p); /* do again to preserve bottom up nature....  */
+               }
+#endif
+       }
+
+int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ;  /* negatives of relationals */
+
+cbranch( p, true, false ) NODE *p; {
+       /* evaluate p for truth value, and branch to true or false
+       /* accordingly: label <0 means fall through */
+
+       register o, lab, flab, tlab;
+
+       lab = -1;
+
+       switch( o=p->in.op ){
+
+       case ULE:
+       case ULT:
+       case UGE:
+       case UGT:
+       case EQ:
+       case NE:
+       case LE:
+       case LT:
+       case GE:
+       case GT:
+               if( true < 0 ){
+                       o = p->in.op = negrel[ o-EQ ];
+                       true = false;
+                       false = -1;
+                       }
+#ifndef NOOPT
+               if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
+                       switch( o ){
+
+                       case UGT:
+                       case ULE:
+                               o = p->in.op = (o==UGT)?NE:EQ;
+                       case EQ:
+                       case NE:
+                       case LE:
+                       case LT:
+                       case GE:
+                       case GT:
+                               if( logop(p->in.left->in.op) ){
+                                       /* strange situation: e.g., (a!=0) == 0 */
+                                       /* must prevent reference to p->in.left->lable, so get 0/1 */
+                                       /* we could optimize, but why bother */
+                                       codgen( p->in.left, INAREG|INBREG );
+                                       }
+                               codgen( p->in.left, FORCC );
+                               cbgen( o, true, 'I' );
+                               break;
+
+                       case UGE:
+                               codgen(p->in.left, FORCC);
+                               cbgen( 0, true, 'I' );  /* unconditional branch */
+                               break;
+                       case ULT:
+                               codgen(p->in.left, FORCC);
+                               }
+                       }
+               else
+#endif
+                       {
+                       p->bn.label = true;
+                       codgen( p, FORCC );
+                       }
+               if( false>=0 ) cbgen( 0, false, 'I' );
+               reclaim( p, RNULL, 0 );
+               return;
+
+       case ANDAND:
+               lab = false<0 ? get2lab() : false ;
+               cbranch( p->in.left, -1, lab );
+               cbranch( p->in.right, true, false );
+               if( false < 0 ) def2lab( lab );
+               p->in.op = FREE;
+               return;
+
+       case OROR:
+               lab = true<0 ? get2lab() : true;
+               cbranch( p->in.left, lab, -1 );
+               cbranch( p->in.right, true, false );
+               if( true < 0 ) def2lab( lab );
+               p->in.op = FREE;
+               return;
+
+       case NOT:
+               cbranch( p->in.left, false, true );
+               p->in.op = FREE;
+               break;
+
+       case COMOP:
+               codgen( p->in.left, FOREFF );
+               p->in.op = FREE;
+               cbranch( p->in.right, true, false );
+               return;
+
+       case QUEST:
+               flab = false<0 ? get2lab() : false;
+               tlab = true<0 ? get2lab() : true;
+               cbranch( p->in.left, -1, lab = get2lab() );
+               cbranch( p->in.right->in.left, tlab, flab );
+               def2lab( lab );
+               cbranch( p->in.right->in.right, true, false );
+               if( true < 0 ) def2lab( tlab);
+               if( false < 0 ) def2lab( flab );
+               p->in.right->in.op = FREE;
+               p->in.op = FREE;
+               return;
+
+       case ICON:
+               if( p->in.type != FLOAT && p->in.type != DOUBLE ){
+
+                       if( p->tn.lval || p->in.name[0] ){
+                               /* addresses of C objects are never 0 */
+                               if( true>=0 ) cbgen( 0, true, 'I' );
+                               }
+                       else if( false>=0 ) cbgen( 0, false, 'I' );
+                       p->in.op = FREE;
+                       return;
+                       }
+               /* fall through to default with other strange constants */
+
+       default:
+               /* get condition codes */
+               codgen( p, FORCC );
+               if( true >= 0 ) cbgen( NE, true, 'I' );
+               if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
+               reclaim( p, RNULL, 0 );
+               return;
+
+               }
+
+       }
+
+rcount(){ /* count recursions */
+       if( ++nrecur > NRECUR ){
+               cerror( "expression causes compiler loop: try simplifying" );
+               }
+
+       }
+
+# ifndef BUG4
+e2print( p, down, a, b ) NODE *p; int *a, *b; {
+
+       *a = *b = down+1;
+       while( down >= 2 ){
+               printf( "\t" );
+               down -= 2;
+               }
+       if( down-- ) printf( "    " );
+
+
+       printf( "%o) %s", p, opst[p->in.op] );
+       switch( p->in.op ) { /* special cases */
+
+       case REG:
+               printf( " %s", rnames[p->tn.rval] );
+               break;
+
+       case ICON:
+       case NAME:
+       case OREG:
+               printf( " " );
+               adrput( p );
+               break;
+
+       case STCALL:
+       case UNARY STCALL:
+       case STARG:
+       case STASG:
+               printf( " size=%d", p->stn.stsize );
+               printf( " align=%d", p->stn.stalign );
+               break;
+               }
+
+       printf( ", " );
+       tprint( p->in.type );
+       printf( ", " );
+       if( p->in.rall == NOPREF ) printf( "NOPREF" );
+       else {
+               if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
+               else printf( "PREF " );
+               printf( "%s", rnames[p->in.rall&~MUSTDO]);
+               }
+       printf( ", SU= %d\n", p->in.su );
+
+       }
+# endif
+
+# if !defined(FORT) && !defined(ONEPASS)
+NODE *
+eread(){
+
+       /* call eread recursively to get subtrees, if any */
+
+       register NODE *p;
+       register i, c;
+       register char *pc;
+       register j;
+
+       i = rdin( 10 );
+
+       p = talloc();
+
+       p->in.op = i;
+
+       i = optype(i);
+
+       if( i == LTYPE ) p->tn.lval = rdin( 10 );
+       if( i != BITYPE ) p->tn.rval = rdin( 10 );
+
+       p->in.type = rdin(8 );
+       p->in.rall = NOPREF;  /* register allocation information */
+
+       if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
+               p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
+               p->stn.stalign = rdin(10) / SZCHAR;
+               if( getchar() != '\n' ) cerror( "illegal \n" );
+               }
+       else {   /* usual case */
+               if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type );  /* non usually, but sometimes justified */
+#ifndef FLEXNAMES
+               for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
+                       if( j < NCHNAM ) *pc++ = c;
+                       }
+               if( j < NCHNAM ) *pc = '\0';
+#else
+               { char buf[BUFSIZ];
+               for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){
+                       if( j < BUFSIZ ) *pc++ = c;
+                       }
+               if( j < BUFSIZ ) *pc = '\0';
+               p->in.name = tstr(buf);
+               }
+#endif
+               }
+
+       /* now, recursively read descendents, if any */
+
+       if( i != LTYPE ) p->in.left = eread();
+       if( i == BITYPE ) p->in.right = eread();
+
+       return( p );
+
+       }
+
+CONSZ
+rdin( base ){
+       register sign, c;
+       CONSZ val;
+
+       sign = 1;
+       val = 0;
+
+       while( (c=getchar()) > 0 ) {
+               if( c == '-' ){
+                       if( val != 0 ) cerror( "illegal -");
+                       sign = -sign;
+                       continue;
+                       }
+               if( c == '\t' ) break;
+               if( c>='0' && c<='9' ) {
+                       val *= base;
+                       if( sign > 0 )
+                               val += c-'0';
+                       else
+                               val -= c-'0';
+                       continue;
+                       }
+               cerror( "illegal character `%c' on intermediate file", c );
+               break;
+               }
+
+       if( c <= 0 ) {
+               cerror( "unexpected EOF");
+               }
+       return( val );
+       }
+# endif
+
+#ifndef FIELDOPS
+       /* do this if there is no special hardware support for fields */
+
+ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
+        /* look for fields that are not in an lvalue context, and rewrite them... */
+       register NODE *shp;
+       register s, o, v, ty;
+
+       *down1 =  asgop( p->in.op );
+       *down2 = 0;
+
+       if( !down && p->in.op == FLD ){ /* rewrite the node */
+
+               if( !rewfld(p) ) return;
+
+               ty = (szty(p->in.type) == 2)? LONG: INT;
+               v = p->tn.rval;
+               s = UPKFSZ(v);
+# ifdef RTOLBYTES
+               o = UPKFOFF(v);  /* amount to shift */
+# else
+               o = szty(p->in.type)*SZINT - s - UPKFOFF(v);  /* amount to shift */
+#endif
+
+               /* make & mask part */
+
+               p->in.left->in.type = ty;
+
+               p->in.op = AND;
+               p->in.right = talloc();
+               p->in.right->in.op = ICON;
+               p->in.right->in.rall = NOPREF;
+               p->in.right->in.type = ty;
+               p->in.right->tn.lval = 1;
+               p->in.right->tn.rval = 0;
+#ifndef FLEXNAMES
+               p->in.right->in.name[0] = '\0';
+#else
+               p->in.right->in.name = "";
+#endif
+               p->in.right->tn.lval <<= s;
+               p->in.right->tn.lval--;
+
+               /* now, if a shift is needed, do it */
+
+               if( o != 0 ){
+                       shp = talloc();
+                       shp->in.op = RS;
+                       shp->in.rall = NOPREF;
+                       shp->in.type = ty;
+                       shp->in.left = p->in.left;
+                       shp->in.right = talloc();
+                       shp->in.right->in.op = ICON;
+                       shp->in.right->in.rall = NOPREF;
+                       shp->in.right->in.type = ty;
+                       shp->in.right->tn.rval = 0;
+                       shp->in.right->tn.lval = o;  /* amount to shift */
+#ifndef FLEXNAMES
+                       shp->in.right->in.name[0] = '\0';
+#else
+                       shp->in.right->in.name = "";
+#endif
+                       p->in.left = shp;
+                       /* whew! */
+                       }
+               }
+       }
+#endif
+
+oreg2( p ) register NODE *p; {
+
+       /* look for situations where2 we can turn * into OREG */
+
+       NODE *q;
+       register i;
+       register r;
+       register char *cp;
+       register NODE *ql, *qr;
+       CONSZ temp;
+
+       if( p->in.op == UNARY MUL ){
+               q = p->in.left;
+               if( q->in.op == REG ){
+                       temp = q->tn.lval;
+                       r = q->tn.rval;
+                       cp = q->in.name;
+                       goto ormake;
+                       }
+
+               if( q->in.op != PLUS && q->in.op != MINUS ) return;
+               ql = q->in.left;
+               qr = q->in.right;
+
+#ifdef R2REGS
+
+               /* look for doubly indexed expressions */
+
+               if( q->in.op == PLUS) {
+                       if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
+                               makeor2(p, ql, r, i);
+                               return;
+                       } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
+                               makeor2(p, qr, r, i);
+                               return;
+                               }
+                       }
+
+
+#endif
+
+               if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
+                               ql->in.op==REG && szty(qr->in.type)==1) {
+                       temp = qr->tn.lval;
+                       if( q->in.op == MINUS ) temp = -temp;
+                       r = ql->tn.rval;
+                       temp += ql->tn.lval;
+                       cp = qr->in.name;
+                       if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
+                       if( !*cp ) cp = ql->in.name;
+
+                       ormake:
+                       if( notoff( p->in.type, r, temp, cp ) ) return;
+                       p->in.op = OREG;
+                       p->tn.rval = r;
+                       p->tn.lval = temp;
+#ifndef FLEXNAMES
+                       for( i=0; i<NCHNAM; ++i )
+                               p->in.name[i] = *cp++;
+#else
+                       p->in.name = cp;
+#endif
+                       tfree(q);
+                       return;
+                       }
+               }
+
+       }
+
+canon(p) NODE *p; {
+       /* put p in canonical form */
+       int oreg2(), sucomp();
+
+#ifndef FIELDOPS
+       int ffld();
+       fwalk( p, ffld, 0 ); /* look for field operators */
+# endif
+       walkf( p, oreg2 );  /* look for and create OREG nodes */
+#ifdef MYCANON
+       MYCANON(p);  /* your own canonicalization routine(s) */
+#endif
+       walkf( p, sucomp );  /* do the Sethi-Ullman computation */
+
+       }
+
diff --git a/lib/pcc/scan.c b/lib/pcc/scan.c
new file mode 100644 (file)
index 0000000..f08b68f
--- /dev/null
@@ -0,0 +1,1153 @@
+#ifndef lint
+static char *sccsid ="@(#)scan.c       2.1 (Berkeley) 4/23/86";
+#endif lint
+
+# include "pass1.h"
+# include <a.out.h>
+# include <stab.h>
+# include <ctype.h>
+# include <signal.h>
+
+       /* temporarily */
+
+int asm_esc = 0; /* asm escaped used in file */
+       /* lexical actions */
+
+# define A_ERR 0               /* illegal character */
+# define A_LET 1               /* saw a letter */
+# define A_DIG 2               /* saw a digit */
+# define A_1C 3                        /* return a single character */
+# define A_STR 4               /* string */
+# define A_CC 5                        /* character constant */
+# define A_BCD 6               /* GCOS BCD constant */
+# define A_SL 7                        /* saw a / */
+# define A_DOT 8               /* saw a . */
+# define A_PL 9                /* + */
+# define A_MI 10               /* - */
+# define A_EQ 11               /* = */
+# define A_NOT 12              /* ! */
+# define A_LT 13               /* < */
+# define A_GT 14               /* > */
+# define A_AND 16              /* & */
+# define A_OR 17               /* | */
+# define A_WS 18               /* whitespace (not \n) */
+# define A_NL 19               /* \n */
+
+       /* character classes */
+
+# define LEXLET 01
+# define LEXDIG 02
+# define LEXOCT 04
+# define LEXHEX 010
+# define LEXWS 020
+# define LEXDOT 040
+
+       /* reserved word actions */
+
+# define AR_TY 0               /* type word */
+# define AR_RW 1               /* simple reserved word */
+# define AR_CL 2               /* storage class word */
+# define AR_S 3                /* struct */
+# define AR_U 4                /* union */
+# define AR_E 5                /* enum */
+# define AR_A 6                /* asm */
+
+       /* text buffer */
+#ifndef FLEXNAMES
+# define LXTSZ 100
+#else
+#define        LXTSZ   BUFSIZ
+#endif
+char yytext[LXTSZ];
+char * lxgcp;
+
+extern int proflg;
+extern int gdebug;
+extern int fpe();
+struct sigvec fpe_sigvec;
+int oldway;            /* allocate storage so lint will compile as well */
+#ifndef LINT
+extern int lastloc;
+#endif
+
+unsigned caloff();
+       /* ARGSUSED */
+mainp1( argc, argv ) int argc; char *argv[]; {  /* control multiple files */
+
+       register i;
+       register char *cp;
+       extern int idebug, bdebug, tdebug, edebug;
+       extern int ddebug, xdebug, gdebug, adebug;
+       extern unsigned int offsz;
+       int fdef = 0;
+       char *release = "PCC/2.1 (Berkeley) 4/23/86";
+
+       offsz = caloff();
+       for( i=1; i<argc; ++i ){
+               if( *(cp=argv[i]) == '-' && *++cp == 'X' ){
+                       while( *++cp ){
+                               switch( *cp ){
+
+                               case 'r':
+                                       fprintf( stderr, "Release: %s\n",
+                                               release );
+                                       break;
+
+                               case 'd':
+                                       ++ddebug;
+                                       break;
+                               case 'i':
+                                       ++idebug;
+                                       break;
+                               case 'b':
+                                       ++bdebug;
+                                       break;
+                               case 't':
+                                       ++tdebug;
+                                       break;
+                               case 'e':
+                                       ++edebug;
+                                       break;
+                               case 'x':
+                                       ++xdebug;
+                                       break;
+                               case 'P':       /* profiling */
+                                       ++proflg;
+                                       break;
+                               case 'g':
+                                       ++gdebug;
+                                       break;
+                               case 'a':
+                                       ++adebug;
+                                       break;
+                               case 'G':
+                                       ++gdebug;
+                                       oldway = 1;
+                                       break;
+                                       }
+                               }
+                       }
+                       else {
+                       if( *(argv[i]) != '-' ) switch( fdef++ ) {
+                               case 0:
+                               case 1:
+                                       if( freopen(argv[i], fdef==1 ? "r" : "w", fdef==1 ? stdin : stdout) == NULL) {
+                                               fprintf(stderr, "ccom:can't open %s\n", argv[i]);
+                                               exit(1);
+                                       }
+                                       break;
+
+                               default:
+                                       ;
+                               }
+                       }
+               }
+
+# ifdef ONEPASS
+       p2init( argc, argv );
+# endif
+
+       for( i=0; i<SYMTSZ; ++i ) stab[i].stype = TNULL;
+
+       lineno = 1;
+
+       lxinit();
+       tinit();
+       mkdope();
+
+       /* dimension table initialization */
+
+       dimtab[NULL] = 0;
+       dimtab[CHAR] = SZCHAR;
+       dimtab[INT] = SZINT;
+       dimtab[FLOAT] = SZFLOAT;
+       dimtab[DOUBLE] = SZDOUBLE;
+       dimtab[LONG] = SZLONG;
+       dimtab[SHORT] = SZSHORT;
+       dimtab[UCHAR] = SZCHAR;
+       dimtab[USHORT] = SZSHORT;
+       dimtab[UNSIGNED] = SZINT;
+       dimtab[ULONG] = SZLONG;
+       /* starts past any of the above */
+       curdim = 16;
+       reached = 1;
+
+       fpe_sigvec.sv_handler = fpe;
+       (void) sigvec(SIGFPE, &fpe_sigvec, (struct sigvec *) NULL);
+
+       yyparse();
+       yyaccpt();
+
+       ejobcode( nerrors ? 1 : 0 );
+       return(nerrors?1:0);
+
+       }
+
+# ifdef ibm
+
+# define CSMASK 0377
+# define CSSZ 256
+
+# else
+
+# define CSMASK 0177
+# define CSSZ 128
+
+# endif
+
+short lxmask[CSSZ+1];
+
+lxenter( s, m ) register char *s; register short m; {
+       /* enter a mask into lxmask */
+       register c;
+
+       while( c= *s++ ) lxmask[c+1] |= m;
+
+       }
+
+
+# define lxget(c,m) (lxgcp=yytext,lxmore(c,m))
+
+lxmore( c, m )  register c, m; {
+       register char *cp;
+
+       *(cp = lxgcp) = c;
+       while( c=getchar(), lxmask[c+1]&m ){
+               if( cp < &yytext[LXTSZ-1] ){
+                       *++cp = c;
+                       }
+               }
+       ungetc(c,stdin);
+       *(lxgcp = cp+1) = '\0';
+       }
+
+struct lxdope {
+       short lxch;     /* the character */
+       short lxact;    /* the action to be performed */
+       short lxtok;    /* the token number to be returned */
+       short lxval;    /* the value to be returned */
+       } lxdope[] = {
+
+       '@',    A_ERR,  0,      0,      /* illegal characters go here... */
+       '_',    A_LET,  0,      0,      /* letters point here */
+       '0',    A_DIG,  0,      0,      /* digits point here */
+       ' ',    A_WS,   0,      0,      /* whitespace goes here */
+       '\n',   A_NL,   0,      0,
+       '"',    A_STR,  0,      0,      /* character string */
+       '\'',   A_CC,   0,      0,      /* character constant */
+       '`',    A_BCD,  0,      0,      /* GCOS BCD constant */
+       '(',    A_1C,   LP,     0,
+       ')',    A_1C,   RP,     0,
+       '{',    A_1C,   LC,     0,
+       '}',    A_1C,   RC,     0,
+       '[',    A_1C,   LB,     0,
+       ']',    A_1C,   RB,     0,
+       '*',    A_1C,   MUL,    MUL,
+       '?',    A_1C,   QUEST,  0,
+       ':',    A_1C,   COLON,  0,
+       '+',    A_PL,   PLUS,   PLUS,
+       '-',    A_MI,   MINUS,  MINUS,
+       '/',    A_SL,   DIVOP,  DIV,
+       '%',    A_1C,   DIVOP,  MOD,
+       '&',    A_AND,  AND,    AND,
+       '|',    A_OR,   OR,     OR,
+       '^',    A_1C,   ER,     ER,
+       '!',    A_NOT,  UNOP,   NOT,
+       '~',    A_1C,   UNOP,   COMPL,
+       ',',    A_1C,   CM,     CM,
+       ';',    A_1C,   SM,     0,
+       '.',    A_DOT,  STROP,  DOT,
+       '<',    A_LT,   RELOP,  LT,
+       '>',    A_GT,   RELOP,  GT,
+       '=',    A_EQ,   ASSIGN, ASSIGN,
+       -1,     A_1C,   0,      0,
+       };
+
+struct lxdope *lxcp[CSSZ+1];
+
+lxinit(){
+       register struct lxdope *p;
+       register i;
+       register char *cp;
+       /* set up character classes */
+
+       lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET );
+       lxenter( "0123456789", LEXDIG );
+       lxenter( "0123456789abcdefABCDEF", LEXHEX );
+               /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */
+       lxenter( " \t\r\b\f\013", LEXWS );
+       lxenter( "01234567", LEXOCT );
+       lxmask['.'+1] |= LEXDOT;
+
+       /* make lxcp point to appropriate lxdope entry for each character */
+
+       /* initialize error entries */
+
+       for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope;
+
+       /* make unique entries */
+
+       for( p=lxdope; ; ++p ) {
+               lxcp[p->lxch+1] = p;
+               if( p->lxch < 0 ) break;
+               }
+
+       /* handle letters, digits, and whitespace */
+       /* by convention, first, second, and third places */
+
+       cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$";
+       while( *cp ) lxcp[*cp++ + 1] = &lxdope[1];
+       cp = "123456789";
+       while( *cp ) lxcp[*cp++ + 1] = &lxdope[2];
+       cp = "\t\b\r\f\013";
+       while( *cp ) lxcp[*cp++ + 1] = &lxdope[3];
+
+       /* first line might have title */
+       lxtitle();
+
+       }
+
+int lxmatch;  /* character to be matched in char or string constant */
+
+lxstr(ct){
+       /* match a string or character constant, up to lxmatch */
+
+       register c;
+       register val;
+       register i;
+
+       i=0;
+       while( (c=getchar()) != lxmatch ){
+               switch( c ) {
+
+               case EOF:
+                       uerror( "unexpected EOF" );
+                       break;
+
+               case '\n':
+                       uerror( "newline in string or char constant" );
+                       ++lineno;
+                       break;
+
+               case '\\':
+                       switch( c = getchar() ){
+
+                       case '\n':
+                               ++lineno;
+                               continue;
+
+                       default:
+                               val = c;
+                               goto mkcc;
+
+                       case 'n':
+                               val = '\n';
+                               goto mkcc;
+
+                       case 'r':
+                               val = '\r';
+                               goto mkcc;
+
+                       case 'b':
+                               val = '\b';
+                               goto mkcc;
+
+                       case 't':
+                               val = '\t';
+                               goto mkcc;
+
+                       case 'f':
+                               val = '\f';
+                               goto mkcc;
+
+                       case 'v':
+                               val = '\013';
+                               goto mkcc;
+
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                               val = c-'0';
+                               c=getchar();  /* try for 2 */
+                               if( lxmask[c+1] & LEXOCT ){
+                                       val = (val<<3) | (c-'0');
+                                       c = getchar();  /* try for 3 */
+                                       if( lxmask[c+1] & LEXOCT ){
+                                               val = (val<<3) | (c-'0');
+                                               }
+                                       else ungetc( c ,stdin);
+                                       }
+                               else ungetc( c ,stdin);
+
+                               goto mkcc1;
+
+                               }
+               default:
+                       val =c;
+               mkcc:
+                       val = CCTRANS(val);
+               mkcc1:
+                       if( lxmatch == '\'' ){
+                               val = CHARCAST(val);  /* it is, after all, a "character" constant */
+                               makecc( val, i );
+                               }
+                       else { /* stash the byte into the string */
+                               if( strflg ) {
+                                       if( ct==0 || i<ct ) putbyte( val );
+                                       else if( i == ct ) werror( "non-null byte ignored in string initializer" );
+                                       }
+                               else bycode( val, i );
+                               }
+                       ++i;
+                       continue;
+                       }
+               break;
+               }
+       /* end of string or  char constant */
+
+       if( lxmatch == '"' ){
+               if( strflg ){ /* end the string */
+                       if( ct==0 || i<ct ) putbyte( 0 );  /* the null at the end */
+                       }
+               else {  /* the initializer gets a null byte */
+                       bycode( 0, i++ );
+                       bycode( -1, i );
+                       dimtab[curdim] = i;  /* in case of later sizeof ... */
+                       }
+               }
+       else { /* end the character constant */
+               if( i == 0 ) uerror( "empty character constant" );
+               if( i>(SZINT/SZCHAR) || ( (pflag||hflag)&&i>1) )
+                       uerror( "too many characters in character constant" );
+               }
+       }
+
+lxcom(){
+       register c;
+       /* saw a /*: process a comment */
+
+       for(;;){
+
+               switch( c = getchar() ){
+
+               case EOF:
+                       uerror( "unexpected EOF" );
+                       return;
+
+               case '\n':
+                       ++lineno;
+
+               default:
+                       continue;
+
+               case '*':
+                       if( (c = getchar()) == '/' ) return;
+                       else ungetc( c ,stdin);
+                       continue;
+
+# ifdef LINT
+               case 'V':
+                       lxget( c, LEXLET|LEXDIG );
+                       {
+                               extern int vaflag;
+                               int i;
+                               i = yytext[7]?yytext[7]-'0':0;
+                               yytext[7] = '\0';
+                               if( strcmp( yytext, "VARARGS" ) ) continue;
+                               vaflag = i;
+                               continue;
+                               }
+               case 'L':
+                       lxget( c, LEXLET );
+                       if( strcmp( yytext, "LINTLIBRARY" ) ) continue;
+                       {
+                               extern int libflag;
+                               libflag = 1;
+                               }
+                       continue;
+
+               case 'A':
+                       lxget( c, LEXLET );
+                       if( strcmp( yytext, "ARGSUSED" ) ) continue;
+                       {
+                               extern int argflag, vflag;
+                               argflag = 1;
+                               vflag = 0;
+                               }
+                       continue;
+
+               case 'N':
+                       lxget( c, LEXLET );
+                       if( strcmp( yytext, "NOTREACHED" ) ) continue;
+                       reached = 0;
+                       continue;
+# endif
+                       }
+               }
+       }
+
+yylex(){
+       for(;;){
+
+               register lxchar;
+               register struct lxdope *p;
+               register struct symtab *sp;
+               int id;
+
+               switch( (p=lxcp[(lxchar=getchar())+1])->lxact ){
+
+               onechar:
+                       ungetc( lxchar ,stdin);
+
+               case A_1C:
+                       /* eat up a single character, and return an opcode */
+
+                       yylval.intval = p->lxval;
+                       return( p->lxtok );
+
+               case A_ERR:
+                       uerror( "illegal character: %03o (octal)", lxchar );
+                       break;
+
+               case A_LET:
+                       /* collect an identifier, check for reserved word, and return */
+                       lxget( lxchar, LEXLET|LEXDIG );
+                       if( (lxchar=lxres()) > 0 ) return( lxchar ); /* reserved word */
+                       if( lxchar== 0 ) continue;
+#ifdef FLEXNAMES
+                       id = lookup( hash(yytext),
+#else
+                       id = lookup( yytext,
+#endif
+                               /* tag name for struct/union/enum */
+                               (stwart&TAGNAME)? STAG:
+                               /* member name for struct/union */
+                               (stwart&(INSTRUCT|INUNION|FUNNYNAME))?SMOS:0 );
+                       sp = &stab[id];
+                       if( sp->sclass == TYPEDEF && !stwart ){
+                               stwart = instruct;
+                               yylval.nodep = mkty( sp->stype, sp->dimoff, sp->sizoff );
+                               return( TYPE );
+                               }
+                       stwart = (stwart&SEENAME) ? instruct : 0;
+                       yylval.intval = id;
+                       return( NAME );
+
+               case A_DIG:
+                       /* collect a digit string, then look at last one... */
+                       lastcon = 0;
+                       lxget( lxchar, LEXDIG );
+                       switch( lxchar=getchar() ){
+
+                       case 'x':
+                       case 'X':
+                               if( yytext[0] != '0' && !yytext[1] ) uerror( "illegal hex constant" );
+                               lxmore( lxchar, LEXHEX );
+                               /* convert the value */
+                               {
+                                       register char *cp;
+                                       for( cp = yytext+2; *cp; ++cp ){
+                                               /* this code won't work for all wild character sets,
+                                                  but seems ok for ascii and ebcdic */
+                                               lastcon <<= 4;
+                                               if( isdigit( *cp ) ) lastcon += *cp-'0';
+                                               else if( isupper( *cp ) ) lastcon += *cp - 'A'+ 10;
+                                               else lastcon += *cp - 'a'+ 10;
+                                               }
+                                       }
+
+                       hexlong:
+                               /* criterion for longness for hex and octal constants is that it
+                                  fit within 0177777 */
+                               if( lastcon & ~0177777L ) yylval.intval = 1;
+                               else yylval.intval = 0;
+
+                               goto islong;
+
+                       case '.':
+                               lxmore( lxchar, LEXDIG );
+
+                       getfp:
+                               if( (lxchar=getchar()) == 'e' || lxchar == 'E' ){ /* exponent */
+
+                       case 'e':
+                       case 'E':
+                                       if( (lxchar=getchar()) == '+' || lxchar == '-' ){
+                                               *lxgcp++ = 'e';
+                                               }
+                                       else {
+                                               ungetc(lxchar,stdin);
+                                               lxchar = 'e';
+                                               }
+                                       lxmore( lxchar, LEXDIG );
+                                       /* now have the whole thing... */
+                                       }
+                               else {  /* no exponent */
+                                       ungetc( lxchar ,stdin);
+                                       }
+                               return( isitfloat( yytext ) );
+
+                       default:
+                               ungetc( lxchar ,stdin);
+                               if( yytext[0] == '0' ){
+                                       /* convert in octal */
+                                       register char *cp;
+                                       for( cp = yytext+1; *cp; ++cp ){
+                                               lastcon <<= 3;
+                                               lastcon += *cp - '0';
+                                               }
+                                       goto hexlong;
+                                       }
+                               else {
+                                       /* convert in decimal */
+                                       register char *cp;
+                                       for( cp = yytext; *cp; ++cp ){
+                                               lastcon = lastcon * 10 + *cp - '0';
+                                               }
+                                       }
+
+                               /* decide if it is long or not (decimal case) */
+
+                               /* if it is positive and fits in 15 bits, or negative and
+                                  and fits in 15 bits plus an extended sign, it is int; otherwise long */
+                               /* if there is an l or L following, all bets are off... */
+
+                               {       CONSZ v;
+                                       v = lastcon & ~077777L;
+                                       if( v == 0 || v == ~077777L ) yylval.intval = 0;
+                                       else yylval.intval = 1;
+                                       }
+
+                       islong:
+                               /* finally, look for trailing L or l */
+                               if( (lxchar = getchar()) == 'L' || lxchar == 'l' ) yylval.intval = 1;
+                               else ungetc( lxchar ,stdin);
+                               return( ICON );
+                               }
+
+               case A_DOT:
+                       /* look for a dot: if followed by a digit, floating point */
+                       lxchar = getchar();
+                       if( lxmask[lxchar+1] & LEXDIG ){
+                               ungetc(lxchar,stdin);
+                               lxget( '.', LEXDIG );
+                               goto getfp;
+                               }
+                       stwart = FUNNYNAME;
+                       goto onechar;
+
+               case A_STR:
+                       /* string constant */
+                       lxmatch = '"';
+                       return( STRING );
+
+               case A_CC:
+                       /* character constant */
+                       lxmatch = '\'';
+                       lastcon = 0;
+                       lxstr(0);
+                       yylval.intval = 0;
+                       return( ICON );
+
+               case A_BCD:
+                       {
+                               register i;
+                               int j;
+                               for( i=0; i<LXTSZ; ++i ){
+                                       if( ( j = getchar() ) == '`' ) break;
+                                       if( j == '\n' ){
+                                               uerror( "newline in BCD constant" );
+                                               break;
+                                               }
+                                       yytext[i] = j;
+                                       }
+                               yytext[i] = '\0';
+                               if( i>6 ) uerror( "BCD constant exceeds 6 characters" );
+# ifdef gcos
+                               else strtob( yytext, &lastcon, i );
+                               lastcon >>= 6*(6-i);
+# else
+                               uerror( "gcos BCD constant illegal" );
+# endif
+                               yylval.intval = 0;  /* not long */
+                               return( ICON );
+                               }
+
+               case A_SL:
+                       /* / */
+                       if( (lxchar=getchar()) != '*' ) goto onechar;
+                       lxcom();
+               case A_WS:
+                       continue;
+
+               case A_NL:
+                       ++lineno;
+                       lxtitle();
+                       continue;
+
+               case A_NOT:
+                       /* ! */
+                       if( (lxchar=getchar()) != '=' ) goto onechar;
+                       yylval.intval = NE;
+                       return( EQUOP );
+
+               case A_MI:
+                       /* - */
+                       if( (lxchar=getchar()) == '-' ){
+                               yylval.intval = DECR;
+                               return( INCOP );
+                               }
+                       if( lxchar != '>' ) goto onechar;
+                       stwart = FUNNYNAME;
+                       yylval.intval=STREF;
+                       return( STROP );
+
+               case A_PL:
+                       /* + */
+                       if( (lxchar=getchar()) != '+' ) goto onechar;
+                       yylval.intval = INCR;
+                       return( INCOP );
+
+               case A_AND:
+                       /* & */
+                       if( (lxchar=getchar()) != '&' ) goto onechar;
+                       return( yylval.intval = ANDAND );
+
+               case A_OR:
+                       /* | */
+                       if( (lxchar=getchar()) != '|' ) goto onechar;
+                       return( yylval.intval = OROR );
+
+               case A_LT:
+                       /* < */
+                       if( (lxchar=getchar()) == '<' ){
+                               yylval.intval = LS;
+                               return( SHIFTOP );
+                               }
+                       if( lxchar != '=' ) goto onechar;
+                       yylval.intval = LE;
+                       return( RELOP );
+
+               case A_GT:
+                       /* > */
+                       if( (lxchar=getchar()) == '>' ){
+                               yylval.intval = RS;
+                               return(SHIFTOP );
+                               }
+                       if( lxchar != '=' ) goto onechar;
+                       yylval.intval = GE;
+                       return( RELOP );
+
+               case A_EQ:
+                       /* = */
+                       switch( lxchar = getchar() ){
+
+                       case '=':
+                               yylval.intval = EQ;
+                               return( EQUOP );
+
+                       case '+':
+                               yylval.intval = ASG PLUS;
+                               break;
+
+                       case '-':
+                               yylval.intval = ASG MINUS;
+
+                       warn:
+                               if( lxmask[ (lxchar=getchar())+1] & (LEXLET|LEXDIG|LEXDOT) ){
+                                       werror( "ambiguous assignment: assignment op taken" );
+                                       }
+                               ungetc( lxchar ,stdin);
+                               break;
+
+                       case '*':
+                               yylval.intval = ASG MUL;
+                               goto warn;
+
+                       case '/':
+                               yylval.intval = ASG DIV;
+                               break;
+
+                       case '%':
+                               yylval.intval = ASG MOD;
+                               break;
+
+                       case '&':
+                               yylval.intval = ASG AND;
+                               break;
+
+                       case '|':
+                               yylval.intval = ASG OR;
+                               break;
+
+                       case '^':
+                               yylval.intval = ASG ER;
+                               break;
+
+                       case '<':
+                               if( (lxchar=getchar()) != '<' ){
+                                       uerror( "=<%c illegal", lxchar );
+                                       }
+                               yylval.intval = ASG LS;
+                               break;
+
+                       case '>':
+                               if( (lxchar=getchar()) != '>' ){
+                                       uerror( "=>%c illegal", lxchar );
+                                       }
+                               yylval.intval = ASG RS;
+                               break;
+
+                       default:
+                               goto onechar;
+
+                               }
+
+                       return( ASOP );
+
+               default:
+                       cerror( "yylex error, character %03o (octal)", lxchar );
+
+                       }
+
+               /* ordinarily, repeat here... */
+               cerror( "out of switch in yylex" );
+
+               }
+
+       }
+
+struct lxrdope {
+       /* dope for reserved, in alphabetical order */
+
+       char *lxrch;    /* name of reserved word */
+       short lxract;   /* reserved word action */
+       short lxrval;   /* value to be returned */
+       } lxrdope[] = {
+
+       "asm",          AR_A,   0,
+       "auto",         AR_CL,  AUTO,
+       "break",        AR_RW,  BREAK,
+       "char",         AR_TY,  CHAR,
+       "case",         AR_RW,  CASE,
+       "continue",     AR_RW,  CONTINUE,
+       "double",       AR_TY,  DOUBLE,
+       "default",      AR_RW,  DEFAULT,
+       "do",           AR_RW,  DO,
+       "extern",       AR_CL,  EXTERN,
+       "else",         AR_RW,  ELSE,
+       "enum",         AR_E,   ENUM,
+       "for",          AR_RW,  FOR,
+       "float",        AR_TY,  FLOAT,
+       "fortran",      AR_CL,  FORTRAN,
+       "goto",         AR_RW,  GOTO,
+       "if",           AR_RW,  IF,
+       "int",          AR_TY,  INT,
+       "long",         AR_TY,  LONG,
+       "return",       AR_RW,  RETURN,
+       "register",     AR_CL,  REGISTER,
+       "switch",       AR_RW,  SWITCH,
+       "struct",       AR_S,   0,
+       "sizeof",       AR_RW,  SIZEOF,
+       "short",        AR_TY,  SHORT,
+       "static",       AR_CL,  STATIC,
+       "typedef",      AR_CL,  TYPEDEF,
+       "unsigned",     AR_TY,  UNSIGNED,
+       "union",        AR_U,   0,
+       "void",         AR_TY,  UNDEF, /* tymerge adds FTN */
+       "while",        AR_RW,  WHILE,
+       "",             0,      0,      /* to stop the search */
+       };
+
+lxres() {
+       /* check to see of yytext is reserved; if so,
+       /* do the appropriate action and return */
+       /* otherwise, return -1 */
+
+       register c, ch;
+       register struct lxrdope *p;
+
+       ch = yytext[0];
+
+       if( !islower(ch) ) return( -1 );
+
+       switch( ch ){
+
+       case 'a':
+               c=0; break;
+       case 'b':
+               c=2; break;
+       case 'c':
+               c=3; break;
+       case 'd':
+               c=6; break;
+       case 'e':
+               c=9; break;
+       case 'f':
+               c=12; break;
+       case 'g':
+               c=15; break;
+       case 'i':
+               c=16; break;
+       case 'l':
+               c=18; break;
+       case 'r':
+               c=19; break;
+       case 's':
+               c=21; break;
+       case 't':
+               c=26; break;
+       case 'u':
+               c=27; break;
+       case 'v':
+               c=29; break;
+       case 'w':
+               c=30; break;
+
+       default:
+               return( -1 );
+               }
+
+       for( p= lxrdope+c; p->lxrch[0] == ch; ++p ){
+               if( !strcmp( yytext, p->lxrch ) ){ /* match */
+                       switch( p->lxract ){
+
+                       case AR_TY:
+                               /* type word */
+                               stwart = instruct;
+                               yylval.nodep = mkty( (TWORD)p->lxrval, 0, p->lxrval );
+                               return( TYPE );
+
+                       case AR_RW:
+                               /* ordinary reserved word */
+                               return( yylval.intval = p->lxrval );
+
+                       case AR_CL:
+                               /* class word */
+                               yylval.intval = p->lxrval;
+                               return( CLASS );
+
+                       case AR_S:
+                               /* struct */
+                               stwart = INSTRUCT|SEENAME|TAGNAME;
+                               yylval.intval = INSTRUCT;
+                               return( STRUCT );
+
+                       case AR_U:
+                               /* union */
+                               stwart = INUNION|SEENAME|TAGNAME;
+                               yylval.intval = INUNION;
+                               return( STRUCT );
+
+                       case AR_E:
+                               /* enums */
+                               stwart = SEENAME|TAGNAME;
+                               return( yylval.intval = ENUM );
+
+                       case AR_A:
+                               /* asm */
+                               asm_esc = 1; /* warn the world! */
+                               lxget( ' ', LEXWS );
+                               if( getchar() != '(' ) goto badasm;
+                               lxget( ' ', LEXWS );
+                               if( getchar() != '"' ) goto badasm;
+# ifndef ONEPASS
+# ifndef LINT
+                               putchar(')');
+# endif
+# endif
+                               while( (c=getchar()) != '"' ){
+                                       if( c=='\n' || c==EOF ) goto badasm;
+# ifndef LINT
+                                       putchar(c);
+# endif
+                                       }
+                               lxget( ' ', LEXWS );
+                               if( getchar() != ')' ) goto badasm;
+# ifndef LINT
+                               putchar('\n');
+# endif
+                               return( 0 );
+
+                       badasm:
+                               uerror( "bad asm construction" );
+                               return( 0 );
+
+                       default:
+                               cerror( "bad AR_?? action" );
+                               }
+                       }
+               }
+       return( -1 );
+       }
+
+extern int     labelno;
+
+lxtitle(){
+       /* called after a newline; set linenumber and file name */
+
+       register c, val;
+       register char *cp, *cq;
+
+       for(;;){  /* might be several such lines in a row */
+               if( (c=getchar()) != '#' ){
+                       if( c != EOF ) ungetc(c,stdin);
+#ifndef LINT
+                       if ( lastloc != PROG) return;
+                       cp = ftitle;
+                       cq = ititle;
+                       while ( *cp ) if (*cp++ != *cq++) return;
+                       if ( *cq ) return;
+                       psline();
+#endif
+                       return;
+                       }
+
+               lxget( ' ', LEXWS );
+               val = 0;
+               for( c=getchar(); isdigit(c); c=getchar() ){
+                       val = val*10+ c - '0';
+                       }
+               if( c == EOF )
+                       continue;
+               ungetc( c, stdin );
+               lineno = val;
+               lxget( ' ', LEXWS );
+               if( (c=getchar()) != '\n' && c != EOF ){
+                       for( cp=ftitle; c!=EOF && c!='\n'; c=getchar(),++cp ){
+                               *cp = c;
+                               }
+                       *cp = '\0';
+#ifndef LINT
+                       if (ititle[0] == '\0') {
+                               cp = ftitle;
+                               cq = ititle;
+                               while ( *cp )  
+                                       *cq++ = *cp++;
+                               *cq = '\0';
+                               *--cq = '\0';
+#ifndef FLEXNAMES
+                               for ( cp = ititle+1; *(cp-1); cp += 8 ) {
+                                       pstab(cp, N_SO);
+                                       if (gdebug) printf("0,0,LL%d\n", labelno);
+                                       }
+#else
+                               pstab(ititle+1, N_SO);
+                               if (gdebug) printf("0,0,LL%d\n", labelno);
+#endif
+
+                               *cq = '"';
+                               printf("LL%d:\n", labelno++);
+                               }
+#endif
+                       }
+               }
+       }
+
+#ifdef FLEXNAMES
+#define        NSAVETAB        4096
+char   *savetab;
+int    saveleft;
+
+char *
+savestr(cp)
+       register char *cp;
+{
+       register int len;
+
+       len = strlen(cp) + 1;
+       if (len > saveleft) {
+               saveleft = NSAVETAB;
+               if (len > saveleft)
+                       saveleft = len;
+               savetab = (char *)malloc(saveleft);
+               if (savetab == 0)
+                       cerror("Ran out of memory (savestr)");
+       }
+       strncpy(savetab, cp, len);
+       cp = savetab;
+       savetab += len;
+       saveleft -= len;
+       return (cp);
+}
+
+/*
+ * The definition for the segmented hash tables.
+ */
+#define        MAXHASH 20
+#define        HASHINC 1013
+struct ht {
+       char    **ht_low;
+       char    **ht_high;
+       int     ht_used;
+} htab[MAXHASH];
+
+char *
+hash(s)
+       char *s;
+{
+       register char **h;
+       register i;
+       register char *cp;
+       struct ht *htp;
+       int sh;
+
+       /*
+        * The hash function is a modular hash of
+        * the sum of the characters with the sum
+        * doubled before each successive character
+        * is added.
+        */
+       cp = s;
+       i = 0;
+       while (*cp)
+               i = i*2 + *cp++;
+       sh = (i&077777) % HASHINC;
+       cp = s;
+       /*
+        * There are as many as MAXHASH active
+        * hash tables at any given point in time.
+        * The search starts with the first table
+        * and continues through the active tables
+        * as necessary.
+        */
+       for (htp = htab; htp < &htab[MAXHASH]; htp++) {
+               if (htp->ht_low == 0) {
+                       register char **hp =
+                           (char **) calloc(sizeof (char **), HASHINC);
+                       if (hp == 0)
+                               cerror("ran out of memory (hash)");
+                       htp->ht_low = hp;
+                       htp->ht_high = htp->ht_low + HASHINC;
+               }
+               h = htp->ht_low + sh;
+               /*
+                * quadratic rehash increment
+                * starts at 1 and incremented
+                * by two each rehash.
+                */
+               i = 1;
+               do {
+                       if (*h == 0) {
+                               if (htp->ht_used > (HASHINC * 3)/4)
+                                       break;
+                               htp->ht_used++;
+                               *h = savestr(cp);
+                               return (*h);
+                       }
+                       if (**h == *cp && strcmp(*h, cp) == 0)
+                               return (*h);
+                       h += i;
+                       i += 2;
+                       if (h >= htp->ht_high)
+                               h -= HASHINC;
+               } while (i < HASHINC);
+       }
+       cerror("ran out of hash tables");
+}
+#endif
index 44bd82f..312cb22 100644 (file)
@@ -14,21 +14,13 @@ static char *sccsid ="@(#)stab.c    1.12 (Berkeley) 3/27/86";
 #include <a.out.h>
 #include <stab.h>
 
-#define private static
-#define and &&
-#define or ||
-#define not !
-#define div /
-#define mod %
-#define nil 0
-
 #define bytes(bits) ((bits) / SZCHAR)
 #define bsize(p) bytes(dimtab[p->sizoff])      /* size in bytes of a symbol */
 
 #define NILINDEX -1
 #define FORWARD -2
 
-typedef int Boolean;
+typedef int bool;
 
 #define false 0
 #define true 1
@@ -40,10 +32,36 @@ extern char *malloc();
 int stabLCSYM;
 
 /*
- * Flag for producing either sdb or dbx symbol information.
+ * Flag for producing either sdb || dbx symbol information.
  */
 int oldway = false;
 
+/*
+ * Since type names are lost in the travels && because C has
+ * structural type equivalence we keep a table of type words that
+ * we've already seen.  The first time we see a type, it is assigned
+ * (inline) a number && future references just list that number.
+ * Structures, unions, enums, && arrays must be handled carefully
+ * since ! all the necessary information is in the type word.
+ */
+
+typedef struct Typeid *Typeid;
+
+struct Typeid {
+    TWORD tword;
+    int tarray;
+    int tstruct;
+    int tstrtag;
+    int tnum;
+    Typeid chain;
+};
+
+#define TABLESIZE 2003
+
+static int tcount = 1;
+static int t_int, t_char;
+static Typeid typetable[TABLESIZE];
+
 /*
  * Generate debugging info for a parameter.
  * The offset isn't known when it is first entered into the symbol table
@@ -65,28 +83,24 @@ struct symtab *p;
 /*
  * Determine if the given symbol is a global array with dimension 0,
  * which only makes sense if it's dimension is to be given later.
- * We therefore currently do not generate symbol information for
+ * We therefore currently do ! generate symbol information for
  * such entries.
  */
 
-#define isglobal(class) ( \
-    class == EXTDEF or class == EXTERN or class == STATIC \
-)
-
-private Boolean zero_length_array(p)
+static bool zero_length_array(p)
 register struct symtab *p;
 {
-    Boolean b;
+    bool b;
     int t;
 
-    if (not isglobal(p->sclass)) {
+    if (p->sclass != EXTDEF && p->sclass != EXTERN && p->sclass != STATIC) {
        b = false;
     } else {
        t = p->stype;
        if (ISFTN(t)) {
            t = DECREF(t);
        }
-       b = (Boolean) (ISARY(t) and dimtab[p->dimoff] == 0);
+       b = (bool) (ISARY(t) && dimtab[p->dimoff] == 0);
     }
     return b;
 }
@@ -101,12 +115,12 @@ struct symtab *sym;
     register struct symtab *p;
     char *classname;
     int offset;
-    Boolean ignore;
-    static Boolean firsttime = true;
+    bool ignore;
+    static bool firsttime = true;
 
     if (oldway) {
        old_outstab(sym);
-    } else if (gdebug and not zero_length_array(sym)) {
+    } else if (gdebug && ! zero_length_array(sym)) {
        if (firsttime) {
            firsttime = false;
            inittypes();
@@ -171,7 +185,7 @@ struct symtab *sym;
            ignore = true;
            break;
        }
-       if (not ignore) {
+       if (! ignore) {
            printf("\t.stabs\t\"%s:%s", p->sname, classname);
            gentype(p);
            geninfo(p);
@@ -179,37 +193,11 @@ struct symtab *sym;
     }
 }
 
-/*
- * Since type names are lost in the travels and because C has
- * structural type equivalence we keep a table of type words that
- * we've already seen.  The first time we see a type, it is assigned
- * (inline) a number and future references just list that number.
- * Structures, unions, enums, and arrays must be handled carefully
- * since not all the necessary information is in the type word.
- */
-
-typedef struct Typeid *Typeid;
-
-struct Typeid {
-    TWORD tword;
-    int tarray;
-    int tstruct;
-    int tstrtag;
-    int tnum;
-    Typeid chain;
-};
-
-#define TABLESIZE 2003
-
-private int tcount = 1;
-private int t_int, t_char;
-private Typeid typetable[TABLESIZE];
-
 /*
  * Look for the given type word in the type table.
  */
 
-private Typeid typelookup(type, arrindex, strindex, strtag)
+static Typeid typelookup(type, arrindex, strindex, strtag)
 TWORD type;
 int arrindex;
 int strindex;
@@ -219,17 +207,17 @@ int strtag;
     register int i1, i2;
     Typeid t;
 
-    t = typetable[type mod TABLESIZE];
-    while (t != nil) {
-       if (t->tword == type and
-         strindex == t->tstruct and strtag == t->tstrtag) {
+    t = typetable[type % TABLESIZE];
+    while (t != 0) {
+       if (t->tword == type &&
+         strindex == t->tstruct && strtag == t->tstrtag) {
            if (arrindex == NILINDEX) {
                break;
            } else {
                tword = type;
                i1 = arrindex;
                i2 = t->tarray;
-               while (ISARY(tword) and dimtab[i1] == dimtab[i2]) {
+               while (ISARY(tword) && dimtab[i1] == dimtab[i2]) {
                    ++i1;
                    ++i2;
                    tword >>= TSHIFT;
@@ -245,10 +233,10 @@ int strtag;
 }
 
 /*
- * Enter a type word and associated symtab indices into the type table.
+ * Enter a type word && associated symtab indices into the type table.
  */
 
-private int entertype(type, arrindex, strindex, strtag)
+static int entertype(type, arrindex, strindex, strtag)
 TWORD type;
 int arrindex;
 int strindex;
@@ -264,7 +252,7 @@ int strtag;
     t->tstrtag = strtag;
     t->tnum = tcount;
     ++tcount;
-    i = type mod TABLESIZE;
+    i = type % TABLESIZE;
     t->chain = typetable[i];
     typetable[i] = t;
     return t->tnum;
@@ -276,7 +264,7 @@ int strtag;
  * as the old one.
  */
 
-private reentertype(typeid, type, arrindex, strindex, strtag)
+static reentertype(typeid, type, arrindex, strindex, strtag)
 Typeid typeid;
 TWORD type;
 int arrindex;
@@ -292,7 +280,7 @@ int strtag;
     t->tstruct = strindex;
     t->tstrtag = strtag;
     t->tnum = typeid->tnum;
-    i = type mod TABLESIZE;
+    i = type % TABLESIZE;
     t->chain = typetable[i];
     typetable[i] = t;
 }
@@ -303,7 +291,7 @@ int strtag;
 
 #define builtintype(type) entertype(type, NILINDEX, NILINDEX, NILINDEX)
 
-private inittypes()
+static inittypes()
 {
     int t;
 
@@ -321,30 +309,30 @@ private inittypes()
     maketype("double", builtintype(DOUBLE), t_int, 8L, 0L);
     t = builtintype(UNDEF);
     printf("\t.stabs\t\"void:t%d=%d", t, t);
-    geninfo(nil);
+    geninfo(0);
     t = builtintype(FARG);
     printf("\t.stabs\t\"???:t%d=%d", t, t_int);
-    geninfo(nil);
+    geninfo(0);
 }
 
 /*
  * Generate info for a new range type.
  */
 
-private maketype(name, tnum, eqtnum, lower, upper)
+static maketype(name, tnum, eqtnum, lower, upper)
 char *name;
 int tnum, eqtnum;
 long lower, upper;
 {
     printf("\t.stabs\t\"%s:t%d=r%d;%d;%d;", name, tnum, eqtnum, lower, upper);
-    geninfo(nil);
+    geninfo(0);
 }
 
 /*
  * Generate debugging information for the given type of the given symbol.
  */
 
-private gentype(sym)
+static gentype(sym)
 struct symtab *sym;
 {
     register struct symtab *p;
@@ -364,7 +352,7 @@ struct symtab *sym;
     } else {
        arrindex = NILINDEX;
     }
-    if (basictype == STRTY or basictype == UNIONTY or basictype == ENUMTY) {
+    if (basictype == STRTY || basictype == UNIONTY || basictype == ENUMTY) {
        strindex = dimtab[p->sizoff + 1];
        if (strindex == -1) {
            strindex = FORWARD;
@@ -378,7 +366,7 @@ struct symtab *sym;
     }
     i = arrindex;
     typeid = typelookup(t, arrindex, strindex, strtag);
-    while (t != basictype and typeid == nil) {
+    while (t != basictype && typeid == 0) {
        printf("%d=", entertype(t, i, strindex, strtag));
        switch (t&TMASK) {
        case PTR:
@@ -403,10 +391,10 @@ struct symtab *sym;
            typeid = typelookup(t, i, strindex, strtag);
        }
     }
-    if (typeid == nil) {
+    if (typeid == 0) {
        if (strindex == FORWARD) {
            typeid = typelookup(t, NILINDEX, FORWARD, dimtab[p->sizoff + 3]);
-           if (typeid == nil) {
+           if (typeid == 0) {
                cerror("unbelievable forward reference");
            }
            printf("%d", typeid->tnum);
@@ -419,10 +407,10 @@ struct symtab *sym;
 }
 
 /*
- * Generate type information for structures, unions, and enumerations.
+ * Generate type information for structures, unions, && enumerations.
  */
 
-private genstruct(t, structid, index, name, size)
+static genstruct(t, structid, index, name, size)
 TWORD t;
 int structid;
 int index;
@@ -476,15 +464,15 @@ int size;
 }
 
 /*
- * Generate offset and size info.
+ * Generate offset && size info.
  */
 
-private geninfo(p)
+static geninfo(p)
 register struct symtab *p;
 {
     int stabtype;
 
-    if (p == nil) {
+    if (p == 0) {
        printf("\",0x%x,0,0,0\n", N_LSYM);
     } else {
        switch (p->sclass) {
@@ -539,10 +527,10 @@ int szindex, paramindex;
     } else if (gdebug) {
        i = dimtab[szindex + 3];
        p = &stab[i];
-       if (p->sname != nil) {
+       if (p->sname != 0) {
            strindex = dimtab[p->sizoff + 1];
            typeid = typelookup(p->stype, NILINDEX, FORWARD, i);
-           if (typeid == nil) {
+           if (typeid == 0) {
                t = 0;
            } else {
                t = typeid->tnum;
@@ -719,7 +707,7 @@ char *sname;
  * Old way of doing things.
  */
 
-private old_fixarg(p)
+static old_fixarg(p)
 struct symtab *p; {
        if (gdebug) {
                old_pstab(p->sname, N_PSYM);
@@ -728,7 +716,7 @@ struct symtab *p; {
        }
 }
 
-private old_outstab(p)
+static old_outstab(p)
 struct symtab *p; {
        register TWORD ptype;
        register char *pname;
@@ -803,7 +791,7 @@ struct symtab *p; {
        }
 }
 
-private old_pstab(name, type)
+static old_pstab(name, type)
 char *name;
 int type; {
        register int i;
@@ -829,7 +817,7 @@ int type; {
 }
 
 #ifdef STABDOT
-private old_pstabdot(type, value)
+static old_pstabdot(type, value)
        int     type;
        int     value;
 {
@@ -840,7 +828,7 @@ private old_pstabdot(type, value)
 }
 #endif
 
-private old_poffs(p)
+static old_poffs(p)
 register struct symtab *p; {
        int s;
        if (!gdebug) return;
@@ -850,7 +838,7 @@ register struct symtab *p; {
        }
 }
 
-private old_psline() {
+static old_psline() {
        static int lastlineno;
        register char *cp, *cq;
        register int i;
@@ -897,7 +885,7 @@ eq: if (lineno == lastlineno) return;
                }
        }
        
-private old_plcstab(level) {
+static old_plcstab(level) {
        if (!gdebug) return;
 #ifdef STABDOT
        old_pstabdot(N_LBRAC, level);
@@ -908,7 +896,7 @@ private old_plcstab(level) {
 #endif
        }
        
-private old_prcstab(level) {
+static old_prcstab(level) {
        if (!gdebug) return;
 #ifdef STABDOT
        pstabdot(N_RBRAC, level);
@@ -919,7 +907,7 @@ private old_prcstab(level) {
 #endif
        }
        
-private old_pfstab(sname) 
+static old_pfstab(sname) 
 char *sname; {
        if (!gdebug) return;
        pstab(sname, N_FUN);
diff --git a/lib/pcc/trees.c b/lib/pcc/trees.c
new file mode 100644 (file)
index 0000000..122ec3f
--- /dev/null
@@ -0,0 +1,1702 @@
+#ifndef lint
+static char *sccsid ="@(#)trees.c      4.10 (Berkeley) 1/8/86";
+#endif
+
+# include "pass1.h"
+
+# include <setjmp.h>
+
+int bdebug = 0;
+int adebug = 0;
+extern ddebug;
+extern eprint();
+
+           /* corrections when in violation of lint */
+
+/*     some special actions, used in finding the type of nodes */
+# define NCVT 01
+# define PUN 02
+# define TYPL 04
+# define TYPR 010
+# define TYMATCH 040
+# define LVAL 0100
+# define CVTO 0200
+# define CVTL 0400
+# define CVTR 01000
+# define PTMATCH 02000
+# define OTHER 04000
+# define NCVTR 010000
+
+#ifndef BUG1
+printact(t, acts)
+       NODE *t;
+       int acts;
+{
+       static struct actions {
+               int     a_bit;
+               char    *a_name;
+       } actions[] = {
+               { PUN,          "PUN" },
+               { CVTL,         "CVTL" },
+               { CVTR,         "CVTR" },
+               { TYPL,         "TYPL" },
+               { TYPR,         "TYPR" },
+               { TYMATCH,      "TYMATCH" },
+               { PTMATCH,      "PTMATCH" },
+               { LVAL,         "LVAL" },
+               { CVTO,         "CVTO" },
+               { NCVT,         "NCVT" },
+               { OTHER,        "OTHER" },
+               { NCVTR,        "NCVTR" },
+               { 0 }
+       };
+       register struct actions *p;
+       char *sep = " ";
+
+       printf("actions");
+       for (p = actions; p->a_name; p++)
+               if (p->a_bit & acts) {
+                       printf("%s%s", sep, p->a_name);
+                       sep = "|";
+               }
+       if (!bdebug) {
+               printf(" for:\n");
+               fwalk(t, eprint, 0);
+       } else
+               putchar('\n');
+}
+#endif
+
+/* node conventions:
+
+       NAME:   rval>0 is stab index for external
+               rval<0 is -inlabel number
+               lval is offset in bits
+       ICON:   lval has the value
+               rval has the STAB index, or - label number,
+                       if a name whose address is in the constant
+               rval = NONAME means no name
+       REG:    rval is reg. identification cookie
+
+       */
+
+NODE *
+buildtree( o, l, r ) register NODE *l, *r; {
+       register NODE *p, *q;
+       register actions;
+       register opty;
+       register struct symtab *sp;
+       register NODE *lr, *ll;
+       NODE *fixargs();
+       int i;
+
+# ifndef BUG1
+       if( bdebug ) printf( "buildtree( %s, %o, %o )\n", opst[o], l, r );
+# endif
+       opty = optype(o);
+
+       /* check for constants */
+
+       if( opty == UTYPE && l->in.op == ICON ){
+
+               switch( o ){
+
+               case NOT:
+                       if( hflag ) werror( "constant argument to NOT" );
+               case UNARY MINUS:
+               case COMPL:
+                       if( conval( l, o, l ) ) return(l);
+                       break;
+
+                       }
+               }
+
+       else if( o==UNARY MINUS && l->in.op==FCON ){
+               l->fpn.fval = -l->fpn.fval;
+               return(l);
+               }
+
+       else if( o==UNARY MINUS && l->in.op==DCON ){
+               l->dpn.dval = -l->dpn.dval;
+               return(l);
+               }
+
+       else if( o==QUEST && l->in.op==ICON ) {
+               l->in.op = FREE;
+               r->in.op = FREE;
+               if( l->tn.lval ){
+                       tfree( r->in.right );
+                       return( r->in.left );
+                       }
+               else {
+                       tfree( r->in.left );
+                       return( r->in.right );
+                       }
+               }
+
+       else if( (o==ANDAND || o==OROR) && (l->in.op==ICON||r->in.op==ICON) ) goto ccwarn;
+
+       else if( opty == BITYPE && l->in.op == ICON && r->in.op == ICON ){
+
+               switch( o ){
+
+               case ULT:
+               case UGT:
+               case ULE:
+               case UGE:
+               case LT:
+               case GT:
+               case LE:
+               case GE:
+               case EQ:
+               case NE:
+               case ANDAND:
+               case OROR:
+               case CBRANCH:
+
+               ccwarn:
+                       if( hflag ) werror( "constant in conditional context" );
+
+               case PLUS:
+               case MINUS:
+               case MUL:
+               case DIV:
+               case MOD:
+               case AND:
+               case OR:
+               case ER:
+               case LS:
+               case RS:
+                       if( conval( l, o, r ) ) {
+                               r->in.op = FREE;
+                               return(l);
+                               }
+                       break;
+                       }
+               }
+       else if (opty == BITYPE &&
+               (l->in.op == FCON || l->in.op == DCON || l->in.op == ICON) &&
+               (r->in.op == FCON || r->in.op == DCON || r->in.op == ICON)) {
+                       if (o == PLUS || o == MINUS || o == MUL || o == DIV) {
+                               extern int fpe_count;
+                               extern jmp_buf gotfpe;
+
+                               fpe_count = 0;
+                               if (setjmp(gotfpe))
+                                       goto treatfpe;
+                               if (l->in.op == ICON)
+                                       l->dpn.dval = l->tn.lval;
+                               else if (l->in.op == FCON)
+                                       l->dpn.dval = l->fpn.fval;
+                               if (r->in.op == ICON)
+                                       r->dpn.dval = r->tn.lval;
+                               else if (r->in.op == FCON)
+                                       r->dpn.dval = r->fpn.fval;
+                               switch (o) {
+
+                               case PLUS:
+                                       l->dpn.dval += r->dpn.dval;
+                                       break;
+
+                               case MINUS:
+                                       l->dpn.dval -= r->dpn.dval;
+                                       break;
+
+                               case MUL:
+                                       l->dpn.dval *= r->dpn.dval;
+                                       break;
+
+                               case DIV:
+                                       if (r->dpn.dval == 0)
+                                               uerror("division by 0.");
+                                       else
+                                               l->dpn.dval /= r->dpn.dval;
+                                       break;
+                                       }
+                       treatfpe:
+                               if (fpe_count > 0) {
+                                       uerror("floating point exception in constant expression");
+                                       l->dpn.dval = 1.0; /* Fairly harmless */
+                                       }
+                               fpe_count = -1;
+                               l->in.op = DCON;
+                               l->in.type = l->fn.csiz = DOUBLE;
+                               r->in.op = FREE;
+                               return (l);
+                       }
+               }
+
+       /* it's real; we must make a new node */
+
+       p = block( o, l, r, INT, 0, INT );
+
+       actions = opact(p);
+#ifndef        BUG1
+       if (adebug)
+               printact(p, actions);
+#endif
+
+       if( actions&LVAL ){ /* check left descendent */
+               if( notlval(p->in.left) ) {
+                       uerror( "illegal lhs of assignment operator" );
+                       }
+               }
+
+       if( actions & NCVTR ){
+               p->in.left = pconvert( p->in.left );
+               }
+       else if( !(actions & NCVT ) ){
+               switch( opty ){
+
+               case BITYPE:
+                       p->in.right = pconvert( p->in.right );
+               case UTYPE:
+                       p->in.left = pconvert( p->in.left );
+
+                       }
+               }
+
+       if( (actions&PUN) && (o!=CAST||cflag) ){
+               chkpun(p);
+               }
+
+       if( actions & (TYPL|TYPR) ){
+
+               q = (actions&TYPL) ? p->in.left : p->in.right;
+
+               p->in.type = q->in.type;
+               p->fn.cdim = q->fn.cdim;
+               p->fn.csiz = q->fn.csiz;
+               }
+
+       if( actions & CVTL ) p = convert( p, CVTL );
+       if( actions & CVTR ) p = convert( p, CVTR );
+       if( actions & TYMATCH ) p = tymatch(p);
+       if( actions & PTMATCH ) p = ptmatch(p);
+
+       if( actions & OTHER ){
+               l = p->in.left;
+               r = p->in.right;
+
+               switch(o){
+
+               case NAME:
+                       sp = &stab[idname];
+                       if( sp->stype == UNDEF ){
+#ifndef FLEXNAMES
+                               uerror( "%.8s undefined", sp->sname );
+#else
+                               uerror( "%s undefined", sp->sname );
+#endif
+                               /* make p look reasonable */
+                               p->in.type = p->fn.cdim = p->fn.csiz = INT;
+                               p->tn.rval = idname;
+                               p->tn.lval = 0;
+                               defid( p, SNULL );
+                               break;
+                               }
+                       p->in.type = sp->stype;
+                       p->fn.cdim = sp->dimoff;
+                       p->fn.csiz = sp->sizoff;
+                       p->tn.lval = 0;
+                       p->tn.rval = idname;
+                       /* special case: MOETY is really an ICON... */
+                       if( p->in.type == MOETY ){
+                               p->tn.rval = NONAME;
+                               p->tn.lval = sp->offset;
+                               p->fn.cdim = 0;
+                               p->in.type = ENUMTY;
+                               p->in.op = ICON;
+                               }
+                       break;
+
+               case ICON:
+                       p->in.type = INT;
+                       p->fn.cdim = 0;
+                       p->fn.csiz = INT;
+                       break;
+
+               case STRING:
+                       p->in.op = NAME;
+                       p->in.type = CHAR+ARY;
+                       p->tn.lval = 0;
+                       p->tn.rval = NOLAB;
+                       p->fn.cdim = curdim;
+                       p->fn.csiz = CHAR;
+                       break;
+
+               case FCON:
+                       p->tn.lval = 0;
+                       p->tn.rval = 0;
+                       p->in.type = FLOAT;
+                       p->fn.cdim = 0;
+                       p->fn.csiz = FLOAT;
+                       break;
+
+               case DCON:
+                       p->tn.lval = 0;
+                       p->tn.rval = 0;
+                       p->in.type = DOUBLE;
+                       p->fn.cdim = 0;
+                       p->fn.csiz = DOUBLE;
+                       break;
+
+               case STREF:
+                       /* p->x turned into *(p+offset) */
+                       /* rhs must be a name; check correctness */
+
+                       i = r->tn.rval;
+                       if( i<0 || ((sp= &stab[i])->sclass != MOS && sp->sclass != MOU && !(sp->sclass&FIELD)) ){
+                               uerror( "member of structure or union required" );
+                               }else
+                       /* if this name is non-unique, find right one */
+                       if( stab[i].sflags & SNONUNIQ &&
+                               (l->in.type==PTR+STRTY || l->in.type == PTR+UNIONTY) &&
+                               (l->fn.csiz +1) >= 0 ){
+                               /* nonunique name && structure defined */
+                               char * memnam, * tabnam;
+                               register k;
+                               int j;
+                               int memi;
+                               j=dimtab[l->fn.csiz+1];
+                               for( ; (memi=dimtab[j]) >= 0; ++j ){
+                                       tabnam = stab[memi].sname;
+                                       memnam = stab[i].sname;
+# ifndef BUG1
+                                       if( ddebug>1 ){
+#ifndef FLEXNAMES
+                                               printf("member %.8s==%.8s?\n",
+#else
+                                               printf("member %s==%s?\n",
+#endif
+                                                       memnam, tabnam);
+                                               }
+# endif
+                                       if( stab[memi].sflags & SNONUNIQ ){
+#ifndef FLEXNAMES
+                                               for( k=0; k<NCHNAM; ++k ){
+                                                       if(*memnam++!=*tabnam)
+                                                               goto next;
+                                                       if(!*tabnam++) break;
+                                                       }
+#else
+                                               if (memnam != tabnam)
+                                                       goto next;
+#endif
+                                               r->tn.rval = i = memi;
+                                               break;
+                                               }
+                                       next: continue;
+                                       }
+                               if( memi < 0 )
+#ifndef FLEXNAMES
+                                       uerror("illegal member use: %.8s",
+#else
+                                       uerror("illegal member use: %s",
+#endif
+                                               stab[i].sname);
+                               }
+                       else {
+                               register j;
+                               if( l->in.type != PTR+STRTY && l->in.type != PTR+UNIONTY ){
+                                       if( stab[i].sflags & SNONUNIQ ){
+                                               uerror( "nonunique name demands struct/union or struct/union pointer" );
+                                               }
+                                       else werror( "struct/union or struct/union pointer required" );
+                                       }
+                               else if( (j=l->fn.csiz+1)<0 ) cerror( "undefined structure or union" );
+                               else if( !chkstr( i, dimtab[j], DECREF(l->in.type) ) ){
+#ifndef FLEXNAMES
+                                       werror( "illegal member use: %.8s", stab[i].sname );
+#else
+                                       werror( "illegal member use: %s", stab[i].sname );
+#endif
+                                       }
+                               }
+
+                       p = stref( p );
+                       break;
+
+               case UNARY MUL:
+                       if( l->in.op == UNARY AND ){
+                               p->in.op = l->in.op = FREE;
+                               p = l->in.left;
+                               }
+                       if( !ISPTR(l->in.type))uerror("illegal indirection");
+                       p->in.type = DECREF(l->in.type);
+                       p->fn.cdim = l->fn.cdim;
+                       p->fn.csiz = l->fn.csiz;
+                       break;
+
+               case UNARY AND:
+                       switch( l->in.op ){
+
+                       case UNARY MUL:
+                               p->in.op = l->in.op = FREE;
+                               p = l->in.left;
+                       case NAME:
+                               p->in.type = INCREF( l->in.type );
+                               p->fn.cdim = l->fn.cdim;
+                               p->fn.csiz = l->fn.csiz;
+                               break;
+
+                       case COMOP:
+                               lr = buildtree( UNARY AND, l->in.right, NIL );
+                               p->in.op = l->in.op = FREE;
+                               p = buildtree( COMOP, l->in.left, lr );
+                               break;
+
+                       case QUEST:
+                               lr = buildtree( UNARY AND, l->in.right->in.right, NIL );
+                               ll = buildtree( UNARY AND, l->in.right->in.left, NIL );
+                               p->in.op = l->in.op = l->in.right->in.op = FREE;
+                               p = buildtree( QUEST, l->in.left, buildtree( COLON, ll, lr ) );
+                               break;
+
+# ifdef ADDROREG
+                       case OREG:
+                               /* OREG was built in clocal()
+                                * for an auto or formal parameter
+                                * now its address is being taken
+                                * local code must unwind it
+                                * back to PLUS/MINUS REG ICON
+                                * according to local conventions
+                                */
+                               {
+                               extern NODE * addroreg();
+                               p->in.op = FREE;
+                               p = addroreg( l );
+                               }
+                               break;
+
+# endif
+                       default:
+                               uerror( "unacceptable operand of &" );
+                               break;
+                               }
+                       break;
+
+               case LS:
+               case RS:
+               case ASG LS:
+               case ASG RS:
+                       if(tsize(p->in.right->in.type, p->in.right->fn.cdim, p->in.right->fn.csiz) > SZINT)
+                               p->in.right = makety(p->in.right, INT, 0, INT );
+                       break;
+
+               case RETURN:
+               case ASSIGN:
+               case CAST:
+                       /* structure assignment */
+                       /* take the addresses of the two sides; then make an
+                       /* operator using STASG and
+                       /* the addresses of left and right */
+
+                       {
+                               register TWORD t;
+                               register d, s;
+
+                               if( l->fn.csiz != r->fn.csiz ) uerror( "assignment of different structures" );
+
+                               r = buildtree( UNARY AND, r, NIL );
+                               t = r->in.type;
+                               d = r->fn.cdim;
+                               s = r->fn.csiz;
+
+                               l = block( STASG, l, r, t, d, s );
+
+                               if( o == RETURN ){
+                                       p->in.op = FREE;
+                                       p = l;
+                                       break;
+                                       }
+
+                               p->in.op = UNARY MUL;
+                               p->in.left = l;
+                               p->in.right = NIL;
+                               break;
+                               }
+               case COLON:
+                       /* structure colon */
+
+                       if( l->fn.csiz != r->fn.csiz ) uerror( "type clash in conditional" );
+                       break;
+
+               case CALL:
+                       p->in.right = r = fixargs( p->in.right );
+               case UNARY CALL:
+                       if( !ISPTR(l->in.type)) uerror("illegal function");
+                       p->in.type = DECREF(l->in.type);
+                       if( !ISFTN(p->in.type)) uerror("illegal function");
+                       p->in.type = DECREF( p->in.type );
+                       p->fn.cdim = l->fn.cdim;
+                       p->fn.csiz = l->fn.csiz;
+                       if( l->in.op == UNARY AND && l->in.left->in.op == NAME &&
+                               l->in.left->tn.rval >= 0 && l->in.left->tn.rval != NONAME &&
+                               ( (i=stab[l->in.left->tn.rval].sclass) == FORTRAN || i==UFORTRAN ) ){
+                               p->in.op += (FORTCALL-CALL);
+                               }
+                       if( p->in.type == STRTY || p->in.type == UNIONTY ){
+                               /* function returning structure */
+                               /*  make function really return ptr to str., with * */
+
+                               p->in.op += STCALL-CALL;
+                               p->in.type = INCREF( p->in.type );
+                               p = buildtree( UNARY MUL, p, NIL );
+
+                               }
+                       break;
+
+               default:
+                       cerror( "other code %d", o );
+                       }
+
+               }
+
+       if( actions & CVTO ) p = oconvert(p);
+       p = clocal(p);
+
+# ifndef BUG1
+       if( bdebug ) fwalk( p, eprint, 0 );
+# endif
+
+       return(p);
+
+       }
+
+int fpe_count = -1;
+jmp_buf gotfpe;
+
+fpe() {
+       if (fpe_count < 0)
+               cerror("floating point exception");
+       ++fpe_count;
+       longjmp(gotfpe, 1);
+       }
+
+/*
+ * Rewrite arguments in a function call.
+ * Structure arguments are massaged, single
+ * precision floating point constants are
+ * cast to double (to eliminate convert code).
+ */
+NODE *
+fixargs( p ) register NODE *p;  {
+       int o = p->in.op;
+
+       if( o == CM ){
+               p->in.left = fixargs( p->in.left );
+               p->in.right = fixargs( p->in.right );
+               return( p );
+               }
+
+       if( p->in.type == STRTY || p->in.type == UNIONTY ){
+               p = block( STARG, p, NIL, p->in.type, p->fn.cdim, p->fn.csiz );
+               p->in.left = buildtree( UNARY AND, p->in.left, NIL );
+               p = clocal(p);
+               }
+       else if( o == FCON )
+               p = makety(p, DOUBLE, 0, 0);
+       return( p );
+       }
+
+chkstr( i, j, type ) TWORD type; {
+       /* is the MOS or MOU at stab[i] OK for strict reference by a ptr */
+       /* i has been checked to contain a MOS or MOU */
+       /* j is the index in dimtab of the members... */
+       int k, kk;
+
+       extern int ddebug;
+
+# ifndef BUG1
+#ifndef FLEXNAMES
+       if( ddebug > 1 ) printf( "chkstr( %.8s(%d), %d )\n", stab[i].sname, i, j );
+#else
+       if( ddebug > 1 ) printf( "chkstr( %s(%d), %d )\n", stab[i].sname, i, j );
+#endif
+# endif
+       if( (k = j) < 0 ) uerror( "undefined structure or union" );
+       else {
+               for( ; (kk = dimtab[k] ) >= 0; ++k ){
+                       if( kk >= SYMTSZ ){
+                               cerror( "gummy structure" );
+                               return(1);
+                               }
+                       if( kk == i ) return( 1 );
+                       switch( stab[kk].stype ){
+
+                       case STRTY:
+                       case UNIONTY:
+                               if( type == STRTY ) continue;  /* no recursive looking for strs */
+                               if( hflag && chkstr( i, dimtab[stab[kk].sizoff+1], stab[kk].stype ) ){
+                                       if( stab[kk].sname[0] == '$' ) return(0);  /* $FAKE */
+                                       werror(
+#ifndef FLEXNAMES
+                                       "illegal member use: perhaps %.8s.%.8s?",
+#else
+                                       "illegal member use: perhaps %s.%s?",
+#endif
+                                       stab[kk].sname, stab[i].sname );
+                                       return(1);
+                                       }
+                               }
+                       }
+               }
+       return( 0 );
+       }
+
+conval( p, o, q ) register NODE *p, *q; {
+       /* apply the op o to the lval part of p; if binary, rhs is val */
+       int i, u;
+       CONSZ val;
+
+       val = q->tn.lval;
+       u = ISUNSIGNED(p->in.type) || ISUNSIGNED(q->in.type);
+       if( u && (o==LE||o==LT||o==GE||o==GT)) o += (UGE-GE);
+
+       if( p->tn.rval != NONAME && q->tn.rval != NONAME ) return(0);
+       if( q->tn.rval != NONAME && o!=PLUS ) return(0);
+       if( p->tn.rval != NONAME && o!=PLUS && o!=MINUS ) return(0);
+
+       switch( o ){
+
+       case PLUS:
+               p->tn.lval += val;
+               if( p->tn.rval == NONAME ){
+                       p->tn.rval = q->tn.rval;
+                       p->in.type = q->in.type;
+                       }
+               break;
+       case MINUS:
+               p->tn.lval -= val;
+               break;
+       case MUL:
+               p->tn.lval *= val;
+               break;
+       case DIV:
+               if( val == 0 ) uerror( "division by 0" );
+               else if ( u ) p->tn.lval = (unsigned) p->tn.lval / val;
+               else p->tn.lval /= val;
+               break;
+       case MOD:
+               if( val == 0 ) uerror( "division by 0" );
+               else if ( u ) p->tn.lval = (unsigned) p->tn.lval % val;
+               else p->tn.lval %= val;
+               break;
+       case AND:
+               p->tn.lval &= val;
+               break;
+       case OR:
+               p->tn.lval |= val;
+               break;
+       case ER:
+               p->tn.lval ^= val;
+               break;
+       case LS:
+               i = val;
+               p->tn.lval = p->tn.lval << i;
+               break;
+       case RS:
+               i = val;
+               if ( u ) p->tn.lval = (unsigned) p->tn.lval >> i;
+               else p->tn.lval = p->tn.lval >> i;
+               break;
+
+       case UNARY MINUS:
+               p->tn.lval = - p->tn.lval;
+               break;
+       case COMPL:
+               p->tn.lval = ~p->tn.lval;
+               break;
+       case NOT:
+               p->tn.lval = !p->tn.lval;
+               break;
+       case LT:
+               p->tn.lval = p->tn.lval < val;
+               break;
+       case LE:
+               p->tn.lval = p->tn.lval <= val;
+               break;
+       case GT:
+               p->tn.lval = p->tn.lval > val;
+               break;
+       case GE:
+               p->tn.lval = p->tn.lval >= val;
+               break;
+       case ULT:
+               p->tn.lval = (p->tn.lval-val)<0;
+               break;
+       case ULE:
+               p->tn.lval = (p->tn.lval-val)<=0;
+               break;
+       case UGE:
+               p->tn.lval = (p->tn.lval-val)>=0;
+               break;
+       case UGT:
+               p->tn.lval = (p->tn.lval-val)>0;
+               break;
+       case EQ:
+               p->tn.lval = p->tn.lval == val;
+               break;
+       case NE:
+               p->tn.lval = p->tn.lval != val;
+               break;
+       default:
+               return(0);
+               }
+       return(1);
+       }
+
+chkpun(p) register NODE *p; {
+
+       /* checks p for the existance of a pun */
+
+       /* this is called when the op of p is ASSIGN, RETURN, CAST, COLON, or relational */
+
+       /* one case is when enumerations are used: this applies only to lint */
+       /* in the other case, one operand is a pointer, the other integer type */
+       /* we check that this integer is in fact a constant zero... */
+
+       /* in the case of ASSIGN, any assignment of pointer to integer is illegal */
+       /* this falls out, because the LHS is never 0 */
+
+       register NODE *q;
+       register t1, t2;
+       register d1, d2;
+
+       t1 = p->in.left->in.type;
+       t2 = p->in.right->in.type;
+
+       if( t1==ENUMTY || t2==ENUMTY ) { /* check for enumerations */
+               if( logop( p->in.op ) && p->in.op != EQ && p->in.op != NE ) {
+                       uerror( "illegal comparison of enums" );
+                       return;
+                       }
+               if( t1==ENUMTY && t2==ENUMTY && p->in.left->fn.csiz==p->in.right->fn.csiz ) return;
+               werror( "enumeration type clash, operator %s", opst[p->in.op] );
+               return;
+               }
+
+       if( ISPTR(t1) || ISARY(t1) ) q = p->in.right;
+       else q = p->in.left;
+
+       if( !ISPTR(q->in.type) && !ISARY(q->in.type) ){
+               if( q->in.op != ICON || q->tn.lval != 0 ){
+                       werror( "illegal combination of pointer and integer, op %s",
+                               opst[p->in.op] );
+                       }
+               }
+       else {
+               d1 = p->in.left->fn.cdim;
+               d2 = p->in.right->fn.cdim;
+               for( ;; ){
+                       if( t1 == t2 ) {;
+                               if( p->in.left->fn.csiz != p->in.right->fn.csiz ) {
+                                       werror( "illegal structure pointer combination" );
+                                       }
+                               return;
+                               }
+                       if( ISARY(t1) || ISPTR(t1) ){
+                               if( !ISARY(t2) && !ISPTR(t2) ) break;
+                               if( ISARY(t1) && ISARY(t2) && dimtab[d1] != dimtab[d2] ){
+                                       werror( "illegal array size combination" );
+                                       return;
+                                       }
+                               if( ISARY(t1) ) ++d1;
+                               if( ISARY(t2) ) ++d2;
+                               }
+                       else break;
+                       t1 = DECREF(t1);
+                       t2 = DECREF(t2);
+                       }
+               werror( "illegal pointer combination" );
+               }
+
+       }
+
+NODE *
+stref( p ) register NODE *p; {
+
+       TWORD t;
+       int d, s, dsc, align;
+       OFFSZ off;
+       register struct symtab *q;
+
+       /* make p->x */
+       /* this is also used to reference automatic variables */
+
+       q = &stab[p->in.right->tn.rval];
+       p->in.right->in.op = FREE;
+       p->in.op = FREE;
+       p = pconvert( p->in.left );
+
+       /* make p look like ptr to x */
+
+       if( !ISPTR(p->in.type)){
+               p->in.type = PTR+UNIONTY;
+               }
+
+       t = INCREF( q->stype );
+       d = q->dimoff;
+       s = q->sizoff;
+
+       p = makety( p, t, d, s );
+
+       /* compute the offset to be added */
+
+       off = q->offset;
+       dsc = q->sclass;
+
+       if( dsc & FIELD ) {  /* normalize offset */
+               align = ALINT;
+               s = INT;
+               off = (off/align)*align;
+               }
+       if( off != 0 ) p = clocal( block( PLUS, p, offcon( off, t, d, s ), t, d, s ) );
+
+       p = buildtree( UNARY MUL, p, NIL );
+
+       /* if field, build field info */
+
+       if( dsc & FIELD ){
+               p = block( FLD, p, NIL, q->stype, 0, q->sizoff );
+               p->tn.rval = PKFIELD( dsc&FLDSIZ, q->offset%align );
+               }
+
+       return( clocal(p) );
+       }
+
+notlval(p) register NODE *p; {
+
+       /* return 0 if p an lvalue, 1 otherwise */
+
+       again:
+
+       switch( p->in.op ){
+
+       case FLD:
+               p = p->in.left;
+               goto again;
+
+       case UNARY MUL:
+               /* fix the &(a=b) bug, given that a and b are structures */
+               if( p->in.left->in.op == STASG ) return( 1 );
+               /* and the f().a bug, given that f returns a structure */
+               if( p->in.left->in.op == UNARY STCALL ||
+                   p->in.left->in.op == STCALL ) return( 1 );
+       case NAME:
+       case OREG:
+               if( ISARY(p->in.type) || ISFTN(p->in.type) ) return(1);
+       case REG:
+               return(0);
+
+       default:
+               return(1);
+
+               }
+
+       }
+
+NODE *
+bcon( i ){ /* make a constant node with value i */
+       register NODE *p;
+
+       p = block( ICON, NIL, NIL, INT, 0, INT );
+       p->tn.lval = i;
+       p->tn.rval = NONAME;
+       return( clocal(p) );
+       }
+
+NODE *
+bpsize(p) register NODE *p; {
+       return( offcon( psize(p), p->in.type, p->fn.cdim, p->fn.csiz ) );
+       }
+
+OFFSZ
+psize( p ) NODE *p; {
+       /* p is a node of type pointer; psize returns the
+          size of the thing pointed to */
+
+       if( !ISPTR(p->in.type) ){
+               uerror( "pointer required");
+               return( SZINT );
+               }
+       /* note: no pointers to fields */
+       return( tsize( DECREF(p->in.type), p->fn.cdim, p->fn.csiz ) );
+       }
+
+NODE *
+convert( p, f )  register NODE *p; {
+       /*  convert an operand of p
+           f is either CVTL or CVTR
+           operand has type int, and is converted by the size of the other side
+           */
+
+       register NODE *q, *r;
+
+       q = (f==CVTL)?p->in.left:p->in.right;
+
+       r = block( PMCONV,
+               q, bpsize(f==CVTL?p->in.right:p->in.left), INT, 0, INT );
+       r = clocal(r);
+       if( f == CVTL )
+               p->in.left = r;
+       else
+               p->in.right = r;
+       return(p);
+
+       }
+
+#ifndef econvert
+econvert( p ) register NODE *p; {
+
+       /* change enums to ints, or appropriate types */
+
+       register TWORD ty;
+
+       if( (ty=BTYPE(p->in.type)) == ENUMTY || ty == MOETY ) {
+               if( dimtab[ p->fn.csiz ] == SZCHAR ) ty = CHAR;
+               else if( dimtab[ p->fn.csiz ] == SZINT ) ty = INT;
+               else if( dimtab[ p->fn.csiz ] == SZSHORT ) ty = SHORT;
+               else ty = LONG;
+               ty = ctype( ty );
+               p->fn.csiz = ty;
+               MODTYPE(p->in.type,ty);
+               if( p->in.op == ICON && ty != LONG ) p->in.type = p->fn.csiz = INT;
+               }
+       }
+#endif
+
+NODE *
+pconvert( p ) register NODE *p; {
+
+       /* if p should be changed into a pointer, do so */
+
+       if( ISARY( p->in.type) ){
+               p->in.type = DECREF( p->in.type );
+               ++p->fn.cdim;
+               return( buildtree( UNARY AND, p, NIL ) );
+               }
+       if( ISFTN( p->in.type) )
+               return( buildtree( UNARY AND, p, NIL ) );
+
+       return( p );
+       }
+
+NODE *
+oconvert(p) register NODE *p; {
+       /* convert the result itself: used for pointer and unsigned */
+
+       switch(p->in.op) {
+
+       case LE:
+       case LT:
+       case GE:
+       case GT:
+               if( ISUNSIGNED(p->in.left->in.type) || ISUNSIGNED(p->in.right->in.type) )  p->in.op += (ULE-LE);
+       case EQ:
+       case NE:
+               return( p );
+
+       case MINUS:
+               return(  clocal( block( PVCONV,
+                       p, bpsize(p->in.left), INT, 0, INT ) ) );
+               }
+
+       cerror( "illegal oconvert: %d", p->in.op );
+
+       return(p);
+       }
+
+NODE *
+ptmatch(p)  register NODE *p; {
+
+       /* makes the operands of p agree; they are
+          either pointers or integers, by this time */
+       /* with MINUS, the sizes must be the same */
+       /* with COLON, the types must be the same */
+
+       TWORD t1, t2, t;
+       int o, d2, d, s2, s;
+
+       o = p->in.op;
+       t = t1 = p->in.left->in.type;
+       t2 = p->in.right->in.type;
+       d = p->in.left->fn.cdim;
+       d2 = p->in.right->fn.cdim;
+       s = p->in.left->fn.csiz;
+       s2 = p->in.right->fn.csiz;
+
+       switch( o ){
+
+       case ASSIGN:
+       case RETURN:
+       case CAST:
+               {  break; }
+
+       case MINUS:
+               {  if( psize(p->in.left) != psize(p->in.right) ){
+                       uerror( "illegal pointer subtraction");
+                       }
+                  break;
+                  }
+       case COLON:
+               {  if( t1 != t2 ) uerror( "illegal types in :");
+                  break;
+                  }
+       default:  /* must work harder: relationals or comparisons */
+
+               if( !ISPTR(t1) ){
+                       t = t2;
+                       d = d2;
+                       s = s2;
+                       break;
+                       }
+               if( !ISPTR(t2) ){
+                       break;
+                       }
+
+               /* both are pointers */
+               if( talign(t2,s2) < talign(t,s) ){
+                       t = t2;
+                       s = s2;
+                       }
+               break;
+               }
+
+       p->in.left = makety( p->in.left, t, d, s );
+       p->in.right = makety( p->in.right, t, d, s );
+       if( o!=MINUS && !logop(o) ){
+
+               p->in.type = t;
+               p->fn.cdim = d;
+               p->fn.csiz = s;
+               }
+
+       return(clocal(p));
+       }
+
+int tdebug = 0;
+
+NODE *
+tymatch(p)  register NODE *p; {
+
+       /* satisfy the types of various arithmetic binary ops */
+
+       /* rules are:
+               if assignment, type of LHS
+               if any float or doubles, make double
+               if any longs, make long
+               otherwise, make int
+               if either operand is unsigned, the result is...
+       */
+
+       register TWORD t1, t2, t, tu;
+       register o, u;
+
+       o = p->in.op;
+
+       t1 = p->in.left->in.type;
+       t2 = p->in.right->in.type;
+       if( (t1==UNDEF || t2==UNDEF) && o!=CAST )
+               uerror("void type illegal in expression");
+
+       u = 0;
+       if( ISUNSIGNED(t1) ){
+               u = 1;
+               t1 = DEUNSIGN(t1);
+               }
+       if( ISUNSIGNED(t2) ){
+               u = 1;
+               t2 = DEUNSIGN(t2);
+               }
+
+       if( ( t1 == CHAR || t1 == SHORT ) && o!= RETURN ) t1 = INT;
+       if( t2 == CHAR || t2 == SHORT ) t2 = INT;
+
+#ifdef SPRECC
+       if( t1 == DOUBLE || t2 == DOUBLE )
+               t = DOUBLE;
+       else if( t1 == FLOAT || t2 == FLOAT )
+               t = FLOAT;
+#else
+       if (t1 == DOUBLE || t1 == FLOAT || t2 == DOUBLE || t2 == FLOAT)
+               t = DOUBLE;
+#endif
+       else if( t1==LONG || t2==LONG ) t = LONG;
+       else t = INT;
+
+       if( o == ASSIGN || o == CAST || o == RETURN ){
+               tu = p->in.left->in.type;
+               t = t1;
+               }
+       else {
+               tu = (u && UNSIGNABLE(t))?ENUNSIGN(t):t;
+               }
+
+       /* because expressions have values that are at least as wide
+          as INT or UNSIGNED, the only conversions needed
+          are those involving FLOAT/DOUBLE, and those
+          from LONG to INT and ULONG to UNSIGNED */
+
+       if( t != t1 && ! asgop(o) )
+               p->in.left = makety( p->in.left, tu, 0, (int)tu );
+
+       if( t != t2 || o==CAST )
+               p->in.right = makety( p->in.right, tu, 0, (int)tu );
+
+       if( asgop(o) ){
+               p->in.type = p->in.left->in.type;
+               p->fn.cdim = p->in.left->fn.cdim;
+               p->fn.csiz = p->in.left->fn.csiz;
+               }
+       else if( !logop(o) ){
+               p->in.type = tu;
+               p->fn.cdim = 0;
+               p->fn.csiz = t;
+               }
+
+# ifndef BUG1
+       if( tdebug ) printf( "tymatch(%o): %o %s %o => %o\n",p,t1,opst[o],t2,tu );
+# endif
+
+       return(p);
+       }
+
+NODE *
+makety( p, t, d, s ) register NODE *p; TWORD t; {
+       /* make p into type t by inserting a conversion */
+
+       if( p->in.type == ENUMTY && p->in.op == ICON ) econvert(p);
+       if( t == p->in.type ){
+               p->fn.cdim = d;
+               p->fn.csiz = s;
+               return( p );
+               }
+
+       if( t & TMASK ){
+               /* non-simple type */
+               return( block( PCONV, p, NIL, t, d, s ) );
+               }
+
+       if( p->in.op == ICON ){
+               if (t == DOUBLE) {
+                       p->in.op = DCON;
+                       if (ISUNSIGNED(p->in.type))
+                               p->dpn.dval = /* (unsigned CONSZ) */ p->tn.lval;
+                       else
+                               p->dpn.dval = p->tn.lval;
+                       p->in.type = p->fn.csiz = t;
+                       return (clocal(p));
+               }
+               if (t == FLOAT) {
+                       p->in.op = FCON;
+                       if( ISUNSIGNED(p->in.type) ){
+                               p->fpn.fval = /* (unsigned CONSZ) */ p->tn.lval;
+                               }
+                       else {
+                               p->fpn.fval = p->tn.lval;
+                               }
+
+                       p->in.type = p->fn.csiz = t;
+                       return( clocal(p) );
+                       }
+               }
+       else if (p->in.op == FCON && t == DOUBLE) {
+               double db;
+
+               p->in.op = DCON;
+               db = p->fpn.fval;
+               p->dpn.dval = db;
+               p->in.type = p->fn.csiz = t;
+               return (clocal(p));
+       } else if (p->in.op == DCON && t == FLOAT) {
+               float fl;
+
+               p->in.op = FCON;
+               fl = p->dpn.dval;
+#ifdef notdef
+               if (fl != p->dpn.dval)
+                       werror("float conversion loses precision");
+#endif
+               p->fpn.fval = fl;
+               p->in.type = p->fn.csiz = t;
+               return (clocal(p));
+       }
+
+       return( clocal( block( SCONV, p, NIL, t, d, s ) ) );
+
+       }
+
+NODE *
+block( o, l, r, t, d, s ) register NODE *l, *r; TWORD t; {
+
+       register NODE *p;
+
+       p = talloc();
+       p->in.op = o;
+       p->in.left = l;
+       p->in.right = r;
+       p->in.type = t;
+       p->fn.cdim = d;
+       p->fn.csiz = s;
+       return(p);
+       }
+
+icons(p) register NODE *p; {
+       /* if p is an integer constant, return its value */
+       int val;
+
+       if( p->in.op != ICON ){
+               uerror( "constant expected");
+               val = 1;
+               }
+       else {
+               val = p->tn.lval;
+               if( val != p->tn.lval ) uerror( "constant too big for cross-compiler" );
+               }
+       tfree( p );
+       return(val);
+       }
+
+/*     the intent of this table is to examine the
+       operators, and to check them for
+       correctness.
+
+       The table is searched for the op and the
+       modified type (where this is one of the
+       types INT (includes char and short), LONG,
+       DOUBLE (includes FLOAT), and POINTER
+
+       The default action is to make the node type integer
+
+       The actions taken include:
+               PUN       check for puns
+               CVTL      convert the left operand
+               CVTR      convert the right operand
+               TYPL      the type is determined by the left operand
+               TYPR      the type is determined by the right operand
+               TYMATCH   force type of left and right to match, by inserting conversions
+               PTMATCH   like TYMATCH, but for pointers
+               LVAL      left operand must be lval
+               CVTO      convert the op
+               NCVT      do not convert the operands
+               OTHER     handled by code
+               NCVTR     convert the left operand, not the right...
+
+       */
+
+# define MINT 01  /* integer */
+# define MDBI 02   /* integer or double */
+# define MSTR 04  /* structure */
+# define MPTR 010  /* pointer */
+# define MPTI 020  /* pointer or integer */
+# define MENU 040 /* enumeration variable or member */
+# define MVOID 0100000 /* void type */
+
+opact( p )  NODE *p; {
+
+       register mt12, mt1, mt2, o;
+
+       mt1 = mt2 = mt12 = 0;
+
+       switch( optype(o=p->in.op) ){
+
+       case BITYPE:
+               mt2 = moditype( p->in.right->in.type );
+       case UTYPE:
+               mt1 = moditype( p->in.left->in.type );
+               break;
+
+               }
+
+       if( ((mt1 | mt2) & MVOID) &&
+           o != COMOP &&
+           !(o == CAST && (mt1 & MVOID)) ){
+               /* if lhs of RETURN is void, grammar will complain */
+               if( o != RETURN )
+                       uerror( "value of void expression used" );
+               return( NCVT );
+               }
+       mt1 &= ~MVOID;
+       mt2 &= ~MVOID;
+       mt12 = mt1 & mt2;
+
+       switch( o ){
+
+       case NAME :
+       case STRING :
+       case ICON :
+       case FCON :
+       case DCON :
+       case CALL :
+       case UNARY CALL:
+       case UNARY MUL:
+               {  return( OTHER ); }
+       case UNARY MINUS:
+               if( mt1 & MDBI ) return( TYPL );
+               break;
+
+       case COMPL:
+               if( mt1 & MINT ) return( TYPL );
+               break;
+
+       case UNARY AND:
+               {  return( NCVT+OTHER ); }
+       case INIT:
+       case CM:
+               return( 0 );
+
+       case NOT:
+       case CBRANCH:
+               if( mt1 & MSTR ) break;
+               return( 0 );
+
+       case ANDAND:
+       case OROR:
+               if( (mt1 & MSTR) || (mt2 & MSTR) ) break;
+               return( 0 );
+
+       case MUL:
+       case DIV:
+               if( mt12 & MDBI ) return( TYMATCH );
+               break;
+
+       case MOD:
+       case AND:
+       case OR:
+       case ER:
+               if( mt12 & MINT ) return( TYMATCH );
+               break;
+
+       case LS:
+       case RS:
+               if( mt12 & MINT ) return( TYMATCH+OTHER );
+               break;
+
+       case EQ:
+       case NE:
+       case LT:
+       case LE:
+       case GT:
+       case GE:
+               if( (mt1&MENU)||(mt2&MENU) ) return( PTMATCH+PUN+NCVT );
+               if( mt12 & MDBI ) return( TYMATCH+CVTO );
+               else if( mt12 & MPTR ) return( PTMATCH+PUN );
+               else if( mt12 & MPTI ) return( PTMATCH+PUN );
+               else break;
+
+       case QUEST:
+       case COMOP:
+               if( mt2&MENU ) return( TYPR+NCVTR );
+               return( TYPR );
+
+       case STREF:
+               return( NCVTR+OTHER );
+
+       case FORCE:
+               return( TYPL );
+
+       case COLON:
+               if( mt12 & MENU ) return( NCVT+PUN+PTMATCH );
+               else if( mt12 & MDBI ) return( TYMATCH );
+               else if( mt12 & MPTR ) return( TYPL+PTMATCH+PUN );
+               else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+PUN );
+               else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+PUN );
+               else if( mt12 & MSTR ) return( NCVT+TYPL+OTHER );
+               break;
+
+       case ASSIGN:
+       case RETURN:
+               if( mt12 & MSTR ) return( LVAL+NCVT+TYPL+OTHER );
+       case CAST:
+               if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+               if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+               else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+               else if( mt2 == 0 &&
+                       ( p->in.right->in.op == CALL ||
+                         p->in.right->in.op == UNARY CALL)) break;
+               else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+               else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+               break;
+
+       case ASG LS:
+       case ASG RS:
+               if( mt12 & MINT ) return( TYPL+LVAL+OTHER );
+               break;
+
+       case ASG MUL:
+       case ASG DIV:
+               if( mt12 & MDBI ) return( LVAL+TYMATCH );
+               break;
+
+       case ASG MOD:
+       case ASG AND:
+       case ASG OR:
+       case ASG ER:
+               if( mt12 & MINT ) return( LVAL+TYMATCH );
+               break;
+
+       case ASG PLUS:
+       case ASG MINUS:
+       case INCR:
+       case DECR:
+               if( mt12 & MDBI ) return( TYMATCH+LVAL );
+               else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+LVAL+CVTR );
+               break;
+
+       case MINUS:
+               if( mt12 & MPTR ) return( CVTO+PTMATCH+PUN );
+               if( mt2 & MPTR ) break;
+       case PLUS:
+               if( mt12 & MDBI ) return( TYMATCH );
+               else if( (mt1&MPTR) && (mt2&MINT) ) return( TYPL+CVTR );
+               else if( (mt1&MINT) && (mt2&MPTR) ) return( TYPR+CVTL );
+
+               }
+       if( mt12 == MSTR )
+               uerror( "%s is not a permitted struct/union operation", opst[o] );
+       else
+               uerror( "operands of %s have incompatible types", opst[o] );
+       return( NCVT );
+       }
+
+moditype( ty ) TWORD ty; {
+
+       switch( ty ){
+
+       case TVOID:
+               return( MPTR );
+       case UNDEF:
+               return( MVOID );
+       case ENUMTY:
+       case MOETY:
+               return( MENU );
+
+       case STRTY:
+       case UNIONTY:
+               return( MSTR );
+
+       case CHAR:
+       case SHORT:
+       case UCHAR:
+       case USHORT:
+               return( MINT|MPTI|MDBI );
+       case UNSIGNED:
+       case ULONG:
+       case INT:
+       case LONG:
+               return( MINT|MDBI|MPTI );
+       case FLOAT:
+       case DOUBLE:
+               return( MDBI );
+       default:
+               return( MPTR|MPTI );
+
+               }
+       }
+
+NODE *
+doszof( p )  register NODE *p; {
+       /* do sizeof p */
+       int i;
+
+       /* whatever is the meaning of this if it is a bitfield? */
+       i = tsize( p->in.type, p->fn.cdim, p->fn.csiz )/SZCHAR;
+
+       tfree(p);
+       if( i <= 0 ) werror( "sizeof returns 0" );
+       return( bcon( i ) );
+       }
+
+# ifndef BUG2
+eprint( p, down, a, b ) register NODE *p; int *a, *b; {
+       register ty;
+
+       *a = *b = down+1;
+       while( down > 1 ){
+               printf( "\t" );
+               down -= 2;
+               }
+       if( down ) printf( "    " );
+
+       ty = optype( p->in.op );
+
+       printf("%o) %s, ", p, opst[p->in.op] );
+       if( ty == LTYPE ){
+               printf( CONFMT, p->tn.lval );
+               printf( ", %d, ", p->tn.rval );
+               }
+       tprint( p->in.type );
+       printf( ", %d, %d\n", p->fn.cdim, p->fn.csiz );
+       }
+# endif
+
+prtdcon( p ) register NODE *p; {
+       int o = p->in.op, i;
+
+       if( o == DCON || o == FCON ){
+               locctr( DATA );
+               defalign( o == DCON ? ALDOUBLE : ALFLOAT );
+               deflab( i = getlab() );
+               if( o == FCON )
+                       fincode( p->fpn.fval, SZFLOAT );
+               else
+                       fincode( p->dpn.dval, SZDOUBLE );
+               p->tn.lval = 0;
+               p->tn.rval = -i;
+               p->in.type = (o == DCON ? DOUBLE : FLOAT);
+               p->in.op = NAME;
+               }
+       }
+
+
+int edebug = 0;
+ecomp( p ) register NODE *p; {
+# ifndef BUG2
+       if( edebug ) fwalk( p, eprint, 0 );
+# endif
+       if( !reached ){
+               werror( "statement not reached" );
+               reached = 1;
+               }
+       p = optim(p);
+       walkf( p, prtdcon );
+       locctr( PROG );
+       ecode( p );
+       tfree(p);
+       }
+
+# ifdef STDPRTREE
+# ifndef ONEPASS
+
+prtree(p) register NODE *p; {
+
+       register struct symtab *q;
+       register ty;
+
+# ifdef MYPRTREE
+       MYPRTREE(p);  /* local action can be taken here; then return... */
+#endif
+
+       ty = optype(p->in.op);
+
+       printf( "%d\t", p->in.op );
+
+       if( ty == LTYPE ) {
+               printf( CONFMT, p->tn.lval );
+               printf( "\t" );
+               }
+       if( ty != BITYPE ) {
+               if( p->in.op == NAME || p->in.op == ICON ) printf( "0\t" );
+               else printf( "%d\t", p->tn.rval );
+               }
+
+       printf( "%o\t", p->in.type );
+
+       /* handle special cases */
+
+       switch( p->in.op ){
+
+       case NAME:
+       case ICON:
+               /* print external name */
+               if( p->tn.rval == NONAME ) printf( "\n" );
+               else if( p->tn.rval >= 0 ){
+                       q = &stab[p->tn.rval];
+                       printf(  "%s\n", exname(q->sname) );
+                       }
+               else { /* label */
+                       printf( LABFMT, -p->tn.rval );
+                       }
+               break;
+
+       case STARG:
+       case STASG:
+       case STCALL:
+       case UNARY STCALL:
+               /* print out size */
+               /* use lhs size, in order to avoid hassles with the structure `.' operator */
+
+               /* note: p->in.left not a field... */
+               printf( CONFMT, (CONSZ) tsize( STRTY, p->in.left->fn.cdim, p->in.left->fn.csiz ) );
+               printf( "\t%d\t\n", talign( STRTY, p->in.left->fn.csiz ) );
+               break;
+
+       default:
+               printf(  "\n" );
+               }
+
+       if( ty != LTYPE ) prtree( p->in.left );
+       if( ty == BITYPE ) prtree( p->in.right );
+
+       }
+
+# else
+
+p2tree(p) register NODE *p; {
+       register ty;
+
+# ifdef MYP2TREE
+       MYP2TREE(p);  /* local action can be taken here; then return... */
+# endif
+
+       ty = optype(p->in.op);
+
+       switch( p->in.op ){
+
+       case NAME:
+       case ICON:
+#ifndef FLEXNAMES
+               if( p->tn.rval == NONAME ) p->in.name[0] = '\0';
+#else
+               if( p->tn.rval == NONAME ) p->in.name = "";
+#endif
+               else if( p->tn.rval >= 0 ){ /* copy name from exname */
+                       register char *cp;
+                       register i;
+                       cp = exname( stab[p->tn.rval].sname );
+#ifndef FLEXNAMES
+                       for( i=0; i<NCHNAM; ++i ) p->in.name[i] = *cp++;
+#else
+                       p->in.name = tstr(cp);
+#endif
+                       }
+#ifndef FLEXNAMES
+               else sprintf( p->in.name, LABFMT, -p->tn.rval );
+#else
+               else {
+                       char temp[32];
+                       sprintf( temp, LABFMT, -p->tn.rval );
+                       p->in.name = tstr(temp);
+               }
+#endif
+               break;
+
+       case STARG:
+       case STASG:
+       case STCALL:
+       case UNARY STCALL:
+               /* set up size parameters */
+               p->stn.stsize = (tsize(STRTY,p->in.left->fn.cdim,p->in.left->fn.csiz)+SZCHAR-1)/SZCHAR;
+               p->stn.stalign = talign(STRTY,p->in.left->fn.csiz)/SZCHAR;
+               break;
+
+       case REG:
+               rbusy( p->tn.rval, p->in.type );
+       default:
+#ifndef FLEXNAMES
+               p->in.name[0] = '\0';
+#else
+               p->in.name = "";
+#endif
+               }
+
+       p->in.rall = NOPREF;
+
+       if( ty != LTYPE ) p2tree( p->in.left );
+       if( ty == BITYPE ) p2tree( p->in.right );
+       }
+
+# endif
+# endif
diff --git a/lib/pcc/uniqifystab.sed b/lib/pcc/uniqifystab.sed
new file mode 100644 (file)
index 0000000..eb015d8
--- /dev/null
@@ -0,0 +1,17 @@
+s/@/ATSIGN/g
+s/^/@/
+s/$/@/
+s/[^A-Za-z0-9_]\+/@&@/g
+
+# stab.c
+s/@private@/@static@/g
+s/@and@/@\&\&@/g
+s/@or@/@||@/g
+s/@not@/@!@/g
+s/@div@/@\/@/g
+s/@mod@/@%@/g
+s/@nil@/@0@/g
+s/@Boolean@/@bool@/g
+
+s/@//g
+s/ATSIGN/@/g
diff --git a/lib/pcc/xdefs.c b/lib/pcc/xdefs.c
new file mode 100644 (file)
index 0000000..2f1047f
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef lint
+static char *sccsid ="@(#)xdefs.c      4.3 (Berkeley) 3/19/85";
+#endif lint
+
+# include "pass1.h"
+
+/*     communication between lexical routines  */
+
+char   ftitle[100] = "";       /* title of the file */
+char   ititle[100] = "";       /* title of initial file */
+int    lineno;         /* line number of the input file */
+
+CONSZ lastcon;  /* the last constant read by the lexical analyzer */
+float fcon;   /* the last float read by the lexical analyzer */
+double dcon;   /* the last double read by the lexical analyzer */
+
+
+/*     symbol table maintainence */
+
+struct symtab stab[SYMTSZ+1];  /* one extra slot for scratch */
+
+int    curftn;  /* "current" function */
+int    ftnno;  /* "current" function number */
+
+int    curclass,         /* current storage class */
+       instruct,       /* "in structure" flag */
+       stwart,         /* for accessing names which are structure members or names */
+       blevel,         /* block level: 0 for extern, 1 for ftn args, >=2 inside function */
+       curdim;         /* current offset into the dimension table */
+       
+int    dimtab[ DIMTABSZ ];
+
+int    paramstk[ PARAMSZ ];  /* used in the definition of function parameters */
+int    paramno;          /* the number of parameters */
+int    autooff,        /* the next unused automatic offset */
+       argoff, /* the next unused argument offset */
+       strucoff;       /*  the next structure offset position */
+int    regvar;         /* the next free register for register variables */
+int    minrvar;        /* the smallest that regvar gets witing a function */
+OFFSZ  inoff;          /* offset of external element being initialized */
+int    brkflag = 0;    /* complain about break statements not reached */
+
+struct sw swtab[SWITSZ];  /* table for cases within a switch */
+struct sw *swp;  /* pointer to next free entry in swtab */
+int swx;  /* index of beginning of cases for current switch */
+
+/* debugging flag */
+int xdebug = 0;
+
+int strflg;  /* if on, strings are to be treated as lists */
+
+int reached;   /* true if statement can be reached... */
+
+int idname;    /* tunnel to buildtree for name id's */
+
+
+NODE node[TREESZ];
+
+int cflag = 0;  /* do we check for funny casts */
+int hflag = 0;  /* do we check for various heuristics which may indicate errors */
+int pflag = 0;  /* do we check for portable constructions */
+
+int brklab;
+int contlab;
+int flostat;
+int retlab = NOLAB;
+int retstat;
+
+/* save array for break, continue labels, and flostat */
+
+int asavbc[BCSZ];
+int *psavbc = asavbc ;
+
+# ifndef BUG1
+static char *
+ccnames[] = { /* names of storage classes */
+       "SNULL",
+       "AUTO",
+       "EXTERN",
+       "STATIC",
+       "REGISTER",
+       "EXTDEF",
+       "LABEL",
+       "ULABEL",
+       "MOS",
+       "PARAM",
+       "STNAME",
+       "MOU",
+       "UNAME",
+       "TYPEDEF",
+       "FORTRAN",
+       "ENAME",
+       "MOE",
+       "UFORTRAN",
+       "USTATIC",
+       };
+
+char * scnames( c ) register c; {
+       /* return the name for storage class c */
+       static char buf[12];
+       if( c&FIELD ){
+               sprintf( buf, "FIELD[%d]", c&FLDSIZ );
+               return( buf );
+               }
+       return( ccnames[c] );
+       }
+# endif
index 4b70a1f..caba106 100755 (executable)
@@ -56,7 +56,8 @@ then
   #rm -f `find $INCLUDE -name '*.h.uses' -print`
   rm -rf `find $INCLUDE -name .xify -print`
 
-  rm -f a b conflicts.temp oldprotos.txt oldprotos.temp xx*
+  rm -f a b oldprotos.txt oldprotos.temp xx*
+#conflicts.temp
 
   if test "$1" = 000
   then
@@ -352,12 +353,12 @@ EOF
   mv $INCLUDE/stdint.h.save $INCLUDE/stdint.h
   mv $INCLUDE/varargs.h.save $INCLUDE/varargs.h
 
-  if test -f conflicts.txt
-  then
-    sed -e 's/^/:/;s/ /::/g;s/$/:/' <conflicts.txt >conflicts.temp
-  else
-    touch conflicts.temp
-  fi
+  #if test -f conflicts.txt
+  #then
+  #  sed -e 's/^/:/;s/ /::/g;s/$/:/' <conflicts.txt >conflicts.temp
+  #else
+  #  touch conflicts.temp
+  #fi
 
   for i in $all_h $std_h
   do
@@ -442,7 +443,8 @@ EOF
           echo "j=$j"
           k=`echo $j |sed -e "s:^$INCLUDE/::"`
           echo "k=$k"
-          if ! grep -q ":$h:.*:$k:\\|:$k:.*:$h:" conflicts.temp
+          #if ! grep -q ":$h:.*:$k:\\|:$k:.*:$h:" conflicts.temp
+          if ! test -f conflicts.txt || ! grep -q "^$k $h$" conflicts.txt
           then
             echo $i >>$j.uses
           fi
@@ -518,7 +520,8 @@ EOF
           echo "j=$j"
           k=`echo $j |sed -e "s:^$INCLUDE/::"`
           echo "k=$k"
-          if ! grep -q ":$h:.*:$k:\\|:$k:.*:$h:" conflicts.temp
+          #if ! grep -q ":$h:.*:$k:\\|:$k:.*:$h:" conflicts.temp
+          if ! test -f conflicts.txt || ! grep -q "^$k $h$" conflicts.txt
           then
             echo $i >>$j.uses
           fi