diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/makeprog/src |
Initial commit
Diffstat (limited to 'support/makeprog/src')
-rw-r--r-- | support/makeprog/src/doc2tex.l | 122 | ||||
-rw-r--r-- | support/makeprog/src/makeprog.web | 1171 | ||||
-rw-r--r-- | support/makeprog/src/progdoc.doc | 668 | ||||
-rw-r--r-- | support/makeprog/src/progdoc.tex | 217 | ||||
-rw-r--r-- | support/makeprog/src/progltx.doc | 739 | ||||
-rw-r--r-- | support/makeprog/src/progltx.sty | 194 | ||||
-rw-r--r-- | support/makeprog/src/tex2doc.l | 12 |
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 ; |