diff options
Diffstat (limited to 'Master/texmf-dist/doc/etex/base/webmerge.tex')
-rw-r--r-- | Master/texmf-dist/doc/etex/base/webmerge.tex | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/etex/base/webmerge.tex b/Master/texmf-dist/doc/etex/base/webmerge.tex new file mode 100644 index 00000000000..a55ac3e9301 --- /dev/null +++ b/Master/texmf-dist/doc/etex/base/webmerge.tex @@ -0,0 +1,392 @@ +% This is webmerge.tex +% Copyright (C) 1995,96 by the NTS team; all rights are reserved. +% +\def\fileversion{V 1.1} +\def\filedate{29 Mar 96} +% +% In order to generate e-TeX several change files have to be applied +% (one after the other) to tex.web. This can be done efficiently with +% programs such as PATCHWEB or TIE. If neither of these is available +% the present program WEBMERGE can be used to merge several change +% files into one change file that can then be used with TANGLE. +% +% If the web file or one of the change files contains tab of form feed +% characters there is, however, a problem that can't be solved in a +% satisfactory way. This should not be a real problem since the +% original tex.web and etex.ch don't contain these characters and there +% is no real good reason why the system-dependent change files should +% (except may be that some editors insist on converting sequences of +% space characters into tabs). +% +% The problem is due to the fact that (an unmodified) TeX cannot write +% tabs or form feeds to the output file. Therefore WEBMERGE offers two +% alternatives: if \ifallowtabs is false (by default) then tab and form +% feed characters are invalid and lead to error messages; if this +% happens one may use the command +% \allowtabstrue +% to allow tab and form feed as valid input characters. If they are +% written to the output file they will appear as '^^I' and '^^L'. This +% must then be changed manually with a suitable editor before the output +% from WEBMERGE can be used as input for TANGLE. +% +% Typically three change files are required to generate e-TeX, e.g., +% 1. etex.ch (system independent changes for e-TeX) +% 2. tex.ch (system dependent changes for TeX) +% 3. tex.ech (additional system dependent changes for e-TeX) +% The sequence commands (to be used with plain TeX) +% \input webmerge +% \webfile{tex.web} % web file +% \changefile{etex.ch} % 1. change file +% \changefile{tex.ch} % 2. change file +% \changefile{tex.ech} % 3. change file +% \outfile{etex.ch} % output file, start processing +% creates a combined change file `etex.ch'. +% Webmerge uses a temporary file with default name `tmp.tmp', +% the command +% \tempfile{<temp name>} +% can be used to change that name. +% +% Webmerge is slow, therefore PATCHWEB or TIE should be used whenever +% possible. The program checks for correct change files and gives error +% messages similar to those of TANGLE and WEAVE. The error recovery is, +% however, rather limited. +% +% In case of problems please contact: +% Peter Breitenlohner peb@mppmu.mpg.de + +% We make @ signs act like letters, temporarily. +\catcode`\@=11 + +\newif\ifallowtabs % initially false +\def\allowtabs{\catcode`\^^I=12 \catcode`\^^L=12 } +\def\forbidtabs{\catcode`\^^I=15 \catcode`\^^L=15 } + +\toksdef\toks@ii=2 + +% First we redefine plain.tex's \loop to allow the construction +% \loop ... \if... \else ... \repeat +% +\def\@iterate{\@body \expandafter\@iterate\fi} +% +% and to allow nested loops such as +% \loop{... \loop ... \if... \repeat ... \if...}\repeat +% where the braces do not imply grouping +% +\def\loop#1\repeat{% + \toks@\expandafter{\@body}% + \toks@ii\expandafter{\@@body}% + \edef\@@body{\def\noexpand\@body{\the\toks@}% + \def\noexpand\@@body{\the\toks@ii}}% + \def\@body{#1}\@iterate \@@body} +\let\@body=\empty +\let\@@body=\empty + +% +\def\@msg{\immediate\write\sixt@@n} +\@msg{*** webmerge \fileversion\space <\filedate> ***} +% +% Conceptually the web file (web_0) is combined with the first change +% file, ch_1, in order to produce a ficticious web file web_1. Then +% web_1 is combined with ch_2 in order to produce web_2 etc. + +% The logic of merging is that of TANGLE and WEAVE. +% With several change files there may, however, be changes on top of +% changes, i.e., a line changed by one change file may be changed again +% by another change file. + +% The program below uses quite a few control sequences, many of them +% constructed dynamically. +% The most important ones are \<i>read (<i>=0,1,...) used to obtain the +% next line from web_<i>. For reasons of efficiency they are \let to +% either \<i>w (changing=false), \<i>c (changing=true), of \<i>e (file +% has ended). +% \<i>g is used to obtain the next line from ch_<i> and test for +% @x/@y/@z, +% \<i>prime (prime the change buffer) scans for the next @x from ch_<i>, +% and \<i>match discards matching lines from web_<i-1> and ch_<i> until +% an @y is found. + +\def\tempfile#1{\def\t@n{#1}} +\def\t@n{tmp.tmp} % default tempfile name +\newread\t@r % read tempfile +\newwrite\t@w % write tempfile +\def\t@o{\immediate\write\t@w} % write to tempfile +\newwrite\o@w % write output file +\def\o@o{\immediate\write\o@w} % write to outfile + +\newcount\@nch % number of change files +\newcount\@num % number of active changes +\newcount\@res % result from @x/@y/@z test +\begingroup % \@pct expands to `% ' + \lccode`\1=`\% + \lowercase{\endgroup \def\@pct{1 }} +% + +% We need macros to define read streams, count registers, and control +% sequences dynamically (inside \edef) + +\def\@nrd#1{\ifx#1\relax \csname newread\endcsname#1\fi} +\def\@nct#1{\ifx#1\relax \csname newcount\endcsname#1\else #1\z@ \fi} +\def\@cs#1{\csname#1\endcsname} +\def\@csi#1{\csname\@i#1\endcsname} +\def\@dcs#1{\expandafter\def\csname#1\endcsname} +\def\@ecsi#1{\expandafter\edef\csname\@i#1\endcsname} +\def\@ncsi#1{\expandafter\noexpand\csname\@i#1\endcsname} +\def\@read{\expandafter\noexpand\csname\@ii read\endcsname} +\def\@ifx{\noexpand\ifx} +\def\@ifnum{\noexpand\ifnum} +\def\@ifeof{\noexpand\ifeof\@csi r} +\def\@else{\noexpand\else} +\def\@fi{\noexpand\fi} +\def\@loop{\noexpand\loop} +\def\@repeat{\noexpand\repeat} +\def\@expa{\noexpand\expandafter\noexpand} +\def\@expai#1{\expandafter\@expa\csname\@i#1\endcsname} + +\def\webfile#1{% define webfile + \ifnum\@nch=\m@ne \@nch\z@ \@dcs{0n}{#1}% + \else \@msg{\string\webfile{#1} ignored (out of order)}% + \fi} +\def\changefile#1{% define a changefile + \ifnum\@nch<\z@ + \@msg{\string\changefile{#1} ignored (missing \string\webfile)}% + \else \ifnum\@nch>8 \@msg{\string\changefile{#1} ignored (too many)}% + \else \advance\@nch\@ne \@dcs{\number\@nch n}{#1}% + \fi \fi} +\def\outfile#1{% define outfile and process + \ifnum\@nch<\@ne + \@msg{\string\outfile{#1} ignored (missing \string\changefile)}% + \else \def\o@n{#1}\@init \@merge \@done + \fi} +\def\@init{% initialize + \@msg{}\@msg{webmerge \fileversion\space <\filedate>}% + \immediate\openout\o@w=\o@n + \o@o{\@pct This is \o@n, a WEB change file produced by webmerge.tex}% + \begingroup + \def\do##1{\catcode`##1=12 }\dospecials + \ifallowtabs \allowtabs \else \forbidtabs \fi + \endlinechar=\m@ne + \count@\z@ + \loop \edef\@i{\number\count@}\@@init + \ifnum\count@<\@nch \advance\count@\@ne \let\@ii\@i + \repeat + \o@o{}% + \@msg{out=\o@n, merging ...}} +% +% Here now is the quite complicated macro \@@init +% its main purpose is to dynamically construct +% the macro \<i>read that returns the next line of web_<i> in \@web +% as well as various auxiliary macros \<i>... +% +\def\@@init{% initialize input file <i> + \edef\x{% define \read streams and \count registers + \noexpand\@nrd\@ncsi r% \newread\<i>r + \noexpand\@nct\@ncsi l% \newcount\<i>l (line number) + \noexpand\@nct\@ncsi s% \newcount\<i>s (status) + }\x \@csi l\z@ \@csi s\z@ % \<i>l=0 \<i>s=0 + \openin\@csi r\@csi n % \openin\<i>r=\<i>n + \@msg{\ifeof\@csi runable to open input file + \else \ifnum\@i=\z@ web\else change \@i\fi =\fi \@csi n}% + \ifnum\count@=\z@ % <i>=0 for web file + \let\@web\relax +%% +%% \def\0w{% return web_0 line (file not yet ended) +%% \read\0r to\@web \0s=0 % read from web_0, mark as unchanged +%% \ifeof\0r \0e \else \advance\0l by 1 \fi} +%% + \@ecsi w{% return web_0 line (file not yet ended) + \read\@csi rto\@web \@csi s\z@ + \@ifeof \@ncsi e\@else \advance\@csi l\@ne \@fi}% +%% +%% \def\0e{% return web_0 line (file has ended) +%% \let\0read=\0e \let\@web=\relax} +%% + \@ecsi e{% return web_0 line (file has ended) + \let\@ncsi{read}\@ncsi e\let\@web\relax}% +%% +%% \ifeof\0r \0e \else \let\0read=\0w +%% + \ifeof\@csi r\@csi e% + \else \edef\x{\let\@ncsi{read}\@ncsi w}\x + \fi + \o@o{\@pct to be applied to \@csi n}% + \o@o{\@pct combining the changes (one after the other) from}% + \else % <i>=1,2,3,... for change files + \o@o{\@pct \@i. \@csi n}% +%% +%% \def\<i>g#1{% read change file and test for @x/@y/@z +%% \ifeof\<i>r \let\<i>x=\relax \@res=#1 +%% \else \@res=0 \read\<i>r to\<i>x +%% \advance\<i>l by 1 \expandafter\@test\<i>x ab\@#1<i> +%% \fi} +%% + \@ecsi g##1{% read change file and test for @x/@y/@z + \@ifeof \let\@ncsi x\relax \@res##1% + \@else \@res\z@ \read\@csi rto\@ncsi x% + \advance\@csi l\@ne \@expa\@test\@ncsi xab\noexpand\@##1\@i + \@fi}% +%% +%% \def\<i>w{% return web_i line (changing is false) +%% \<i-1>read % get web_<i-1> line +%% \ifx\@web\<i>x % test for match +%% \expandafter\<i>match % match lines from web_i-i and ch_i +%% \fi} % else return web_<i-1> line +%% + \@ecsi w{% return web_i line (changing is false) + \@read \@ifx\@web\@ncsi x\@expai{match}\@fi}% +%% +%% \def\<i>c{% return web_i line (changing is true) +%% \<i>g 3 % get ch_i line and test for @z +%% \ifnum\@res=3 % @z found +%% \@echg <i> % deactivate a change +%% \<i>prime % prime the change buffer +%% \expandafter\<i>read % read again, now from web_<i-1> +%% \else \@mod\<i>x % return ch_i line, mark as changed (\0s=1) +%% \fi} +%% + \@ecsi c{% return web_i line (changing is true) + \@ncsi g\thr@@ + \@ifnum\@res=\thr@@ + \noexpand\@echg\@i \@ncsi{prime}\@expai{read}% + \@else \noexpand\@mod\@ncsi x% + \@fi}% +%% +%% \def\<i>e{% return web_i line (change file has ended) +%% \<i-1>read} % return web_<i-1> line +%% + \@ecsi e{% return web_i line (change file has ended) + \@read}% +%% +%% \def\<i>prime{% prime the change buffer +%% \loop +%% \<i>g 1 % get ch_i line and test for @x +%% \ifnum\@res=1 \else \repeat % repeat until found +%% \loop +%% \<i>g 0 % get ch_i line +%% \ifx\<i>x\empty \repeat % repeat until not blank line +%% \ifx\<x>\relax \let\<i>read=\<i>e % change file has ended +%% \else \let\<i>read=\<i>w % +%% + \@ecsi{prime}{% prime the change buffer + \@loop \@ncsi g\@ne \@ifnum\@res=\@ne \@else \@repeat + \@loop \@ncsi g\z@ \@ifx\@ncsi x\noexpand\empty \@repeat + \@ifx\@ncsi x\relax \let\@ncsi{read}\@ncsi e% + \@else \let\@ncsi{read}\@ncsi w% + \@fi}% +%% +%% \def\<i>match{% match lines from web_<i-1> and ch_<i> +%% \ifx\@web\relax % web_<i-1> and ch_<i> have ended +%% \let\<i>read=\<i>e \<i> % indicate web_<i> has ended +%% \else \@bchg % activate a change +%% \loop \@chg % write a matching line to output (maybe) +%% \<i>g 2 % get ch_i line and test for @y +%% \ifnum\@res=2 \@endm <i> % end of match found +%% \else \<i-1>read % get web_<i-1> line +%% \ifx\@web\relax % test for end of web file +%% \@err <i>{Web file ended during change} +%% \fi +%% \ifx\@web\<i>x % test for matching lines +%% \else \advance\<i>s by 1 \fi % count mismatches +%% \repeat +%% \let\<i>read=\<i>c % now changing is true +%% \fi +%% \<i>read} % get next web_<i> line again +%% + \@ecsi{match}{% match lines from web_<i-1> and ch_<i> + \@ifx\@web\relax + \let\@ncsi{read}\@ncsi e% + \@else \noexpand\@bchg + \@loop \noexpand\@chg \@ncsi g\tw@ + \@ifnum\@res=\tw@ \noexpand\@endm\@i% + \@else \@read + \@ifx\@web\relax + \noexpand\@err\@i{Web file ended during change}% + \@fi + \@ifx\@web\@ncsi x\@else \advance\@csi s\@ne \@fi + \@repeat + \let\@ncsi{read}\@ncsi c% + \@fi + \@ncsi{read}}% +%% +%% \<i>prime % prime the change buffer +%% + \@csi{prime}% prime the change buffer + \fi} +\def\@done{%terminate + \count@\z@ + \loop \edef\@i{\number\count@}% + \ifnum\count@=\z@ \else % change file + \ifeof\@csi r\else \@@err{Change file entry didn't match}\fi + \fi + \closein\@csi r% close input file <i> + \ifnum\count@<\@nch \advance\count@\@ne + \repeat + \endgroup + \immediate\closeout\o@w + \@nch\m@ne % prepare for next \webfile + \@msg{... done}\@msg{}} + +\catcode`\0=11 % for \0s +\def\@merge{% process + \@num\z@ + \expandafter\loop\csname\number\@nch read\endcsname % read web_<n> + \ifnum\0s=\@ne \t@o{\@web}\fi + \ifx\@web\relax + \else + \repeat} +\def\@chg{\ifnum\0s=\z@ \o@o{\@web}\fi} +\def\@mod{\0s\@ne \let\@web} +\catcode`\0=12 + +\def\@err#1{\def\@i{#1}\@@err} +\def\@@err#1{\@msg{! #1}% + \@msg{ ... change file \@i\space (\@csi n) line \the\@csi l}} + +\def\@test#1#2#3\@{\if#1@ \csname set@#2\endcsname \fi \@eat} +\def\@eat#1#2{} +\def\set@x{\@res\@ne \expandafter\@xyz} +\def\set@y{\@res\tw@ \expandafter\@xyz} +\def\set@z{\@res\thr@@ \expandafter\@xyz} +\let\set@X=\set@x +\let\set@Y=\set@y +\let\set@Z=\set@z +\def\@xyz\@eat#1#2{% + \ifnum#1=\@res + \else \@err#2{Extra \@@xyz{\@res} ignored (expecting \@@xyz#1)}% + \@res\z@ + \fi} +\def\@@xyz#1{@\ifcase#1\or x\or y\or z\fi} + +\def\@endm#1{% + \ifnum\csname#1s\endcsname>\z@ + \@err#1{Hmm... \the\@csi s of the preceding lines failed to match}% + \fi + \csname#1s\endcsname\z@} + +\def\@bchg{% activate a change + \ifnum\@num=\z@ % first change activated, start writing to temp + \immediate\openout\t@w=\t@n\space + \o@o{@x l.\number\csname 0l\endcsname} + \fi + \advance\@num\@ne} +\def\@echg#1{% deactivate a change + \expandafter\ifx\csname#1x\endcsname\relax + \@err#1{Change file ended during change}% + \fi + \advance\@num\m@ne + \ifnum\@num=\z@ % last change deactivated + \t@o{@z}% + \immediate\closeout\t@w % close temp file + \openin\t@r=\t@n\space + \o@o{@y} + \loop \read\t@r to\t@x \o@o{\t@x}% copy temp to output + \ifeof\t@r \closein\t@r + \else + \repeat + \fi} + +\@nch=\m@ne + +\catcode`\@=12 % at signs are no longer letters + +\endinput |