summaryrefslogtreecommitdiff
path: root/support/makeprog/src
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/makeprog/src
Initial commit
Diffstat (limited to 'support/makeprog/src')
-rw-r--r--support/makeprog/src/doc2tex.l122
-rw-r--r--support/makeprog/src/makeprog.web1171
-rw-r--r--support/makeprog/src/progdoc.doc668
-rw-r--r--support/makeprog/src/progdoc.tex217
-rw-r--r--support/makeprog/src/progltx.doc739
-rw-r--r--support/makeprog/src/progltx.sty194
-rw-r--r--support/makeprog/src/tex2doc.l12
7 files changed, 3123 insertions, 0 deletions
diff --git a/support/makeprog/src/doc2tex.l b/support/makeprog/src/doc2tex.l
new file mode 100644
index 0000000000..fbe22e600a
--- /dev/null
+++ b/support/makeprog/src/doc2tex.l
@@ -0,0 +1,122 @@
+%{
+/* doc2tex.l 06 Oct 90
+ *---------------------------------------------------------
+ * (c) 1990 by J.Schrod.
+ * Copyright conditions: GNU General Public License
+ */
+
+/*
+ * VERSION HISTORY
+ *
+ * DATE REMARK
+ * 90-10-06 mentioned filelist WEBWARE for LISTSERV in Heidelberg,
+ * added tuglib
+ * 90-01-14 june.cs.washington.edu instead of cs.washington.edu
+ * 90-01-20 first version
+ */
+
+%}
+
+%S PREAMBLE COMMENT COPY
+
+
+%{
+#include <ctype.h>
+void hint_to_makeprog();
+%}
+
+
+%%
+
+%{
+#ifdef MSDOS
+ check_yycrank(); /* this should go into ncform... */
+#endif
+ BEGIN PREAMBLE;
+%}
+
+
+^\ *\n putc('\n', yyout);
+
+
+<PREAMBLE>^%.*\n ECHO;
+<PREAMBLE>^. {
+ hint_to_makeprog();
+ unput(yytext[0]); NLSTATE;
+ BEGIN COMMENT;
+ }
+
+<COMMENT>^\\beginprog.*\n {
+ fputs("%%% ", yyout); ECHO;
+ BEGIN COPY;
+ }
+<COMMENT>^.*\n {
+ fputs("%%% ", yyout); ECHO;
+ }
+
+<COPY>^\\endprog.*\n {
+ fputs("%%% ", yyout); ECHO;
+ BEGIN COMMENT;
+ }
+<COPY>^%%%.*\n {
+ fputs("%%% ", yyout); ECHO;
+ fprintf(stderr, "Macro code changed at line %d\n", yylineno-1);
+ }
+<COPY>^.*\n ECHO;
+
+
+.|\n {
+ register char c = yytext[0];
+ fprintf(stderr,
+ "! Illegal state at char %c (\"%02x) in line %d\n",
+ ( isprint(c) ? c : ' ' ),
+ (unsigned char)c,
+ ( c == '\n' ? yylineno-1 : yylineno )
+ );
+ }
+
+
+%%
+
+void hint_to_makeprog()
+{
+ fputs("%%%%\n",yyout);
+ fputs("%%%%\n",yyout);
+ fputs(
+ "%%%% These TeX macros were documented with the documentation system\n",
+ yyout);
+ fputs(
+ "%%%% MAKEPROG and automatically converted to the current form.\n",
+ yyout);
+ fputs(
+ "%%%% If you have MAKEPROG available you may transform it back to\n",
+ yyout);
+ fputs(
+ "%%%% the original input: Remove every occurence of three percents\n",
+ yyout);
+ fputs(
+ "%%%% and one optional blank from the beginning of a line and remove\n",
+ yyout);
+ fputs(
+ "%%%% every line which starts with four percents. The following lex\n",
+ yyout);
+ fputs(
+ "%%%% program will do this:\n",
+ yyout);
+ fputs("%%%%\n",yyout);
+ fputs("%%%% %%\n",yyout);
+ fputs("%%%%\n",yyout);
+ fputs("%%%% ^%%%\\ ? ;\n",yyout);
+ fputs("%%%% ^%%%%.*\\n ;\n",yyout);
+ fputs("%%%%\n",yyout);
+ fputs(
+ "%%%% MAKEPROG may be obtained over the net from the Bitnet-Listserver\n",
+ yyout);
+ fputs(
+ "%%%% LISTSERV@DHDURZ1 (filelist WEBWARE), from tuglib@science.utah.edu,\n",
+ yyout);
+ fputs("%%%% or via ftp from june.cs.washington.edu.\n", yyout);
+ fputs("%%%%\n",yyout);
+ fputs("%%%%\n",yyout);
+ return;
+}
diff --git a/support/makeprog/src/makeprog.web b/support/makeprog/src/makeprog.web
new file mode 100644
index 0000000000..0ef2f4989d
--- /dev/null
+++ b/support/makeprog/src/makeprog.web
@@ -0,0 +1,1171 @@
+% This is MAKEPROG.WEB as of 25 Sep 90
+%---------------------------------------------------------
+% (c) 1988 by J.Schrod.
+% Major parts of this program have been taken from TANGLE.WEB
+% by D.E.Knuth, which is not copyrighted.
+
+%
+% VERSION HISTORY (MSCF -- most significant change first)
+%
+% DATE VER WHO REMARK
+% 90-09-25 1.0.1 js updated copyright notice
+% 88-11 1.0 js first release
+
+% bug reports to:
+%
+% Detig$\,\cdot\,$Schrod \TeX{}sys
+% Joachim Schrod
+% Kranichweg 1
+%
+% D-6074 R\"odermark-Urberach
+% FR Germany
+%
+% Tel. (+6074) 1617
+% Bitnet: XITIJSCH@DDATHD21
+
+% author:
+% js: Joachim Schrod <xitijsch@ddathd21.bitnet>
+% contributors:
+% (-: place enough for your name! :-)
+
+
+\def\title{MAKEPROG (V\version)}
+\def\version{1.0.1}
+\def\years{1988,1990}
+
+\font\ninerm=cmr9
+\let\mc=\ninerm % medium caps for names like EBCDIC
+
+\def\hang{\hangindent 3em\indent\ignorespaces}
+\def\item#1{ % fixed item of 30pt width
+ {\parskip=0pt\endgraf\noindent}% % new line
+ \hangindent 30pt %
+ \hbox to 30pt{\hfil#1\kern 1em}%
+ \ignorespaces % ignore following blanks
+ }
+
+\def\PASCAL{Pascal}
+\def\MAKEPROG{\leavevmode\hbox{\mc MAKEPROG\/}}
+\def\ASCII{\leavevmode\hbox{\mc ASCII\/}}
+\mathchardef\BA="3224 % double arrow as relation
+
+\def\topofcontents{\null\vfill
+ \centerline{\titlefont The MAKEPROG processor}
+ \vskip 15pt
+ \centerline{(Version \version)}
+ \vskip 2cm}
+\def\botofcontents{\vfill
+ \hangindent 3em
+ \noindent $\copyright$ \years{} by Joachim Schrod.
+ All rights reserved.
+ \par \vskip 1ex
+ \noindent \MAKEPROG{} comes with {\bf absolutely no warranty}.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; see section~2 for details.
+ \par}
+
+
+
+
+
+@* Introduction. % sect. 1
+
+\noindent This program converts a documentation file to a
+program file, i.e.\ all files between \.{\\beginprog} and
+\.{\\endprog} are copied verbatim. It was written by
+J.~Schrod in September, 1987. This program is written in
+\.{WEB}.
+
+The program uses a few features of the local \PASCAL\
+compiler that may need to be changed in other installations:
+
+\item{1)} Case statements have a default.
+
+\item{2)} Input-output routines may need to be adapted for
+use with a particular character set and/or for printing
+messages on the user's terminal.
+
+\noindent System-dependent portions of \MAKEPROG{} can be
+identified by looking at the entries for `system
+dependencies' in the index below.
+@!@^system dependencies@>
+
+
+@ % sect. 2
+This program is free software; you can redistribute it and/or
+modify it under the terms of the \GNU{} General Public License as
+published by the Free Software Foundation; either version~1, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+{\bf without any warranty\/}; without even the implied warranty of
+{\bf merchantability\/} or {\bf fitness for a particular purpose}. See
+the \GNU{} General Public License for more details.
+
+You should have received a copy of the \GNU{} General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 675~Mass Ave, Cambridge, MA~02139, USA.
+
+The ``banner line'' defined here should be changed whenever
+\MAKEPROG{} is modified. The copyright notice must not be deleted.
+
+@d banner=='This is MAKEPROG, Version 1.0.1.'
+@d copy_right==' (c) 1988,1990 by J.Schrod.'
+@d rights_res==' All rights reserved.'
+
+
+@ % sect. 3
+The program begins with a fairly normal header, made up of
+pieces that will mostly be filled in later. The input comes
+from files |doc_file| and |change_file|, the output goes to
+file |prog_file|. Messages from \MAKEPROG{} are written to
+|term_out|, which is supposed to be the terminal.
+@^system dependencies@>
+
+If it is necessary to abort the job because of a fatal
+error, the program calls the `|jump_out|' procedure, which
+goes to the label |end_of_MAKEPROG|.
+
+@d end_of_MAKEPROG = 9999 {go here to wrap it up}
+
+@p @t\4@>@<Compiler directives@>@/
+program MAKEPROG(@!doc_file,@!change_file,@!prog_file);
+label end_of_MAKEPROG; {go here to finish}
+const @<Constants in the outer block@>@;
+type @<Types in the outer block@>@;
+var @<Globals in the outer block@>@;
+@t\4@>@<Error handling procedures@>@;
+procedure initialize;
+ var @<Local variables for initialization@>@;
+ begin @<Set initial values@>
+ end;
+
+
+@ % sect. 4
+Some of this code is optional for use when debugging only;
+such material is enclosed between the delimiters \&{debug}
+and \&{gubed}.
+
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@f debug==repeat
+@f gubed==until
+
+
+@ % sect. 5
+The \PASCAL\ compiler used to develop this system has
+``compiler directives'' that can appear in comments whose
+first character is a dollar sign. In production versions of
+\MAKEPROG{} these directives tell the compiler that it is
+safe to avoid range checks and to leave out the extra code
+it inserts for the \PASCAL\ debugger's benefit.
+@^system dependencies@>
+
+@<Compiler directives@>=
+@{@&@=$D-@> @} {no debug overhead}
+@!debug @{@&@=$D+@> @}@+ gubed @; {but turn everything on when debugging}
+
+
+@ % sect. 6
+Labels are given symbolic names by the following
+definitions. We insert the label `|exit|' just before the
+`\&{end}' of a procedure in which we have used the
+`|return|' statement defined below; the label `|restart|' is
+occasionally used at the very beginning of a procedure; and
+the label `|reswitch|' is occasionally used just prior to a
+\&{case} statement in which some cases change the conditions
+and we wish to branch to the newly applicable case. Loops
+that are set up with the \&{loop} construction defined below
+are commonly exited by going to `|done|' or to `|found|' or
+to `|not_found|', and they are sometimes repeated by going
+to `|continue|'.
+
+@d exit=10 {go here to leave a procedure}
+@d restart=20 {go here to start a procedure again}
+@d reswitch=21 {go here to start a case statement again}
+@d continue=22 {go here to resume a loop}
+@d done=30 {go here to exit a loop}
+@d found=31 {go here when you've found it}
+@d not_found=32 {go here when you've found something else}
+
+
+@ % sect. 7
+Here are some macros for common programming idioms.
+
+@d incr(#) == #:=#+1 {increase a variable by unity}
+@d decr(#) == #:=#-1 {decrease a variable by unity}
+@d loop == @+ while true do@+ {repeat over and over until a |goto| happens}
+@d do_nothing == {empty statement}
+@d return == goto exit {terminate a procedure call}
+@f return == nil
+@f loop == xclause
+
+
+@ % sect. 8
+We assume that |case| statements may include a default case
+that applies if no matching label is found. Thus, we shall
+use constructions like
+@^system dependencies@>
+$$
+\vbox{\halign{#\hfil\cr
+|case x of|\cr
+ \quad 1: $\langle\,$code for $x=1\,\rangle$;\cr
+ \quad 3: $\langle\,$code for $x=3\,\rangle$;\cr
+ \quad |othercases| $\langle\,$code for |x<>1| and |x<>3|$\,\rangle$\cr
+|endcases|\cr
+}}
+$$
+since most \PASCAL\ compilers have plugged this hole in the
+language by incorporating some sort of default mechanism.
+For example, the compiler used to develop \.{WEB} and \TeX\
+allows `|others|:' as a default label, and other \PASCAL s
+allow syntaxes like `\&{else}' or `\&{otherwise}' or
+`\\{otherwise}:', etc. The definitions of |othercases| and
+|endcases| should be changed to agree with local
+conventions. (Of course, if no default mechanism is
+available, the |case| statements of this program must be
+extended by listing all remaining cases.)
+
+@d othercases == others: {default for cases not listed explicitly}
+@d endcases == @+end {follows the default case in an extended |case| statement}
+@f othercases == else
+@f endcases == end
+
+
+@ % sect. 9
+The following parameter is set big enough to be sufficient
+for most applications of \MAKEPROG{}.
+
+@<Constants...@>=
+@!buf_size=500; {maximum length of input line}
+
+
+@ % sect. 10
+A global variable called |history| will contain one of four values
+at the end of every run: |spotless| means that no unusual messages were
+printed; |harmless_message| means that a message of possible interest
+was printed but no serious errors were detected; |error_message| means that
+at least one error was found; |fatal_message| means that the program
+terminated abnormally. The value of |history| does not influence the
+behavior of the program; it is simply computed for the convenience
+of systems that might want to use such information.
+
+@d spotless=0 {|history| value for normal jobs}
+@d harmless_message=1 {|history| value when non-serious info was printed}
+@d error_message=2 {|history| value when an error was noted}
+@d fatal_message=3 {|history| value when we had to stop prematurely}
+@#
+@d mark_harmless==@t@>@+if history=spotless then history:=harmless_message
+@d mark_error==history:=error_message
+@d mark_fatal==history:=fatal_message
+
+@<Glob...@>=@!history:spotless..fatal_message; {how bad was this run?}
+
+@ % sect. 11
+@<Set init...@>=history:=spotless;
+
+
+
+
+
+@* The character set. % sect. 12
+
+\noindent One of the main goals in the design of \MAKEPROG{}
+has been to make it readily portable between a wide variety
+of computers. Yet \MAKEPROG{} by its very nature must use a
+greater variety of characters than most computer programs
+deal with, and character encoding is one of the areas in
+which existing machines differ most widely from each other.
+
+To resolve this problem, all input to \MAKEPROG{} is
+converted to an internal seven-bit code that is essentially
+standard \ASCII{}, the ``American Standard Code for
+Information Interchange.'' The conversion is done
+immediately when each character is read in. Conversely,
+characters are converted from \ASCII{} to the user's
+external representation just before they are output. Such
+an internal code is never relevant to users of \MAKEPROG{}.
+
+\noindent Here is a table of the standard visible \ASCII{} codes:
+$$\def\:{\char\count255\global\advance\count255 by 1}
+\count255='40
+\vbox{
+\hbox{\hbox to 40pt{\it\hfill0\/\hfill}%
+\hbox to 40pt{\it\hfill1\/\hfill}%
+\hbox to 40pt{\it\hfill2\/\hfill}%
+\hbox to 40pt{\it\hfill3\/\hfill}%
+\hbox to 40pt{\it\hfill4\/\hfill}%
+\hbox to 40pt{\it\hfill5\/\hfill}%
+\hbox to 40pt{\it\hfill6\/\hfill}%
+\hbox to 40pt{\it\hfill7\/\hfill}}
+\vskip 4pt
+\hrule
+\def\^{\vrule height 10.5pt depth 4.5pt}
+\halign{\hbox to 0pt{\hskip -24pt\O{#0}\hfill}&\^
+\hbox to 40pt{\tt\hfill#\hfill\^}&
+&\hbox to 40pt{\tt\hfill#\hfill\^}\cr
+04&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+05&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+06&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+07&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+10&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+11&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+12&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+13&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+14&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+15&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+16&\:&\:&\:&\:&\:&\:&\:&\:\cr\noalign{\hrule}
+17&\:&\:&\:&\:&\:&\:&\:\cr}
+\hrule width 280pt}$$
+(Actually, of course, code @"20 is an invisible blank
+space.) Code @"3E was once an upward arrow (\.{\char'13}),
+and code @"3F was once a left arrow (\.^^X), in olden times
+when the first draft of \ASCII{} code was prepared; but
+\MAKEPROG{} works with today's standard \ASCII{} in which
+those codes represent circumflex and underline as shown.
+
+@<Types...@>=
+@!ASCII_code=0..@"7F; {seven-bit numbers, a subrange of the integers}
+
+
+@ % sect. 13
+The original \PASCAL\ compiler was designed in the late 60s,
+when six-bit character sets were common, so it did not make
+provision for lowercase letters. Nowadays, of course, we
+need to deal with both capital and small letters in a
+convenient way, so \MAKEPROG{} assumes that it is being used
+with a \PASCAL\ whose character set contains at least the
+characters of standard \ASCII{} as listed above. Some
+\PASCAL\ compilers use the original name |char| for the data
+type associated with the characters in text files, while
+other \PASCAL s consider |char| to be a 64-element subrange
+of a larger data type that has some other name.
+
+In order to accommodate this difference, we shall use the
+name |text_char| to stand for the data type of the
+characters in the input and output files. We shall also
+assume that |text_char| consists of the elements
+|chr(first_text_char)| through |chr(last_text_char)|,
+inclusive. The following definitions should be adjusted if
+necessary.
+@^system dependencies@>
+
+@d text_char == char {the data type of characters in text files}
+@d first_text_char=0 {ordinal number of the smallest element of |text_char|}
+@d last_text_char=127 {ordinal number of the largest element of |text_char|}
+
+@<Types...@>=
+@!text_file=packed file of text_char;
+
+
+@ % sect. 14
+The \MAKEPROG{} processor convert between \ASCII{} code and
+the user's external character set by means of arrays |xord|
+and |xchr| that are analogous to \PASCAL's |ord| and |chr|
+functions.
+
+@<Globals...@>=
+@!xord: array [text_char] of ASCII_code;
+ {specifies conversion of input characters}
+@!xchr: array [ASCII_code] of text_char;
+ {specifies conversion of output characters}
+
+
+@ % sect. 15
+If we assume that every system using \.{WEB} is able to read
+and write the visible characters of standard \ASCII{}
+(although not necessarily using the \ASCII{} codes to
+represent them), the following assignment statements
+initialize most of the |xchr| array properly, without
+needing any system-dependent changes. For example, the
+statement \.{xchr["A"]:=\'A\'} that appears in the present
+\.{WEB} file might be encoded in, say, \hbox{\mc EBCDIC}
+code on the external medium on which it resides, but
+\.{TANGLE} will convert from this external code to \ASCII{}
+and back again. Therefore the assignment statement
+\.{XCHR[65]:=\'A\'} will appear in the corresponding
+\PASCAL\ file, and \PASCAL\ will compile this statement so
+that |xchr[65]| receives the character \.A in the external
+(|char|) code. Note that it would be quite incorrect to say
+\.{xchr["A"]:="A"}, because |"A"| is a constant of type
+|integer|, not |char|, and because we have $|"A"|=65$
+regardless of the external character set.
+
+@<Set init...@>=
+xchr[" "]:=' ';
+xchr["!"]:='!';
+xchr[""""]:='"';
+xchr["#"]:='#';
+xchr["$"]:='$';
+xchr["%"]:='%';
+xchr["&"]:='&';
+xchr["'"]:='''';@/
+xchr["("]:='(';
+xchr[")"]:=')';
+xchr["*"]:='*';
+xchr["+"]:='+';
+xchr[","]:=',';
+xchr["-"]:='-';
+xchr["."]:='.';
+xchr["/"]:='/';@/
+xchr["0"]:='0';
+xchr["1"]:='1';
+xchr["2"]:='2';
+xchr["3"]:='3';
+xchr["4"]:='4';
+xchr["5"]:='5';
+xchr["6"]:='6';
+xchr["7"]:='7';@/
+xchr["8"]:='8';
+xchr["9"]:='9';
+xchr[":"]:=':';
+xchr[";"]:=';';
+xchr["<"]:='<';
+xchr["="]:='=';
+xchr[">"]:='>';
+xchr["?"]:='?';@/
+xchr["@@"]:='@@';
+xchr["A"]:='A';
+xchr["B"]:='B';
+xchr["C"]:='C';
+xchr["D"]:='D';
+xchr["E"]:='E';
+xchr["F"]:='F';
+xchr["G"]:='G';@/
+xchr["H"]:='H';
+xchr["I"]:='I';
+xchr["J"]:='J';
+xchr["K"]:='K';
+xchr["L"]:='L';
+xchr["M"]:='M';
+xchr["N"]:='N';
+xchr["O"]:='O';@/
+xchr["P"]:='P';
+xchr["Q"]:='Q';
+xchr["R"]:='R';
+xchr["S"]:='S';
+xchr["T"]:='T';
+xchr["U"]:='U';
+xchr["V"]:='V';
+xchr["W"]:='W';@/
+xchr["X"]:='X';
+xchr["Y"]:='Y';
+xchr["Z"]:='Z';
+xchr["["]:='[';
+xchr["\"]:='\';
+xchr["]"]:=']';
+xchr["^"]:='^';
+xchr["_"]:='_';@/
+xchr["`"]:='`';
+xchr["a"]:='a';
+xchr["b"]:='b';
+xchr["c"]:='c';
+xchr["d"]:='d';
+xchr["e"]:='e';
+xchr["f"]:='f';
+xchr["g"]:='g';@/
+xchr["h"]:='h';
+xchr["i"]:='i';
+xchr["j"]:='j';
+xchr["k"]:='k';
+xchr["l"]:='l';
+xchr["m"]:='m';
+xchr["n"]:='n';
+xchr["o"]:='o';@/
+xchr["p"]:='p';
+xchr["q"]:='q';
+xchr["r"]:='r';
+xchr["s"]:='s';
+xchr["t"]:='t';
+xchr["u"]:='u';
+xchr["v"]:='v';
+xchr["w"]:='w';@/
+xchr["x"]:='x';
+xchr["y"]:='y';
+xchr["z"]:='z';
+xchr["{"]:='{';
+xchr["|"]:='|';
+xchr["}"]:='}';
+xchr["~"]:='~';@/
+xchr[0]:=' '; xchr[@"7F]:=' '; {these \ASCII{} codes are not used}
+
+
+@ % sect. 16
+Some of the nonprintable \ASCII{} codes have been given
+symbolic names in \MAKEPROG{} because they are used with a
+special meaning.
+
+@d tab_mark=@"09 {\ASCII{} code used as tab-skip}
+@d line_feed=@"0A {\ASCII{} code thrown away at end of line}
+@d form_feed=@"0C {\ASCII{} code used at end of page}
+@d carriage_return=@"0D {\ASCII{} code used at end of line}
+
+
+@ % sect. 17
+When we initialize the |xord| array and the remaining parts of |xchr|,
+it will be convenient to make use of an index variable, |i|.
+
+@<Local variables for init...@>=
+@!i:0..last_text_char;
+
+
+@ % sect. 18
+Here now is the system-dependent part of the character set.
+If \MAKEPROG{} is being implemented on a garden-variety
+\PASCAL\ for which only standard \ASCII{} codes will appear
+in the input and output files, you don't need to make any
+changes here.
+@^system dependencies@>
+
+Changes to the present module will make \MAKEPROG{} more
+friendly on computers that have an extended character set,
+so that one can type things like Umlaute. If you have an
+extended set of characters that are easily incorporated into
+text files, you can assign codes arbitrarily here, giving an
+|xchr| equivalent to whatever characters the users of
+\MAKEPROG{} are allowed to have in their input files,
+provided that unsuitable characters do not correspond to
+special codes like |carriage_return| that are listed above.
+
+@<Set init...@>=
+for i:=1 to " "-1 do xchr[i]:=' ';
+
+
+@ % sect. 19
+The following system-independent code makes the |xord| array
+contain a suitable inverse to the information in |xchr|.
+
+@<Set init...@>=
+for i:=first_text_char to last_text_char do xord[chr(i)]:=" ";
+for i:=1 to "~" do xord[xchr[i]]:=i;
+
+
+
+
+
+@* Basic Input and output. % sect. 20
+
+\noindent The input conventions of \MAKEPROG{} are identical
+to those of \.{WEB}. Therefore people who need to make
+modifications to both systems should be able to do so
+without too many headaches.
+
+
+@ % sect. 21
+Terminal output is done by writing on file |term_out|, which
+is assumed to consist of characters of type |text_char|:
+@^system dependencies@>
+
+@d print(#)==write(term_out,#) {`|print|' means write on the terminal}
+@d print_ln(#)==write_ln(term_out,#) {`|print|' and then start new line}
+@d new_line==write_ln(term_out) {start new line}
+@d print_nl(#)== {print information starting on a new line}
+ begin new_line; print(#);
+ end
+
+@<Globals...@>=
+@!term_out:text_file; {the terminal as an output file}
+
+
+@ % sect. 22
+Different systems have different ways of specifying that the
+output on a certain file will appear on the user's terminal.
+Here is one way to do this on the \PASCAL{} system that was
+used in \.{TANGLE}'s initial development.
+@^system dependencies@>
+
+@<Set init...@>=
+rewrite(term_out,'TTY:'); {send |term_out| output to the terminal}
+
+
+@ % sect. 23
+The |update_terminal| procedure is called when we want to
+make sure that everything we have output to the terminal so
+far has actually left the computer's internal buffers and
+been sent.
+@^system dependencies@>
+
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+
+
+@ % sect. 24
+The main input comes from |doc_file|; this input may be
+overridden by changes in |change_file|. (If |change_file|
+is empty, there are no changes.)
+
+@<Globals...@>=
+@!doc_file:text_file; {primary input}
+@!change_file:text_file; {updates}
+
+
+@ % sect. 25
+The following code opens the input files. Since these files
+were listed in the program header, we assume that the
+\PASCAL\ runtime system has already checked that suitable
+file names have been given; therefore no additional error
+checking needs to be done.
+@^system dependencies@>
+
+@< Set init... @>=
+reset(doc_file); reset(change_file);
+
+
+@ % sect. 26
+The output goes to |prog_file|.
+
+@<Globals...@>=
+@!prog_file: text_file;
+
+
+@ % sect. 27
+The following code opens |prog_file|. Since this file is
+listed in the program header, we assume that the \PASCAL\
+runtime system has checked that a suitable external file
+name have been given.
+@^system dependencies@>
+
+@<Set init...@>=
+rewrite(prog_file);
+
+
+@ % sect. 28
+Input goes into an array called |buffer|.
+
+@<Globals...@>=
+@!buffer: array[0..buf_size] of ASCII_code;
+
+
+@ % sect. 29
+The |input_ln| procedure brings the next line of input from
+the specified file into the |buffer| array and returns the
+value |true|, unless the file has already been entirely
+read, in which case it returns |false|. The conventions of
+\.{WEB} are followed; i.e., |ASCII_code| numbers
+representing the next line of the file are input into
+|buffer[0]|, |buffer[1]|, \dots, |buffer[limit-1]|; trailing
+blanks are ignored; and the global variable |limit| is set
+to the length of the line. The value of |limit| must be
+strictly less than |buf_size|.
+@^system dependencies@>
+
+We assume that none of the |ASCII_code| values of
+|buffer[j]| for |0<=j<limit| is equal to 0, @"7F,
+|line_feed|, |form_feed|, or |carriage_return|.
+
+@p
+function input_ln(var f:text_file):boolean; {inputs a line or returns |false|}
+ var final_limit:0..buf_size; {|limit| without trailing blanks}
+ begin limit:=0; final_limit:=0;
+ if eof(f) then input_ln:=false
+ else begin
+ while not eoln(f) do
+ begin buffer[limit]:=xord[f^]; get(f);
+ incr(limit);
+ if (buffer[limit-1]<>" ") and (buffer[limit-1]<>tab_mark) then
+ final_limit:=limit;
+ if limit=buf_size then
+ begin while not eoln(f) do get(f);
+ decr(limit); {keep |buffer[buf_size]| empty}
+ print_nl('! Input line too long'); error; mark_error;
+@.Input line too long@>
+ end;
+ end;
+ read_ln(f); limit:=final_limit; input_ln:=true;
+ end;
+ end;
+
+
+
+
+
+@* Reporting errors to the user. % sect. 30
+
+\noindent Errors are reported to the user by saying
+$$
+ \hbox{`|err_print('! Error message')|'},
+$$
+followed by `|jump_out|' if no recovery from the error is
+provided. This will print the error message followed by an
+indication of where the error was spotted in the source
+file. Note that no period follows the error message, since
+the error routine will automatically supply a period.
+
+\noindent The actual error indications are provided by a
+procedure called |error|.
+
+@d err_print(#)==begin print_nl(#); error; mark_error; end
+
+@<Error handling...@>=
+procedure error; {prints '\..' and location of error message}
+ begin @< Print error location @>;
+ update_terminal;
+ end;
+
+
+@ % sect. 31
+The error locations can be indicated by using the global
+variables |line| and |changing|, which tell respectively the
+the current line number and whether or not the current line
+is from |change_file| or |doc_file|. This routine should be
+modified on systems whose standard text editor has special
+line-numbering conventions.
+@^system dependencies@>
+
+@< Print error location @>=
+begin
+if changing then print('. (change file ') @+ else print('. (');
+print_ln('l.', line:1, ')');
+print(' '); {this space separates the message from future output}
+end
+
+
+@ % sect. 32
+The |jump_out| procedure just cuts across all active
+procedure levels and jumps out of the program. This is the
+only non-local |goto| statement in \MAKEPROG{}. It is used
+when no recovery from a particular error has been provided.
+
+Some \PASCAL\ compilers do not implement non-local |goto| statements.
+@^system dependencies@>
+In such cases the code that appears at label
+|end_of_MAKEPROG| should be copied into the |jump_out|
+procedure, followed by a call to a system procedure that
+terminates the program.
+
+@d fatal_error(#)==begin print_nl(#); error; mark_fatal; jump_out;
+ end
+
+@<Error handling...@>=
+procedure jump_out;
+begin goto end_of_MAKEPROG;
+end;
+
+
+@ % sect. 33
+Sometimes the program's behavior is far different from what
+it should be, and \MAKEPROG{} prints an error message that
+is really for the \MAKEPROG{} maintenance person, not the
+user. In such cases the program says
+|confusion('indication of where we are')|.
+
+@d confusion(#)==fatal_error('! This can''t happen (',#,')')
+@.This can't happen@>
+
+
+
+
+
+@* The kernel. % sect. 34
+
+\noindent Let us now consider the routine |get_line| that
+takes care of merging |change_file| into |doc_file|. The
+|get_line| procedure also updates the line numbers for error
+messages.
+
+@<Globals...@>=
+@!line:integer; {the number of the current line in the current file}
+@!other_line:integer; {the number of the current line in the input file that
+ is not currently being read}
+@!temp_line:integer; {used when interchanging |line| with |other_line|}
+@!limit:0..buf_size; {the last character position occupied in the buffer}
+@!input_has_ended: boolean; {if |true|, there is no more input}
+@!changing: boolean; {if |true|, the current line is from |change_file|}
+
+
+@ % sect. 35
+As we change |changing| from |true| to |false| and back
+again, we must remember to swap the values of |line| and
+|other_line| so that the |err_print| routine will be sure to
+report the correct line number.
+
+@d change_changing==
+ begin changing := not changing;@/
+ temp_line:=other_line; other_line:=line; line:=temp_line;
+ end {$|line| \BA |other_line|$}
+
+
+@ % sect. 36
+When |changing| is |false|, the next line of |change_file|
+is kept in |change_buffer[0..change_limit-1]|, for purposes
+of comparison with the next line of |doc_file|. After the
+change file has been completely input, we set
+|change_limit:=0|, so that no further matches will be made.
+
+@<Globals...@>=
+@!change_buffer:array[0..buf_size] of ASCII_code;
+@!change_limit:0..buf_size; {the last position occupied in |change_buffer|}
+
+
+@ % sect. 37
+Here's a simple function that checks if the two buffers are
+different.
+
+@p function lines_dont_match:boolean;
+label exit;
+var k:0..buf_size; {index into the buffers}
+begin lines_dont_match:=true;
+if change_limit<>limit then return;
+if limit>0 then
+ for k:=0 to limit-1 do if change_buffer[k]<>buffer[k] then return;
+lines_dont_match:=false;
+exit: end;
+
+
+@ % sect. 38
+Procedure |prime_the_change_buffer| sets |change_buffer| in
+preparation for the next matching operation. Since blank
+lines in the change file are not used for matching, we have
+|(change_limit=0)and not changing| if and only if the change
+file is exhausted. This procedure is called only when
+|changing| is true; hence error messages will be reported
+correctly.
+
+@p procedure prime_the_change_buffer;
+label continue, done, exit;
+var k:0..buf_size; {index into the buffers}
+begin change_limit:=0; {this value will be used if the change file ends}
+@<Skip over comment lines in the change file; |return| if end of file@>;
+@<Skip to the next nonblank line; |return| if end of file@>;
+@<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>;
+exit: end;
+
+
+@ % sect. 39
+While looking for a line that begins with \.{@@x} in the
+change file, we allow lines that begin with \.{@@}, as long
+as they don't begin with \.{@@y} or \.{@@z} (which would
+probably indicate that the change file is fouled up).
+
+@<Skip over comment lines in the change file...@>=
+loop@+ begin incr(line);
+ if not input_ln(change_file) then return;
+ if limit<2 then goto continue;
+ if buffer[0]<>"@@" then goto continue;
+ if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if buffer[1]="x" then goto done;
+ if (buffer[1]="y")or(buffer[1]="z") then
+ err_print('! Where is the matching @@x?');
+@.Where is the match...@>
+continue: end;
+done:
+
+
+@ % sect. 40
+Here we are looking at lines following the \.{@@x}.
+
+@<Skip to the next nonblank line...@>=
+repeat incr(line);
+ if not input_ln(change_file) then
+ begin err_print('! Change file ended after @@x');
+@.Change file ended...@>
+ return;
+ end;
+until limit>0;
+
+
+@ % sect. 41
+@<Move |buffer| and |limit| to |change_buffer| and |change_limit|@>=
+begin change_limit:=limit;
+for k:=0 to limit-1 do change_buffer[k]:=buffer[k];
+end
+
+
+@ % sect. 42
+The following procedure is used to see if the next change
+entry should go into effect; it is called only when
+|changing| is false. The idea is to test whether or not the
+current contents of |buffer| matches the current contents of
+|change_buffer|. If not, there's nothing more to do; but if
+so, a change is called for: All of the text down to the
+\.{@@y} is supposed to match. An error message is issued if
+any discrepancy is found. Then the procedure prepares to
+read the next line from |change_file|.
+
+@p
+procedure check_change; {switches to |change_file| if the buffers match}
+label exit;
+var n:integer; {the number of discrepancies found}
+@!k:0..buf_size; {index into the buffers}
+begin if lines_dont_match then return;
+n:=0;
+loop@+ begin change_changing; {now it's |true|}
+ incr(line);
+ if not input_ln(change_file) then
+ begin err_print('! Change file ended before @@y');@/
+@.Change file ended...@>
+ change_limit:=0; change_changing; {|false| again}
+ return;
+ end;
+ @<If the current line starts with \.{@@y},
+ report any discrepancies and |return|@>;
+ @<Move |buffer| and |limit|...@>;
+ change_changing; {now it's |false|}
+ incr(line);
+ if not input_ln(doc_file) then
+ begin err_print('! CWEB file ended during a change');
+@.CWEB file ended...@>
+ input_has_ended:=true; return;
+ end;
+ if lines_dont_match then incr(n);
+ end;
+exit: end;
+
+
+@ % sect. 43
+@<If the current line starts with \.{@@y}...@>=
+if limit>1 then if buffer[0]="@@" then
+ begin if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if (buffer[1]="x")or(buffer[1]="z") then
+ err_print('! Where is the matching @@y?')
+@.Where is the match...@>
+ else if buffer[1]="y" then
+ begin if n>0 then
+ err_print('! Hmm... ',n:1,' of the preceding lines failed to match');
+@.Hmm... n of the preceding...@>
+ return;
+ end;
+ end
+
+
+@ % sect. 44
+@< Initialize the input system @>=
+begin line:=0; other_line:=0;@/
+changing:=true; prime_the_change_buffer; change_changing;@/
+limit:=0; buffer[0]:=" "; input_has_ended:=false;
+end
+
+
+@ % sect. 45
+The |get_line| procedure puts the next line of merged input
+into the buffer and updates the other variables
+appropriately. A space is placed at the right end of the
+line. We output points to show the user the progress in
+reading.
+
+@p
+procedure get_line; {inputs the next line}
+ label restart;
+ begin
+restart: if changing then
+ @<Read from |change_file| and maybe turn off |changing|@>;
+ if not changing then
+ begin @<Read from |doc_file| and maybe turn on |changing|@>;
+ if changing then goto restart;
+ end;
+ buffer[limit]:=" ";
+ if (line mod 500) = 0 then
+ begin print(line:1); update_terminal;
+ end
+ else if (line mod 100) = 0 then
+ begin print('.'); update_terminal;
+ end
+ @!debug else begin print('.'); update_terminal; @+ end @+ gubed @;
+ ;@/
+ end;
+
+
+@ % sect. 46
+@<Read from |doc_file|...@>=
+begin incr(line);
+if not input_ln(doc_file) then input_has_ended:=true
+else if change_limit>0 then check_change;
+end
+
+
+@ % sect. 47
+@<Read from |change_file|...@>=
+begin incr(line);
+if not input_ln(change_file) then
+ begin err_print('! Change file ended without @@z');
+@.Change file ended...@>
+ buffer[0]:="@@"; buffer[1]:="z"; limit:=2;
+ end;
+if limit>1 then {check if the change has ended}
+ if buffer[0]="@@" then
+ begin if (buffer[1]>="X")and(buffer[1]<="Z") then
+ buffer[1]:=buffer[1]+"z"-"Z"; {lowercasify}
+ if (buffer[1]="x")or(buffer[1]="y") then
+ err_print('! Where is the matching @@z?')
+@.Where is the match...@>
+ else if buffer[1]="z" then
+ begin prime_the_change_buffer; change_changing;
+ end;
+ end;
+end
+
+
+@ % sect. 48
+At the end of the program, we will tell the user if the
+change file had a line that didn't match any relevant line
+in |doc_file|.
+
+@<Check that all changes have been read@>=
+begin
+if change_limit<>0 then {|changing| is false}
+ begin
+ for limit:=0 to change_limit do buffer[limit] := change_buffer[limit];
+ limit := change_limit; changing := true; line := other_line;
+ err_print('! Change file entry did not match');
+@.Change file entry did not match@>
+ end;
+end
+
+
+@ % sect. 49
+The |put_line| procedure outputs the next line from
+|buffer| to |prog_file|. Perhaps we should give here a
+progress report, too (with asterisks?)
+
+@p
+procedure put_line;
+ var i: 0..buf_size;
+ begin
+ for i:=0 to limit-1 do write(prog_file, xchr[buffer[i]]);
+ write_ln(prog_file);
+ end;
+
+
+
+
+
+@* The main program. % sect. 50
+
+\noindent We have defined some procedures, and it is time to
+use them---here is where \MAKEPROG{} starts, and where it
+ends.
+@^system dependencies@>
+
+@p
+ begin initialize;
+ print_ln(banner); {print a ``banner line''}
+ print_ln(copy_right); print_ln(rights_res); {print a copyright notice}
+ @< Initialize the input system @>;
+ debug print_ln('begin copy');
+ gubed @;
+ @< Copy all program parts to the output @>;
+ debug print_ln('end copy');
+ gubed @;
+ @< Check that all changes... @>;
+end_of_MAKEPROG:
+ @#
+ {here files should be closed if the operating system requires it}
+ @;@#
+ @<Print the job |history|@>;
+ end.
+
+
+@ % sect. 51
+A program part begins after a line that begins with
+\.{\\beginprog} and ends before the next line with
+\.{\\endprog} starting it. If we find the starting line we
+set |state| to |begin_prog|, between to lines |state| has
+the value |inner_prog| and with the ending line |state| is
+set to |out_of_prog|.
+
+@d begin_prog = 0
+@d inner_prog = 1
+@d out_of_prog = 2
+
+@< Glob... @>=
+@!state: begin_prog..out_of_prog;
+
+@ % sect. 52
+@< Set init... @>=
+state := out_of_prog;
+
+
+@ % sect. 53
+After we have read the introducing line for a program part
+which is signaled with |state=begin_prog| we change the
+state to |inner_prog| to start copy the next line;
+
+@< Copy all program... @>=
+begin get_line;
+while not input_has_ended do
+ begin @< Look at the input line and store in |state| the result @>;
+ if state = inner_prog then put_line
+ else if state = begin_prog then state := inner_prog;
+ get_line;
+ end;
+if state = inner_prog then err_print('! Input has ended prematurely');
+@.Input has ended...@>
+end
+
+
+@ % sect. 54
+We first define a few macros to improve the readability of
+the program part behind. After \.{\\beginprog} no letters
+may appear and after \.{\\endprog} either the line is ended
+or white space is to be there. The comparison is facilitated
+by the fact that |buffer[limit]=" "|, i.e.\ the last
+character of a line is always a space.
+
+@d cmp_prog(#) == (buffer[#]="p") and (buffer[#+1]="r") and
+ (buffer[#+2]="o") and (buffer[#+3]="g")
+@d cmp_begin == (buffer[1]="b") and (buffer[2]="e") and (buffer[3]="g") and@|
+ (buffer[4]="i") and (buffer[5]="n") and cmp_prog(6) and@|
+ ((buffer[10]<"A") or (buffer[10]>"Z")) and@|
+ ((buffer[10]<"a") or (buffer[10]>"z"))
+@d cmp_end == (buffer[1]="e") and (buffer[2]="n") and (buffer[3]="d") and
+ cmp_prog(4) and @|
+ ((buffer[8]=" ") or (buffer[8]=tab_mark))
+
+@< Look at the input... @>=
+begin
+if buffer[0] = "\" then
+ if limit >= 10 then
+ begin @+ if cmp_begin then state := begin_prog; @+ end
+ else if limit >= 8 then
+ if cmp_end then state := out_of_prog;
+end
+
+
+@ % sect. 55
+Some implementations may wish to pass the |history| value to the
+operating system so that it can be used to govern whether or not other
+programs are started. Here we simply report the history to the user.
+@^system dependencies@>
+
+@<Print the job |history|@>=
+case history of
+spotless: print_nl('(No errors were found.)');
+harmless_message: print_nl('(Did you see the warning message above?)');
+error_message: print_nl('(Pardon me, but I think I spotted something wrong.)');
+fatal_message: print_nl('(That was a fatal error, my friend.)');
+end {there are no other cases}
+
+
+
+
+
+@* System-dependent changes. % sect. 56
+
+\noindent This module should be replaced, if necessary, by
+changes to the program that are necessary to make
+\MAKEPROG{} work at a particular installation. It is
+usually best to design your change file so that all changes
+to previous modules preserve the module numbering; then
+everybody's version will be consistent with the printed
+program. More extensive changes, which introduce new
+modules, can be inserted here; then only the index itself
+will get a new module number.
+@^system dependencies@>
+
+
+
+
+
+@* Index. % sect. 57
+
+\noindent Here is a cross-reference table for the
+\MAKEPROG{} processor. All modules in which an identifier
+is used are listed with that identifier, except that
+reserved words are indexed only when they appear in format
+definitions, and the appearances of identifiers in module
+names are not indexed. Underlined entries correspond to
+where the identifier was declared. Error messages and a few
+other things like ``system dependencies'' are indexed here
+too.
+
diff --git a/support/makeprog/src/progdoc.doc b/support/makeprog/src/progdoc.doc
new file mode 100644
index 0000000000..d85bd0ca9c
--- /dev/null
+++ b/support/makeprog/src/progdoc.doc
@@ -0,0 +1,668 @@
+% progdoc.doc 21 Sep 90
+%------------------------------------------------------------
+% (c) 1988-1990 by J.Schrod. Copyright conditions see below.
+
+%
+% Macro package for the documentation of programs (and TeX macros)
+% MAKEPROG is needed
+%
+
+%
+% VERSION HISTORY (MSCF -- most significant change first)
+%
+% DATE WHO REMARK
+% 90-09-21 js table of contents and headline added.
+% 89-09-08 js repaired initialization of \char_count.
+% 89-06-30 js Definition of \beginverbatim/\endverbatim.
+% 88-12-05 js first version (for ftp/Bitnet).
+
+% bug reports to:
+%
+% Detig$\,\cdot\,$Schrod \TeX{}sys
+% Joachim Schrod
+% Kranichweg 1
+%
+% D-6074 R\"odermark-Urberach
+% FR Germany
+%
+% Tel. (+6074) 1617
+% Bitnet: XITIJSCH@DDATHD21
+
+% author:
+% js: Joachim Schrod <xitijsch@ddathd21.bitnet>
+% contributors:
+% (-: place enough for your name! :-)
+
+
+% documented with itself...
+\input progdoc
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% local macros
+%
+
+\font\mc=cmr9 % for names like ASCII
+\font\sc=cmcsc10 % caps and small caps 10pt
+
+\def\WEB{{\tt WEB\/}}
+\def\LaTeX{{\rm L\kern-.36em\raise.3ex\hbox{\sc a}\kern-.15em\TeX}}
+\def\GNU{{\mc GNU}}
+
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
+
+\title{{\tt progdoc} --- A {\tt WEB\/}-like Markup}
+
+
+
+
+
+\chap Introduction.
+
+\WEB{} systems allow the documentation of programs by supporting the
+separation in program fragments which can be collected and rearranged
+afterwards. This allows {\it top-down\/} programming as well as the
+{\it bottom-up\/} design of programs. Each program fragment can be
+documented, usually with \TeX{}. The creation of a new \WEB{} system
+has become easy with the introduction of Spider \WEB{} but even within
+Spider \WEB{} the lexical analysis is bound to languages of the Algol
+family. Building up \WEB{} systems for languages which are line
+oriented or even for ``exotic'' programming languages like \TeX{}
+(with a dynamic lexical, syntactical and semantical structure) remains
+to be difficult.
+
+This macro package was built to allow good documentation for programs
+in languages for which \WEB{} does not exist. It separates a program
+text in sections that can be documented. All sections, collected
+sequentially, will result in the complete program. In each section
+begin and end of the program part are marked with |\beginprog| and
+|\endprog|, this program part will be formatted as is input
+(``verbatim'').
+
+The separation of the sections is done in this version (which is
+based on Plain~\TeX{}) by the macros |\chap| and |\sect|. In the
+documentation part of a section text pieces, e.g.\ names of
+variables, can be inserted verbatim to demonstrate the connection to
+the program text. These parts are included in vertical bars
+(`{\tt\vbar}') while the vertical bar itself can be obtained by
+|\origvert|. Longer text parts can be printed verbatim by enclosing
+them in |\beginverbatim| and |\endverbatim| which behaves like
+|\beginprog| and |\endprog| except that the text between is not
+copied to the program file.
+
+This macro package does not offer the creation of an index because it
+is not known which syntactical tokens the language has that should be
+mentioned in an index. As well the creation of a table of contents
+and of headings would be preferable to allow better orientation in the
+document. Some remarks about future enhancements which should be done
+urgently are set in slanted type.
+
+
+\sect This program is free software; you can redistribute it and/or
+modify it under the terms of the \GNU{} General Public License as
+published by the Free Software Foundation; either version~1, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+{\bf without any warranty\/}; without even the implied warranty of
+{\bf merchantability\/} or {\bf fitness for a particular purpose}. See
+the \GNU{} General Public License for more details.
+
+You should have received a copy of the \GNU{} General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 675~Mass Ave, Cambridge, MA~02139, USA.
+
+
+\sect We have to realize three parts: (1)~the formatting of rather
+small verbatim texts in a line, (2)~the formatting of larger parts of
+program and (3)~the document structuring elements for the separation
+of the sections.
+
+But before we start we declare some shorthands for category codes. By
+declaring the at sign~(`|@|') as well as the underscore~`(|_|)' as
+letters we can use them in our macros. (I agree with D.~Knuth that
+|\identifier_several_words_long| is more readable than
+|\IdentifierSeveralWordsLong| and in every case better than |\p@@@s|.)
+With the at sign we can use the ``private'' Plain macros and with the
+underscore we can make our own macros more readable. But as we have
+to restore these category codes at the end of this macro file we store
+their former values in the control sequences |\atcode| and |\uscode|.
+This method is better than to use a group because not all macros have
+to be defined global this way.
+
+\beginprog
+\chardef\escape=0
+\chardef\subscript=8
+\chardef\letter=11
+\chardef\other=12
+%\chardef\active=13 % is defined in Plain already
+
+\chardef\atcode=\catcode`\@
+\chardef\uscode=\catcode`\_
+
+\catcode`\@=\letter
+\catcode`\_=\letter
+\endprog
+
+
+
+
+\chap Local Verbatim Formatting.
+
+The main point of every verbatim formatting is the switching of the
+character codes of all characters that have a special meaning for
+\TeX{}. This can be done with the control sequence |\dospecials| that
+applies the control sequence |\do| to all special characters.
+Additionally, every line is regarded as a paragraph without
+indentation. Between two paragraphs, i.e.\ between two lines, no
+extra space is set. Finally all blanks and tab characters shall be
+obeyed and the inter word space after sentence terminators shall not
+be enlarged. The activation of the tab character expansion with
+|\obeytabs| is analog to |\obeyspaces| in {\tt plain.tex\/}.
+
+Verbatim texts are set in monospace, we use (like in \WEB{}) the
+character set with the extended {\mc ASCII}.
+
+\beginprog
+\font\tentex=cmtex10 % typewriter extended ASCII 10pt
+\let\ttex=\tentex % only for PLAIN with base size 10pt
+
+\def\setup_verbatim{%
+ \def\do##1{\catcode`##1\other}\dospecials
+ \parskip\z@skip \parindent\z@
+ \obeylines \obeyspaces \obeytabs \frenchspacing
+ \ttex
+ }
+
+\let\tab=\space
+\begingroup
+ \catcode`\^^I=\active% % Attention: no tabs!
+ \gdef\obeytabs{\catcode`\^^I=\active\def^^I{\tab}}
+ \global\let^^I=\tab% % if an active tab appears in a \write
+\endgroup
+\endprog
+
+\sect After having saved the old meaning of `{\tt\vbar}' in
+|\origvert| and after declaring |\vbar| as a synonym for the character
+that has the code of a vertical bar in the current font, the vertical
+bar can be made active. Then we call |\setup_verbatim|. But the
+newline characters shall not be processed, they shall be treated as
+blank space. This can be done by defining |\par| as |\space|.
+
+The next vertical bar in the input closes the group which becomes an
+(unbreakable) |\hbox| then. The old meanings of the special
+characters and of the vertical bar are restored and \TeX{} is in
+normal (horizontal) mode again.
+
+\beginprog
+\let\origvert=|
+\chardef\vbar=`\|
+
+\catcode`\|=\active
+
+\def|{%
+ \leavevmode
+ \hbox\bgroup
+ \let\par\space \setup_verbatim
+ \let|\egroup
+ }
+\endprog
+
+
+
+
+\chap Program Fragments in Verbatim.
+
+We need macros to format the program fragments without any
+linebreaking. Such a text area shall start with the macro
+|\beginprog| resp.\ |\beginverbatim| and end with |\endprog|
+resp.\ |\endverbatim|. The end macros must stand
+at the very beginning of a line and must be followed by white space
+(blank, tab or newline character). After all these macros
+the rest of the line is ignored.
+
+Two demands must be regarded: There should be no length restrictions
+for the processed text, and the tab characters should be expanded
+so that this macro works on PC's and on VAXes, too.
+
+
+\sect The implementation method is quite simple: We read the next
+line, test, wether the end is reached (by comparing with the end line)
+and otherwise set the line actually read. Every character is
+inspected and tabular characters are expanded.
+
+The verbatim text is started with |\begin_verbatim| which will be
+either called by |\beginprog| or by |\beginverbatim|. These macros
+will also define the contents of the end line.
+
+Whether a line is set or whether the end of the processed area is
+reached is indicated by the switch |\if@print|. At the beginning of
+the |\begin_verbatim| macro most settings are done with
+|\setup_verbatim| (the vertical bar must be handled separately)
+and the rest of the line is ignored. As everything is done within
+a group, the end of the verbatim text can be processed by simply
+closing this group.
+
+For the user it looks as if |\endprog| or |\endverbatim|
+terminates the processing, but
+it just serves for the identification of the end, the true processing
+is done with the internal macro |\end_verbatim|.
+
+\beginprog
+\newif\if@print
+
+\def\begin_verbatim{%
+ \endgraf
+ \bigbreak
+ \begingroup
+ \setup_verbatim \catcode`\|\other
+ \@printtrue
+ \ignore_rest_line
+ }
+\let\end_verbatim=\endgroup % internal command !
+\endprog
+
+
+\sect The first line is ignored, all the other lines are identified
+with |\set_next_line| and processed with |\do_set|. This separation
+in identification and processing allows that the line end character is
+active in the definition only for a short time.
+
+When a line is to be formatted, we first check with |\check_print|
+whether it contains |\endprog|, otherwise it is printed with
+|\print_char|. The printing must be done for every character
+individually because we want to check for tab characters; the
+exact algorithm is described below. Here we just have to note that
+|\print_char| is used with two parameters of which the second one is
+terminated with the token |\end_line|. The first parameter is the first
+character of the line, the second parameter is the rest of the line.
+If the line is empty, the argument of |\do_set| is empty, too; so the
+activation of |\print_char| must be finished with two |\end_line|.
+Then the first |\end_line| is the first argument for |\print_char| and
+the second argument is empty. But if the line did contain something,
+the second |\end_line| is evaluated, for this case it is defined as
+|\relax|.
+
+Finally we call |\set_next_line| again to format the next line. If
+the end is reached, i.e.\ if a line with |\endprog| was found,
+|\set_next_line| is redefined as |\relax|. This can be done because
+the original meaning is restored when the group is closed by
+|\end_verbatim|.
+
+\beginprog
+\begingroup
+ \obeylines% % ^^M is active! ==> every line must end with %
+ \gdef\ignore_rest_line#1^^M{\set_next_line}%
+ \gdef\set_next_line#1^^M{\do_set{#1}}%
+\endgroup
+
+\def\do_set#1{%
+ \endgraf
+ \check_print{#1}%
+ \if@print \indent \print_char#1\end_line\end_line
+ \else \let\set_next_line\end_verbatim
+ \fi
+ \set_next_line
+ }
+\let\end_line=\relax
+\endprog
+
+
+\sect Before we attack the problem of formatting a line, we declare
+|\check_print| that checks the end of the verbatim mode. We have to
+do two things: we must split everything in front of the first blank
+or tab character and compare it with |\endprog|. The splitting is easy
+because the line which is our first argument contains blanks and
+tabulators as active characters. First we call |\cut_at_tab| that
+demands a tab character as separator for its two parameters so that
+everything in the line in front of the first tabulator is part of the
+first parameter. If there is no tab character in the line, we append
+one so that the second parameter is empty. The same trick is used to
+separate the part in front of the first blank character from the
+resulting first part.
+
+The check is done with |\do_check|. We use a separate macro here so
+that we can indent it (in the following definition blanks are active!)
+
+\beginprog
+\begingroup
+\obeyspaces\obeytabs
+\gdef\check_print#1{\cut_at_tab#1^^I\end_line}
+\gdef\cut_at_tab#1^^I#2\end_line{\check_first_part#1 \end_line}% blank !
+\gdef\check_first_part#1 #2\end_line{\do_check{#1}}
+\endgroup
+\endprog
+
+
+\sect |\do_check| compares the line with a sample line that is
+available in |\end_verbatim_line|. This macro will be defined later.
+
+\beginprog
+\def\do_check#1{%
+ \def\@line{#1}%
+ \ifx \@line\end_verbatim_line \@printfalse
+ \fi
+ }
+\endprog
+
+
+\sect Now we can set a line: we start with the first character,
+followed by the rest of the line. Each character is counted in
+|\char_count|. At the beginning of a line |\char_count| is~0, it
+is reset at the end of the line.
+
+\beginprog
+\newcount\char_count \char_count\z@
+
+\def\print_char#1#2\end_line{%
+ \print_first_char{#1}%
+ \print_rest_of_line{#2}%
+ }
+\endprog
+
+
+\sect For each character that is set |\char_count| is incremented.
+If a character is a tabulator, we set with |\print_tab| the required
+amount of blank characters, otherwise the character itself. We must
+compare the character that is stored in |\@char| with a macro whose
+``first-level'' expansion is an active tabulator. For this case we
+declare |\@tab|.
+
+\beginprog
+{\obeytabs\gdef\@tab{^^I}}
+
+\def\print_first_char#1{%
+ \def\@char{#1}%
+ \advance \char_count\@ne
+ \ifx \@char\@tab \print_tab
+ \else \@char
+ \fi
+ }
+\endprog
+
+
+\sect If we want to fill the line with blank spaces up to the next
+column with a number that can be divided by~8, we must be able to
+compute the column number modulo~8, but \TeX{} has no modulo operator.
+So we define the macro |\mod_viii| that computes its argument modulo~8
+and returns the result in the counter |\count_mod_viii|. For the
+computation we use the temporary counter |\count@|.
+
+\beginprog
+\newcount\count_mod_viii
+\def\mod_viii#1{%
+ \count@ #1\relax \count_mod_viii\count@
+ \divide \count@ 8\relax
+ \multiply \count@ 8\relax
+ \advance \count_mod_viii -\count@
+ }
+\endprog
+
+
+\sect Now we can declare |\print_tab|. We must remember that
+|\char_count| was incremented already, if we set only one blank
+character the counter keeps untouched.
+
+\beginprog
+\def\print_tab{%
+ \loop \space \mod_viii\char_count
+ \ifnum \count_mod_viii>\z@
+ \advance \char_count\@ne
+ \repeat
+ }
+\endprog
+
+
+\sect If the rest of the line is empty, we have finished the task.
+|\char_count| is reset to~0 for the next line.
+
+Inside the |\else| part of |\ifx| |\print_char| should not be used
+directly because this costs too much storage of \TeX{}. Instead we
+set a control sequence |\next| that is processed afterwards, depending
+on the result of the comparison. If there is still something to set,
+we use |\print_char| again, otherwise a syntactically similar macro
+that expands to |\relax|.
+
+\beginprog
+\def\print_rest_of_line#1{%
+ \def\@line{#1}%
+ \ifx \@line\empty \char_count\z@
+ \def\next##1\end_line{\relax}%
+ \else \let\next\print_char
+ \fi
+ \next#1\end_line
+ }
+\endprog
+
+
+\sect Now we are ready to define the two ``user accessible'' macros
+|\beginprog| and |\beginverbatim|. They must define the prototyp end
+line |\end_verbatim_line| which will be compared against every line
+in the verbatim text. During the definition of
+|\end_verbatim_line| it must be cared for that the escape character~`|\|'
+is a printable character: A comparison with |\ifx| demands identical
+category codes. As a temporary escape character we use the slash.
+
+\beginprog
+{\catcode`\/=\escape \catcode`\\=\other % / is temporary escape char
+ /gdef/beginprog{%
+ /gdef/end_verbatim_line{\endprog}%
+ /begin_verbatim
+ }
+ /gdef/beginverbatim{%
+ /gdef/end_verbatim_line{\endverbatim}%
+ /begin_verbatim
+ }
+} % here \endgroup can't be used
+\endprog
+
+
+
+
+\chap Document Structuring.
+
+The layout of the document shall be like in \WEB{}; this can be done
+easily in Plain. A document -- which may have a title -- consists of
+sections which are numbered. We distinguish between main sections
+which start a group of sections and between normal sections within a
+group. Main sections have a title, a table of contents with all
+titles is output at the end.
+
+
+\sect The number of the current section is stored in the counter
+|\sectno|.
+
+\beginprog
+\newcount\sectno \sectno=\@ne
+
+\newtoks\title \title{}
+\endprog
+
+
+\sect As usual, the name |\toc_file_name| of the table of contents
+file |\toc_file| is built from the jobname and the extension |toc|.
+We open the file and output a |\relax| so we are save that something
+is in the file and it can be read in later without any difficulties.
+
+In this file lines are written with the main section numbers, their
+titles, and their page numbers, respectively. Every line is marked
+with |\tocline| which is assumed to have the given three parameters.
+Now we define |\tocline| to be |\relax| so that |\write| does not
+expand it.
+
+\beginprog
+\def\toc_file_name{\jobname.toc } % <--- Space!!
+\newwrite\toc_file
+
+\immediate\openout\toc_file=\toc_file_name
+\immediate\write\toc_file{\relax}
+
+\let\tocline=\relax
+\endprog
+
+
+\sect We want a headline with the current section number, the
+document title, the last main section title, and the page number. The
+footline is empty.
+
+To realize this headline every section must |\mark| it's section
+number {\it in front of\/} a potentiel page break (so the number may
+be accessed by |\topmark|) and every main section must define
+|\main_title| to be it's title.
+
+\beginprog
+\headline{%
+ \tenrm
+ \S\topmark \qquad \the\title
+ \hfil
+ \main_title \qquad \tenrm \folio
+ }
+\footline{\hfil}
+\endprog
+
+
+\sect But this does not work the way it should: On the first page
+|\topmark| will be always empty! Here we borrow a trick from
+|webmac.tex|, we insert a first garbage page which will be discarded
+by the output routine.
+
+\beginprog
+\vbox to \vsize{}
+
+\output={%
+ \setbox\z@ \vbox{\unvbox\@cclv}% % throw away the first page
+ \global\output{\plainoutput}% % restore Plain output routine
+ }
+\endprog
+
+
+\sect The main sections are started with the macro |\chap|. It has
+one parameter, the title of the section group. This parameter must
+be terminated by a dot. We start a new page, typeset the title in
+bold face and separate it from the section text with a |\medskip|.
+This text, the first paragraph of the documentation part of the
+section, is formatted without paragraph indentation.
+
+At the beginning of the new page we output the section number, the
+title, and the page number to the contents file. We must take care to
+expand the section number right now because it will be incremented
+and would not be the correct value during the output routine.
+
+The deletion of the paragraph indentation is done with |\everypar|.
+We do not care if |\everypar| is used for something else and delete it
+after usage.
+
+\beginprog
+\def\chap#1.{%
+ \endgraf
+ \mark{\number\sectno}% % gather information for headline
+ \vfill\supereject
+ \begingroup
+ \def\protect##1{\string ##1 }% % <--- Space!!
+ \edef\write_toc_sectno{\write\toc_file{\tocline{\number\sectno}}}%
+ \write_toc_sectno
+ \write\toc_file{{#1}{\folio}}%
+ \endgroup
+ \gdef\main_title{#1}% % more information for headline
+ \noindent {\bf \number\sectno.\quad #1.}%
+ \global\advance \sectno\@ne
+ \endgraf
+ \medskip \nobreak
+ \everypar{% % remove next parindent
+ \setbox0\lastbox
+ \global\everypar{}%
+ }%
+ }
+\endprog
+
+
+\sect Normal sections are started with |\sect|. This macro has no
+parameter. Between two paragraphs we set 2~pica space (if possible)
+and prefer the page breaking. Between the section number and the text
+one quad of space is set.
+
+\begingroup \sl
+The page break manipulation should be more sophisticated.
+\endgroup
+
+\beginprog
+\def\sect{%
+ \endgraf
+ \mark{\number\sectno}% % gather information for headline
+ \vskip 2pc plus 1pc minus 6dd \goodbreak
+ \noindent {\bf \number\sectno.}\quad \ignorespaces
+ \global\advance \sectno\@ne
+ }
+\endprog
+
+
+\sect At the end we add a page with the table of contents. This is
+triggered by |\bye|. If the user does not want this table he may use
+|\byebye|.
+
+\beginprog
+\def\byebye{\par\vfil\supereject\end} % original definition of \bye
+\def\bye{%
+ \endgraf
+ \vfill \supereject
+ \immediate\closeout\toc_file
+ \message{Table of contents:}%
+ \leftskip\z@skip \rightskip\z@skip
+ \parskip\z@skip \parindent\z@ \parfillskip\z@skip
+ \normalbaselines
+ \headline{\hfil}%
+ \footline{\hfil \folio \hfil}%
+ \def\HeaderToc{\rightline{Section\hbox to\thr@@ em{\hss Page}}}%
+ \def\tocline##1##2##3{%
+ \line{%
+ \ignorespaces ##2%
+ \leaders\hbox to .5em{.\hfil}\hfil
+ \ ##1%
+ \hbox to \thr@@ em{\hss ##3}%
+ }%
+ }
+ \pageno\m@ne % table of contents gets roman page numbers
+ \topofcontents % may redefine \HeaderToc and \tocline!
+ \HeaderToc
+ \catcode`\@\letter % @ and _ are letters (for reading private macros)
+ \catcode`\_\letter
+ \input \toc_file_name
+ \catcode`\@\atcode % @ and _ are no more letters
+ \catcode`\_\uscode
+ \botofcontents
+ \byebye % print the contents page(s) and terminate
+ }
+
+\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\def\topofcontents{
+ \null \vfill
+ \centerline{\let\tt\ttitlefont \titlefont \the\title}
+ \vskip 1cm
+ }
+\def\botofcontents{
+ \vfill\vfill
+ }
+\endprog
+
+
+\sect We are finished and just have to restore the category codes.
+
+\beginprog
+\catcode`\@=\atcode
+\catcode`\_=\uscode
+
+\endinput
+\endprog
+
+
+
+
+
+\bye
+
diff --git a/support/makeprog/src/progdoc.tex b/support/makeprog/src/progdoc.tex
new file mode 100644
index 0000000000..da52668952
--- /dev/null
+++ b/support/makeprog/src/progdoc.tex
@@ -0,0 +1,217 @@
+\chardef\escape=0
+\chardef\subscript=8
+\chardef\letter=11
+\chardef\other=12
+%\chardef\active=13 % is defined in Plain already
+
+\chardef\atcode=\catcode`\@
+\chardef\uscode=\catcode`\_
+
+\catcode`\@=\letter
+\catcode`\_=\letter
+\font\tentex=cmtex10 % typewriter extended ASCII 10pt
+\let\ttex=\tentex % only for PLAIN with base size 10pt
+
+\def\setup_verbatim{%
+ \def\do##1{\catcode`##1\other}\dospecials
+ \parskip\z@skip \parindent\z@
+ \obeylines \obeyspaces \obeytabs \frenchspacing
+ \ttex
+ }
+
+\let\tab=\space
+\begingroup
+ \catcode`\^^I=\active% % Attention: no tabs!
+ \gdef\obeytabs{\catcode`\^^I=\active\def^^I{\tab}}
+ \global\let^^I=\tab% % if an active tab appears in a \write
+\endgroup
+\let\origvert=|
+\chardef\vbar=`\|
+
+\catcode`\|=\active
+
+\def|{%
+ \leavevmode
+ \hbox\bgroup
+ \let\par\space \setup_verbatim
+ \let|\egroup
+ }
+\newif\if@print
+
+\def\begin_verbatim{%
+ \endgraf
+ \bigbreak
+ \begingroup
+ \setup_verbatim \catcode`\|\other
+ \@printtrue
+ \ignore_rest_line
+ }
+\let\end_verbatim=\endgroup % internal command !
+\begingroup
+ \obeylines% % ^^M is active! ==> every line must end with %
+ \gdef\ignore_rest_line#1^^M{\set_next_line}%
+ \gdef\set_next_line#1^^M{\do_set{#1}}%
+\endgroup
+
+\def\do_set#1{%
+ \endgraf
+ \check_print{#1}%
+ \if@print \indent \print_char#1\end_line\end_line
+ \else \let\set_next_line\end_verbatim
+ \fi
+ \set_next_line
+ }
+\let\end_line=\relax
+\begingroup
+\obeyspaces\obeytabs
+\gdef\check_print#1{\cut_at_tab#1^^I\end_line}
+\gdef\cut_at_tab#1^^I#2\end_line{\check_first_part#1 \end_line}% blank !
+\gdef\check_first_part#1 #2\end_line{\do_check{#1}}
+\endgroup
+\def\do_check#1{%
+ \def\@line{#1}%
+ \ifx \@line\end_verbatim_line \@printfalse
+ \fi
+ }
+\newcount\char_count \char_count\z@
+
+\def\print_char#1#2\end_line{%
+ \print_first_char{#1}%
+ \print_rest_of_line{#2}%
+ }
+{\obeytabs\gdef\@tab{^^I}}
+
+\def\print_first_char#1{%
+ \def\@char{#1}%
+ \advance \char_count\@ne
+ \ifx \@char\@tab \print_tab
+ \else \@char
+ \fi
+ }
+\newcount\count_mod_viii
+\def\mod_viii#1{%
+ \count@ #1\relax \count_mod_viii\count@
+ \divide \count@ 8\relax
+ \multiply \count@ 8\relax
+ \advance \count_mod_viii -\count@
+ }
+\def\print_tab{%
+ \loop \space \mod_viii\char_count
+ \ifnum \count_mod_viii>\z@
+ \advance \char_count\@ne
+ \repeat
+ }
+\def\print_rest_of_line#1{%
+ \def\@line{#1}%
+ \ifx \@line\empty \char_count\z@
+ \def\next##1\end_line{\relax}%
+ \else \let\next\print_char
+ \fi
+ \next#1\end_line
+ }
+{\catcode`\/=\escape \catcode`\\=\other % / is temporary escape char
+ /gdef/beginprog{%
+ /gdef/end_verbatim_line{\endprog}%
+ /begin_verbatim
+ }
+ /gdef/beginverbatim{%
+ /gdef/end_verbatim_line{\endverbatim}%
+ /begin_verbatim
+ }
+} % here \endgroup can't be used
+\newcount\sectno \sectno=\@ne
+
+\newtoks\title \title{}
+\def\toc_file_name{\jobname.toc } % <--- Space!!
+\newwrite\toc_file
+
+\immediate\openout\toc_file=\toc_file_name
+\immediate\write\toc_file{\relax}
+
+\let\tocline=\relax
+\headline{%
+ \tenrm
+ \S\topmark \qquad \the\title
+ \hfil
+ \main_title \qquad \tenrm \folio
+ }
+\footline{\hfil}
+\vbox to \vsize{}
+
+\output={%
+ \setbox\z@ \vbox{\unvbox\@cclv}% % throw away the first page
+ \global\output{\plainoutput}% % restore Plain output routine
+ }
+\def\chap#1.{%
+ \endgraf
+ \mark{\number\sectno}% % gather information for headline
+ \vfill\supereject
+ \begingroup
+ \def\protect##1{\string ##1 }% % <--- Space!!
+ \edef\write_toc_sectno{\write\toc_file{\tocline{\number\sectno}}}%
+ \write_toc_sectno
+ \write\toc_file{{#1}{\folio}}%
+ \endgroup
+ \gdef\main_title{#1}% % more information for headline
+ \noindent {\bf \number\sectno.\quad #1.}%
+ \global\advance \sectno\@ne
+ \endgraf
+ \medskip \nobreak
+ \everypar{% % remove next parindent
+ \setbox0\lastbox
+ \global\everypar{}%
+ }%
+ }
+\def\sect{%
+ \endgraf
+ \mark{\number\sectno}% % gather information for headline
+ \vskip 2pc plus 1pc minus 6dd \goodbreak
+ \noindent {\bf \number\sectno.}\quad \ignorespaces
+ \global\advance \sectno\@ne
+ }
+\def\byebye{\par\vfil\supereject\end} % original definition of \bye
+\def\bye{%
+ \endgraf
+ \vfill \supereject
+ \immediate\closeout\toc_file
+ \message{Table of contents:}%
+ \leftskip\z@skip \rightskip\z@skip
+ \parskip\z@skip \parindent\z@ \parfillskip\z@skip
+ \normalbaselines
+ \headline{\hfil}%
+ \footline{\hfil \folio \hfil}%
+ \def\HeaderToc{\rightline{Section\hbox to\thr@@ em{\hss Page}}}%
+ \def\tocline##1##2##3{%
+ \line{%
+ \ignorespaces ##2%
+ \leaders\hbox to .5em{.\hfil}\hfil
+ \ ##1%
+ \hbox to \thr@@ em{\hss ##3}%
+ }%
+ }
+ \pageno\m@ne % table of contents gets roman page numbers
+ \topofcontents % may redefine \HeaderToc and \tocline!
+ \HeaderToc
+ \catcode`\@\letter % @ and _ are letters (for reading private macros)
+ \catcode`\_\letter
+ \input \toc_file_name
+ \catcode`\@\atcode % @ and _ are no more letters
+ \catcode`\_\uscode
+ \botofcontents
+ \byebye % print the contents page(s) and terminate
+ }
+
+\font\titlefont=cmr7 scaled\magstep4 % title on the contents page
+\font\ttitlefont=cmtt10 scaled\magstep2 % typewriter type in title
+\def\topofcontents{
+ \null \vfill
+ \centerline{\let\tt\ttitlefont \titlefont \the\title}
+ \vskip 1cm
+ }
+\def\botofcontents{
+ \vfill\vfill
+ }
+\catcode`\@=\atcode
+\catcode`\_=\uscode
+
+\endinput
diff --git a/support/makeprog/src/progltx.doc b/support/makeprog/src/progltx.doc
new file mode 100644
index 0000000000..fdc6047699
--- /dev/null
+++ b/support/makeprog/src/progltx.doc
@@ -0,0 +1,739 @@
+% This is PROGLTX.DOC as of 25 May 90
+%---------------------------------------------------------
+% (c) 1989,1990 by J.Schrod. copy conditions see below
+
+%
+% Macro package for the documentation of programs
+% LaTeX style option
+% MAKEPROG is needed
+%
+
+%
+% DATE PERSON REMARK
+% 89-11-18 js repaired the handling of `|' (verbatim and \index).
+% 89-10-05 js first version (for TeX89)
+%
+
+% author's current address:
+%
+% Detig$\,\cdot\,$Schrod \TeX{}sys
+% Joachim Schrod
+% Kranichweg 1
+%
+% D-6074 R\"odermark-Urberach
+% FR Germany
+%
+% Tel. (+6074) 1617
+% Bitnet: XITIJSCH@DDATHD21
+
+
+
+% documented with itself...
+\documentstyle[progltx]{article}
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% local macros
+%
+
+\let\mc=\small % for names like GNU
+
+\def\WEB{{\tt WEB\/}}
+\def\GNU{{\mc GNU}}
+
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+\begin{document}
+
+
+\title{
+ Documenting programs in a \WEB{} style\\
+ The {\tt progltx\/} style option
+ }
+\author{\sc Joachim Schrod}
+
+\maketitle
+
+
+\chap Introduction.
+
+\WEB{} systems allow the documentation of programs by supporting the
+separation in program fragments which can be collected and rearranged
+afterwards. This allows {\it top-down\/} programming as well as the
+{\it bottom-up\/} design of programs. Each program fragment can be
+documented, usually with \TeX{}\@. A disadvantadge is that \WEB{}
+actually exists only for a few programming languages (Pascal, C,
+Modula-2). Besides, building up \WEB{} systems for ``exotic''
+programming languages like \TeX{} is very difficult.
+
+This macro package was built to allow good documentation for programs
+in languages for which \WEB{} doesn't exist. It separates a program
+text in sections that can be documented. All sections, collected
+sequentially, will result in the complete program. In every section
+begin and end of the program part are marked with |\beginprog| and
+|\endprog|, this program part will be formatted as it is input
+(``verbatim'').
+
+Originally these macros were written for the usage with Plain \TeX{}
+resp.\ on top of the \WEB{} macro package |webmac.tex|. But often the
+requirement has been told to me that a \LaTeX{} version would be
+useful, too---well, here it is. But even with \LaTeX{} I have decided
+that still |\beginprog| and |\endprog| must be used for the markup of
+the program parts, not |\begin{prog}| or |\end{prog}| which would be
+more ``\LaTeX{}-like.'' The reason behind this is that I didn't want
+to maintain two versions of the {\mc MAKEPROG\/} processor---but {\mc
+MAKEPROG\/} wants to see the non-\LaTeX{}-like macros. But everybody
+is encouraged to change it by themselves (it is {\it very\/} easy).
+
+The user of these macros may use the usual sectioning macros of
+\LaTeX{} for structuring his documentation. Additionally we provide a
+|progdoc|-compatible (i.e.\ \WEB{}-like) markup with the two macros
+|\chap| and |\sect|.
+
+In the documentation part of a section text pieces, e.g.\ names of
+variables, can be inserted verbatim to demonstrate the connection to
+the program text. These parts are included in vertical bars
+(`{\tt\vbar}') This makes this style option extremely useful if your
+identifiers (or your file names) include characters which would be
+special characters for \TeX{} otherwise. (One example of these
+program languages is \TeX{} itself, but just enclose the macro names
+in vertical bars and {\tt \vbar|\relax|\vbar}.)
+
+The macros |\makevertother| and |\makevertactive| are available to
+activate and deactivate the special behaviour of the vertical bar but
+these macros should be needed seldom because the usual cases as the
+usage within |verbatim| and |tabular| environments or |\index| macros
+etc.\ are handled.
+
+If a vertical bar must be used in the original fashion you can use two
+command sequences: |\origvert| holds the meaning of the vertical bar
+at the time this macro file was read in and |\vbar| is the character
+with the {\mc ASCII\/} code of the vertical bar (i.e.~|"EC|) in the
+current font.
+
+The new notion of |\verb| must not be used within parameters of
+macros, e.g.\ in the argument of |\section| etc.---it will result in
+an error message by \TeX{}\@. Furthermore within the preamble of a
+|tabular|, an |array| environment, or the |\multicolumn| command the
+vertical bar has the same meaning as before. (That means within
+|@{|\ldots|}| it is an ordinary character and otherwise it specifies a
+vertical rule between the columns.
+
+This macro package does not offer the automatic creation of an index
+because it is not known which syntactical tokens the language has that
+should be mentioned in an index. But of course all \LaTeX{} stuff like
+|\index|, |\tableofcontents|, etc.\ may be used.
+
+
+\sect This program is free software; you can redistribute it and/or
+modify it under the terms of the \GNU{} General Public License as
+published by the Free Software Foundation; either version~1, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+{\bf without any warranty\/}; without even the implied warranty of
+{\bf merchantability\/} or {\bf fitness for a particular purpose}. See
+the \GNU{} General Public License for more details.
+
+You should have received a copy of the \GNU{} General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 675~Mass Ave, Cambridge, MA~02139, USA.
+
+
+\sect We have to realize three parts: (1)~the formatting of rather
+small verbatim texts in a line, (2)~the formatting of larger parts of
+program and (3)~the document structuring elements for the separation
+of the sections.
+
+\begin{sloppypar}
+Before we start we declare some shorthands for category codes. By
+declaring the underscore~`(|_|)' as a letter we can use it in our
+macros names. (I agree with D.~Knuth that
+|\identifier_several_words_long| is more readable than
+|\IdentifierSeveralWordsLong| and in every case better than
+|\p@@@s|.) But as we have to restore the category codes at the end
+of this macro file we store its former value in the control
+sequence |\uscode|. This method is better than the usage of a
+group because not all macros have to be defined global this way.
+\end{sloppypar}
+
+\beginprog
+\chardef\escape=0
+\chardef\open=1
+\chardef\close=2
+\chardef\letter=11
+\chardef\other=12
+%\chardef\active=13 % is defined in Plain already
+
+\chardef\uscode=\catcode`\_
+
+\catcode`\_=\letter
+\endprog
+
+
+
+
+\chap Local Verbatim Formatting.
+
+The main point of every verbatim formatting is the switching of the
+character codes of all characters that have a special \TeX{} meaning.
+This can be done with the control sequence |\dospecials| that applies
+the control sequence |\do| to all special characters. Additionally,
+every line is regarded as a paragraph without indentation. Between
+two paragraphs, i.e.\ between two lines, no extra space is set.
+Finally all blanks and tabular characters shall be obeyed and the
+inter word space after sentence terminators shall not be enlarged.
+The activation of the tabular characters with |\obeytabs| is
+equivalent to |\obeyspaces| in {\tt plain.tex}.
+
+\begin{sl}
+As a matter of fact, I would like to use the character set with the
+extended {\mc ASCII} (like in\/ \WEB{}) for setting the verbatim texts
+in monospace. But then I must code many\/ |\@getfont|'s\,\dots
+\end{sl}
+
+\beginprog
+%\font\tentex=cmtex10 % typewriter extended ASCII 10pt
+%\let\ttex=\tentex % only with base size 10pt
+\def\ttex{\tt} % as a substitute
+
+\def\setup_verbatim{%
+ \def\do##1{\catcode`##1\other}\dospecials
+ \parskip\z@skip \parindent\z@
+ \catcode`\`\active \@noligs
+ \obeylines \@vobeyspaces \obeytabs \frenchspacing
+ \ttex
+ }
+
+\let\tab=\space
+\begingroup
+ \catcode`\^^I=\active% % Attention: no tabs!
+ \gdef\obeytabs{\catcode`\^^I=\active\def^^I{\tab}}
+ \global\let^^I=\tab% % if an active tab appears in a \write
+\endgroup
+\endprog
+
+
+\sect After having saved the old meaning of `{\tt\vbar}' in
+|\origvert| and after declaring |\vbar| as a synonym for the character
+that has the code of a vertical bar in the actual font, the vertical
+bar can be made active. Then we call |\setup_verbatim|. But the
+newline characters shall not be processed, they shall be regarded like
+blank space. This can be reached by defining |\par| as |\space|.
+
+The next vertical bar in the input closes the group which becomes an
+(unbreakable) |\hbox| then. The old meanings of the special
+characters and of the vertical bar are restored and \TeX{} is in
+normal (horizontal) mode again.
+
+\beginprog
+\let\origvert=|
+\chardef\vbar=`\|
+
+\def\makebaractive{\catcode`\|\active}
+\def\makebarother{\catcode`\|\other}
+\makebaractive
+
+\def|{%
+ \leavevmode
+ \hbox\bgroup
+ \let\par\space \setup_verbatim
+ \let|\egroup
+ }
+\endprog
+
+
+\sect A problem with this definition of the vertical bar is that
+the bar is not a normal character any more but there exists situations
+where the \LaTeX{} macros assumes this:
+%
+\begin{itemize}
+
+\item In a |verbatim| environment a vertical bar must be typeset if it
+occurs in the input.
+
+\item In a |tabular| or an |array| environment a vertical bar is used
+to denote rules between columns in the table. These environments must
+be started with a parameter which is a ``preamble,'' the same preamble
+construction is used to specify the format of multi-column entries.
+
+\item In an output of an index entry the vertical bar must not result
+in an error message. Usually index entries are typeset in a seperate
+\TeX{} run where |idverb| is not used as a style option and the
+vertical bar is therefore useful. This is no problem in section
+headings or captions etc. Because they take their argument as a
+parameter in every case the vertical bar can never be used there. But
+|\origvert| resp.\ |\vbar| may be used there.
+
+\end{itemize}
+%
+In the next sections we handle each of these problems.
+
+
+\sect Before we start a |verbatim| environment we just redefine the
+vertical bar as an ordinary character. Because this is within the
+environment grouping the end of the environment will reestablish the
+special meaning.
+
+\beginprog
+\let\@@verbatim=\@verbatim
+\def\@verbatim{%
+ \makebarother
+ \@@verbatim
+ }
+\endprog
+
+
+\sect Special care is needed in the |tabular| and the |array|
+environment. Both environments are begun by one macro (|\@tabarray|),
+we redefine it so that the bar can be used in the preamble
+specification. The same problem occurs in |\multicolumn|, it is
+solved the same way. After the preamble construction (with
+|\@mkpream|) the special meaning of the bar can be switched on
+again---this allows the usage of the new meaning in the body of a
+table.
+
+Of course this mean that the ``verbatim identifier'' facility can
+not be used within a preamble of a table. Furthermore it can not
+be used within the |\multicolumn| statement, neither in the
+preamble part (the second parameter) nor within the text part (the
+third parameter).
+
+\beginprog
+\let\@@tabarray=\@tabarray
+\def\@tabarray{%
+ \makebarother
+ \@@tabarray
+ }
+
+\def\multicolumn#1{%
+ \multispan{#1}%
+ \begingroup
+ \makebarother
+ \restof_multicolumn
+ }
+\def\restof_multicolumn#1#2{%
+ \@mkpream{#1}%
+ \def\@sharp{#2}%
+ \let\protect\relax
+ \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
+ \@arstrut \@preamble
+ \endgroup
+ \ignorespaces
+ }
+
+\let\@@mkpream=\@mkpream
+\def\@mkpream#1{%
+ \@@mkpream{#1}%
+ \makebaractive
+ }
+\endprog
+
+
+\sect Before an index entry is scanned almost all special characters
+are transformed into ordinary characters. The only exceptions are the
+opening and the closing brace because they are needed to delimit the
+argument. This transformation is done with |\@sanitize|, this macro
+must be called within a group. We just append the transformation of
+the vertical bar.
+
+\beginprog
+\begingroup
+ \def\@makeother{\noexpand\@makeother\noexpand}
+ \xdef\@sanitize{\@sanitize\@makeother\|}
+\endgroup
+\endprog
+
+
+
+
+\chap Fragments in Verbatim.
+
+We need macros to format the program fragments without any
+linebreaking. Such a text area shall start with the macro
+|\beginprog| and end with |\endprog|, i.e.\ as a kind of a
+|prog|-environment. The macro |\endprog| must stand at the very
+beginning of a line and must be followed by white space (blank, tab or
+newline character). After |\beginprog| as well as after
+|\endprog| the rest of the line is ignored.
+
+Two demands must be regarded: There should be no length restrictions
+for the processed text, and the tabular characters should be expanded
+so that this macro works on PC's and on VAXes etc., too.
+
+
+\sect The implementation method is quite simple: We read the next
+line, test, wether the end is reached (by comparing with the end line)
+and otherwise set the line actually read. Every character is
+inspected and tabular characters are expanded.
+
+The verbatim text is started with |\begin_verbatim| which will be
+either called by |\beginprog| or by |\beginverbatim|. These macros
+will also define the contents of the end line.
+
+Whether a line is set or whether the end of the processed area is
+reached is indicated by the switch |\if@print|. At the beginning of
+the |\begin_verbatim| macro most settings are done with
+|\setup_verbatim| (the vertical bar must be handled separately)
+and the rest of the line is ignored. As everything is done within
+a group, the end of the verbatim text can be processed by simply
+closing this group.
+
+For the user it looks as if |\endprog| or |\endverbatim|
+terminates the processing, but it just serves for the
+identification of the end, the true processing is done with the
+internal macro |\end_verbatim|.
+
+\beginprog
+\newif\if@print
+
+\def\begin_verbatim{%
+ \endgraf
+ \bigbreak
+ \begingroup
+ \setup_verbatim \makebarother
+ \@printtrue
+ \ignore_rest_line
+ }
+\let\end_verbatim=\endgroup % internal command !
+\endprog
+
+
+\sect {\sloppy
+ The first line is ignored, all the other lines are identified with
+|\set_next_line| and processed with |\do_set|. This separation in
+identification and processing allows that the line end character is
+active in the definition only for a short time.
+ \par}
+
+When a line is to be formatted, we first check with |\check_print|
+wether it contains the end line, otherwise it is printed with
+|\print_char|. The printing must be done for every character
+individually because we want to check for tabular characters; the
+exact algorithm is described below. Here we just have to note that
+|\print_char| is used with two parameters of which the second one is
+finished with the token |\end_line|. The first parameter is the first
+character of the line, the second parameter is the rest of the line.
+If the line is empty, the argument of |\do_set| is empty, too; so the
+activation of |\print_char| must be finished with two |\end_line|.
+Then the first |\end_line| is the first argument for |\print_char| and
+the second argument is empty. But if the line did contain something,
+the second |\end_line| is evaluated, for this case it is defined as
+|\relax|.
+
+At last we call |\set_next_line| again to format the next line. If
+the end is reached, i.e.\ if the sample line was found,
+|\set_next_line| will be redefined as |\relax|. This can be done
+because the original meaning is restored while closing the group
+with |\end_verbatim|.
+
+\beginprog
+\begingroup
+ \obeylines% % ^^M is active! ==> every line must end with %
+ \gdef\ignore_rest_line#1^^M{\set_next_line}%
+ \gdef\set_next_line#1^^M{\do_set{#1}}%
+\endgroup
+
+\def\do_set#1{%
+ \endgraf
+ \check_print{#1}%
+ \if@print \indent \print_char#1\end_line\end_line
+ \else \let\set_next_line\end_verbatim
+ \fi
+ \set_next_line
+ }
+\let\end_line=\relax
+\endprog
+
+
+\sect {\sloppy
+ Before we look at the problem of formatting a line, we declare
+|\check_print| that checks the end of the verbatim mode. We have to
+do two things: we must split everything in front of the first blank
+or tabular character and compare for identity with |\endprog|. The
+splitting is easy because the line which is our first argument
+contains blanks and tabulators as active characters. First we call
+|\cut_at_tab| that demands a tabular character as separator for its
+two pramenters so that everything in the line in front of the first
+tabulator is part of the first parameter. If there is no tabular
+character in the line, we append one so that the second parameter is
+empty. The same trick is used to separate the part in front of the
+first blank character from the resulting first part.
+ \par}
+
+The check is done with |\do_check|. We use a separate macro here so
+that we can indent it (in the following definition blanks are active!)
+
+\beginprog
+\begingroup
+\obeyspaces\obeytabs
+\gdef\check_print#1{\cut_at_tab#1^^I\end_line}
+\gdef\cut_at_tab#1^^I#2\end_line{\check_first_part#1 \end_line}% blank !
+\gdef\check_first_part#1 #2\end_line{\do_check{#1}}
+\endgroup
+\endprog
+
+
+\sect
+\begin{sloppypar}
+|\do_check| compares the line with a sample line that is
+available in |\end_verbatim_line|. This macro will be defined later.
+\end{sloppypar}
+
+\beginprog
+\def\do_check#1{%
+ \def\@line{#1}%
+ \ifx \@line\end_verbatim_line \@printfalse
+ \fi
+ }
+\endprog
+
+
+\sect Now we can set a line: we start with the first character,
+followed by the rest of the line. Each character is counted in
+|\char_count|. At the beginning of a line |\char_count| is~0, this
+is reset at the end of the line.
+
+\beginprog
+\newcount\char_count \char_count\z@
+
+\def\print_char#1#2\end_line{%
+ \print_first_char{#1}%
+ \print_rest_of_line{#2}%
+ }
+\endprog
+
+
+\sect For each character that is set |\char_count| is incremented.
+If a character is a tabulator, we set with |\print_tab| the fitting
+amount of blank characters, otherwise the character itself. We must
+compare the character that is stored in |\@char| with a macro of which
+the ``first-level'' expansion is an active tabulator. For this case
+we declare |\@tab|.
+
+\beginprog
+{\obeytabs\gdef\@tab{^^I}}
+
+\def\print_first_char#1{%
+ \def\@char{#1}%
+ \advance \char_count\@ne
+ \ifx \@char\@tab \print_tab
+ \else \@char
+ \fi
+ }
+\endprog
+
+
+\sect If we want to fill the line with blank spaces up to the next
+column with a number that can be divided by~8, we must be able to
+compute the column number modulo~8, but \TeX{} has no modulo operator.
+So we define the macro |\mod_viii| that computes its argument modulo~8
+and returns the result in the counter |\count_mod_viii|. For the
+computation we need the temporary counter |\count@|.
+
+\beginprog
+\newcount\count_mod_viii
+\def\mod_viii#1{%
+ \count@ #1\relax \count_mod_viii\count@
+ \divide \count@ 8\relax
+ \multiply \count@ 8\relax
+ \advance \count_mod_viii -\count@
+ }
+\endprog
+
+
+\sect Now we can declare |\print_tab|. We must remember that
+|\char_count| was incremented already, if we set only one blank
+character the counter keeps untouched.
+
+\beginprog
+\def\print_tab{%
+ \loop \space \mod_viii\char_count
+ \ifnum \count_mod_viii>\z@
+ \advance \char_count\@ne
+ \repeat
+ }
+\endprog
+
+
+\sect If the rest of the line is empty, we are ready. |\char_count|
+is reset to~0 for the next line.
+
+Inside the |\else| part of |\ifx| |\print_char| should not be used
+directly because this costs too much storage of \TeX{}\@. Instead we
+set a control sequence |\next| that is processed afterwards, depending
+on the result of the comparison. (This tail recursion will be
+discovered by \TeX{} and handled appropriately.) If there is still
+something to set, we use |\print_char| again, otherwise a
+syntactically similar macro that expands to |\relax|.
+
+\beginprog
+\def\print_rest_of_line#1{%
+ \def\@line{#1}%
+ \ifx \@line\empty \char_count\z@
+ \def\next##1\end_line{\relax}%
+ \else \let\next\print_char
+ \fi
+ \next#1\end_line
+ }
+\endprog
+
+
+\sect {\sloppy
+Now we are ready to define the two ``user accessible'' macros
+|\beginprog| and |\beginverbatim|. They must define the prototyp end
+line |\end_verbatim_line| which will be compared against every line
+in the verbatim text. During the definition of
+|\end_verbatim_line| it must be cared for that the escape character~`|\|'
+is a printable character: A comparison with |\ifx| demands identical
+category codes. As a temporary escape character we use the slash.
+\par}
+
+\beginprog
+{\catcode`\/=\escape % / is temporary escape char
+ \catcode`\\=\other
+ /gdef/beginprog{%
+ /gdef/end_verbatim_line{\endprog}%
+ /begin_verbatim
+ }
+ /gdef/beginverbatim{%
+ /gdef/end_verbatim_line{\endverbatim}%
+ /begin_verbatim
+ }
+} % here \endgroup can't be used
+\endprog
+
+
+
+
+\chap Document Structuring.
+
+In addition to the normal \LaTeX{} structuring markups we will
+provide a markup for a layout of the document that is like in
+\WEB{}. This can be done easily. All sections are numbered, the
+number of the next section is stored in the counter |section|. We
+distinguish between main sections which start a group of sections
+and between normal sections within a group.
+
+The main sections are started with the macro |\chap|. It has one
+parameter, the title of the section group. This parameter must be
+terminated by a dot. We start a new page, typeset the title in
+bold face and separate it from the section text with a |\medskip|.
+This text, the documentation part of the section, is formatted
+without paragraph indentation.
+
+If the \WEB{}-like macros are used every section number should be
+output with a following dot. We want to establish this when we use the
+|\chap| or the |\sect| macro the first time. Furthermore the new page
+at the begin of a main section should not be started at the first
+|\chap| because a title may precede it (and the title should not
+be on a seperate page unless explicitely requested). Instead a
+skip of (approximately) 2~pica should be set. To achieve
+both goals a macro |\chap_intro| is defined that defines |\thesection|
+appropriately, skips the 2~pica, and redefines itself to
+|\newpage|---we then just have to call |\chap_intro| at the beginning
+of |\chap|. The same applies to |\sect_intro|.
+
+\beginprog
+\newskip\pre_sect_skip \pre_sect_skip=2pc plus 1pc minus 6pt
+
+\def\chap_intro{%
+ \gdef\thesection{\arabic{section}.}%
+ \gdef\chap_intro{\newpage}%
+ \addvspace{\pre_sect_skip}%
+ }
+
+\def\sect_intro{%
+ \gdef\thesection{\arabic{section}.}%
+ \global\let\sect_intro\relax
+ }
+\endprog
+
+
+\sect Now we will have a look at the {\it wonderful\/} internal
+interface of \LaTeX{}\@. With ``wonderful'' I mean that I'm always
+full of wonder why it was designed in this way. E.g., if anybody
+can explain to me why the coding of the non-indentation of the first
+line in the following paragraph was combined with the coding of
+the skip which will come in front of the section---I will be thankful
+for the rest of my life. Such different things should be kept
+different, i.e., the suppression of the indentation should not be
+hidden in the sign of a skip! The same comment applies to the combined
+coding of the skip below the section heading resp.\ to the right
+of a run-in heading.
+
+\begin{quote} \it
+I want the following layout: no indentation in the following
+paragraph\/ {\rm but no} space in front of the section heading.
+How do I code a value of\/ $\sl -0 pt$?
+\end{quote}
+%
+Well, a work-around is to use a value of $\rm -1\,sp$ because the
+reader will not see this distance---but in my opinions this is no
+good programming style. In this special case I have luck, too:
+the skip is not set anyway, either it is discarded by the preceding
+|\newpage| or it is not added by |\addvspace| because of the preceding
+|\pre_sect_skip|.
+
+\beginprog
+\def\chap#1.{%
+ \chap_intro
+ \@startsection{section}{1}%
+ {\z@}%
+ {\m@ne sp}%
+ {\medskipamount}%
+ {\normalsize\bf}%
+ {#1.}%
+ }
+\endprog
+
+
+\sect Normal sections are started with |\sect|. This macro has no
+parameter. Between two paragraphs we skip |\pre_sect_skip|.
+Between the section number and the text one quad of space is set.
+We have to take care for empty documentation parts where the
+program part (i.e.\ |\beginprog|) will follow immediately. Then
+the program part should begin on a new line and not behind the
+section number. So we provide |\null| as an empty documentation
+part in every case.
+
+Now again the design of |\@startsection| comes in hand: \LaTeX{}
+always leaves a quad after the section number (by the way,
+this is not mentioned in the documentation---you have to look
+in the macros to figure this out). Because our section header
+consists only of the number we have to code a value of $\rm
+-0\,pt$\,\dots
+
+\begin{quote}
+Again: {\it non-orthogonal design is bad design}.
+\end{quote}
+
+\beginprog
+\def\sect{%
+ \sect_intro
+ \@startsection{section}{1}%
+ {\z@}%
+ {\pre_sect_skip}%
+ {\m@ne sp}%
+ {\normalsize\bf}%
+ {\null}%
+ }
+\endprog
+
+
+\sect We are finished and just have to restore the category code.
+
+\beginprog
+\catcode`\_=\uscode
+
+\endinput
+\endprog
+
+
+
+
+
+\end{document}
diff --git a/support/makeprog/src/progltx.sty b/support/makeprog/src/progltx.sty
new file mode 100644
index 0000000000..83a3181c20
--- /dev/null
+++ b/support/makeprog/src/progltx.sty
@@ -0,0 +1,194 @@
+\chardef\escape=0
+\chardef\open=1
+\chardef\close=2
+\chardef\letter=11
+\chardef\other=12
+%\chardef\active=13 % is defined in Plain already
+
+\chardef\uscode=\catcode`\_
+
+\catcode`\_=\letter
+%\font\tentex=cmtex10 % typewriter extended ASCII 10pt
+%\let\ttex=\tentex % only with base size 10pt
+\def\ttex{\tt} % as a substitute
+
+\def\setup_verbatim{%
+ \def\do##1{\catcode`##1\other}\dospecials
+ \parskip\z@skip \parindent\z@
+ \catcode`\`\active \@noligs
+ \obeylines \@vobeyspaces \obeytabs \frenchspacing
+ \ttex
+ }
+
+\let\tab=\space
+\begingroup
+ \catcode`\^^I=\active% % Attention: no tabs!
+ \gdef\obeytabs{\catcode`\^^I=\active\def^^I{\tab}}
+ \global\let^^I=\tab% % if an active tab appears in a \write
+\endgroup
+\let\origvert=|
+\chardef\vbar=`\|
+
+\def\makebaractive{\catcode`\|\active}
+\def\makebarother{\catcode`\|\other}
+\makebaractive
+
+\def|{%
+ \leavevmode
+ \hbox\bgroup
+ \let\par\space \setup_verbatim
+ \let|\egroup
+ }
+\let\@@verbatim=\@verbatim
+\def\@verbatim{%
+ \makebarother
+ \@@verbatim
+ }
+\let\@@tabarray=\@tabarray
+\def\@tabarray{%
+ \makebarother
+ \@@tabarray
+ }
+
+\def\multicolumn#1{%
+ \multispan{#1}%
+ \begingroup
+ \makebarother
+ \restof_multicolumn
+ }
+\def\restof_multicolumn#1#2{%
+ \@mkpream{#1}%
+ \def\@sharp{#2}%
+ \let\protect\relax
+ \let\@startpbox\@@startpbox \let\@endpbox\@@endpbox
+ \@arstrut \@preamble
+ \endgroup
+ \ignorespaces
+ }
+
+\let\@@mkpream=\@mkpream
+\def\@mkpream#1{%
+ \@@mkpream{#1}%
+ \makebaractive
+ }
+\begingroup
+ \def\@makeother{\noexpand\@makeother\noexpand}
+ \xdef\@sanitize{\@sanitize\@makeother\|}
+\endgroup
+\newif\if@print
+
+\def\begin_verbatim{%
+ \endgraf
+ \bigbreak
+ \begingroup
+ \setup_verbatim \makebarother
+ \@printtrue
+ \ignore_rest_line
+ }
+\let\end_verbatim=\endgroup % internal command !
+\begingroup
+ \obeylines% % ^^M is active! ==> every line must end with %
+ \gdef\ignore_rest_line#1^^M{\set_next_line}%
+ \gdef\set_next_line#1^^M{\do_set{#1}}%
+\endgroup
+
+\def\do_set#1{%
+ \endgraf
+ \check_print{#1}%
+ \if@print \indent \print_char#1\end_line\end_line
+ \else \let\set_next_line\end_verbatim
+ \fi
+ \set_next_line
+ }
+\let\end_line=\relax
+\begingroup
+\obeyspaces\obeytabs
+\gdef\check_print#1{\cut_at_tab#1^^I\end_line}
+\gdef\cut_at_tab#1^^I#2\end_line{\check_first_part#1 \end_line}% blank !
+\gdef\check_first_part#1 #2\end_line{\do_check{#1}}
+\endgroup
+\def\do_check#1{%
+ \def\@line{#1}%
+ \ifx \@line\end_verbatim_line \@printfalse
+ \fi
+ }
+\newcount\char_count \char_count\z@
+
+\def\print_char#1#2\end_line{%
+ \print_first_char{#1}%
+ \print_rest_of_line{#2}%
+ }
+{\obeytabs\gdef\@tab{^^I}}
+
+\def\print_first_char#1{%
+ \def\@char{#1}%
+ \advance \char_count\@ne
+ \ifx \@char\@tab \print_tab
+ \else \@char
+ \fi
+ }
+\newcount\count_mod_viii
+\def\mod_viii#1{%
+ \count@ #1\relax \count_mod_viii\count@
+ \divide \count@ 8\relax
+ \multiply \count@ 8\relax
+ \advance \count_mod_viii -\count@
+ }
+\def\print_tab{%
+ \loop \space \mod_viii\char_count
+ \ifnum \count_mod_viii>\z@
+ \advance \char_count\@ne
+ \repeat
+ }
+\def\print_rest_of_line#1{%
+ \def\@line{#1}%
+ \ifx \@line\empty \char_count\z@
+ \def\next##1\end_line{\relax}%
+ \else \let\next\print_char
+ \fi
+ \next#1\end_line
+ }
+{\catcode`\/=\escape % / is temporary escape char
+ \catcode`\\=\other
+ /gdef/beginprog{%
+ /gdef/end_verbatim_line{\endprog}%
+ /begin_verbatim
+ }
+ /gdef/beginverbatim{%
+ /gdef/end_verbatim_line{\endverbatim}%
+ /begin_verbatim
+ }
+} % here \endgroup can't be used
+\newskip\pre_sect_skip \pre_sect_skip=2pc plus 1pc minus 6pt
+
+\def\chap_intro{%
+ \gdef\thesection{\arabic{section}.}%
+ \gdef\chap_intro{\newpage}%
+ \addvspace{\pre_sect_skip}%
+ }
+
+\def\sect_intro{%
+ \gdef\thesection{\arabic{section}.}%
+ \global\let\sect_intro\relax
+ }
+\def\chap#1.{%
+ \chap_intro
+ \@startsection{section}{1}%
+ {\z@}%
+ {\m@ne sp}%
+ {\medskipamount}%
+ {\normalsize\bf}%
+ {#1.}%
+ }
+\def\sect{%
+ \sect_intro
+ \@startsection{section}{1}%
+ {\z@}%
+ {\pre_sect_skip}%
+ {\m@ne sp}%
+ {\normalsize\bf}%
+ {\null}%
+ }
+\catcode`\_=\uscode
+
+\endinput
diff --git a/support/makeprog/src/tex2doc.l b/support/makeprog/src/tex2doc.l
new file mode 100644
index 0000000000..7f0fa9cc0a
--- /dev/null
+++ b/support/makeprog/src/tex2doc.l
@@ -0,0 +1,12 @@
+%{
+/* tex2doc.l 20 Jan 90
+ *-------------------------------------------------------
+ * (c) 1990 by J.Schrod.
+ * Copyright conditions: GNU General Public License
+ */
+%}
+
+%%
+
+^%%%\ ? ;
+^%%%%.*\n ;