nwmac.tex
, also known
as the root document ``*'' of this (literate) program.
<*>= <nwmac.tex>
This code is written to a file (or else not used).
*\subsection{Usage}
These macros are intended for use with {\tt noweave}
and {\tt noweb}, and are not particularly useful in their own right.
This document exists to describe the organization and behaviour of the
macros herein.
In use, the macros read in the {\TeXIP} macros required, and documents
from noweave
need no other support than these macros and plain
{\TeX}. However, this document itself does use a number of other
macros from {\TeXIP}.
<nwmac.tex>= % nwmac.tex -- plain TeX support for noweb % DON'T read or edit this file! Use the file nwsup.nw instead.
Used above; next definition.
*\subsection{Copyright} The original versions of these macros were written for {\LaTeX} by Norman Ramsey and are copyright by him. This version by John Hurst, 1995.
<nwmac.tex>+= % copyright Norman Ramsey, 1991 (original LaTeX macros) % modified for plain Tex by John Hurst, 1995
Used above; previous and next definitions.
\subsection{Background} These macros have been modified from Norman Ramsey's {\tt support.nw} document, by removing all {\LaTeX} specific material, and modifying the plain {\TeX} macros appropriately. They have been rewritten to provide cross referencing and indexing, using much of the {\LaTeX} code, together with some macros from {\TeXIP}, the four volume series ``\TeXIP" by Stephan von Bechtolsheim, published in 1993 by Springer-Verlag, New York. \subsection{Components} This document is structured into a number of sections, and, as far as possible, the literate program structure follows the documentation structure, namely: \begingroup \parskip=0pt \advance\rightskip by 10pt \advance\leftskip by 30pt Overview (this section)\par Document Style Parameters\par \begingroup\advance\leftskip by 30pt Page Style\par Chunk Style\par \endgroup Options\par Initialization\par Type Setting Management\par \begingroup\advance\leftskip by 30pt Two Column Handling\par Page-breaking Strategy\par \endgroup Chunk Management\par Labels\par \begingroup\advance\leftskip by 30pt Basic Referencing\par Sub-page Referencing\par WEB numbering\par \endgroup Cross Referencing\par \begingroup\advance\leftskip by 30pt Chunks\par Identifiers\par Support\par \endgroup Indexing\par \begingroup\advance\leftskip by 30pt Chunks\par Identifiers\par \endgroup Support Routines\par Finalization\par Startup Processing\par Miscellaneous\par \endgroup
<nwmac.tex>+= <Document Style Parameters> <Initialization For Macros> <Type Setting Management> <Chunk Management> <Labels> <Cross Referencing of Chunks and Identifiers> <Chunk Index Construction> <Housekeeping and Support Routines> <other stuff not yet updated> <Finalizing and Washup> <Startup Processing>
Used above; previous definition.
% **** Document Style Parameters ***************************************
\section{Document Style Parameters}
Make @
a letter so that we can use `private' macro names.
<Document Style Parameters>= \catcode`\@=11 <Page Style Parameters> <Chunk Style Parameters>
Used above.
*\subsection{Page Style Parameters}
Define the \\nwpagewidth
, which is the width of (normal) text on a
page. \nwpageheight
is the height of text on a page.
<Page Style Parameters>= \newdimen\nwpagewidth \nwpagewidth=\hsize \newdimen\nwpageheight \nwpageheight=\vsize
Defines\nwpageheight
,\nwpagewidth
(links are to index).
*
Standard paragraph separation \parskip
and first line
indentation \parindent
are reset for documentation chunks.
<Page Style Parameters>+= \parskip=16pt \parindent=0pt
Used above; previous and next definitions.
The conditional \iftwopagelayout
allows the user to switch on a
double sided mode of page layout, in which the page number in the
heading switches from side to side. The default is single sided mode
(no switching).
<Page Style Parameters>+= \newif\iftwopagelayout\twopagelayoutfalse
Used above; previous definition.
*\subsection{Chunk Style Parameters}
\codemargin
is the amount by which code listings are indented from
the normal margin. \nwtagstyle
determines the style in which tags
are displayed. \codemargin
, may be reset by the user if she
desires a different setting. This reset should be placed before the
first code chunk that should be indented.
<Chunk Style Parameters>= \newdimen\codemargin \codemargin=20pt \def\nwtagstyle{\footnotesize\rm}%
Defines\codemargin
,\nwtagstyle
(links are to index).
*
We make the \hsize
parameter for code sufficient for 88 columns.
Well, 91 actually, but Norman wasn't sure why the extra bit.
<Chunk Style Parameters>+= \setbox0=\hbox{\tt m} \newdimen\codehsize \codehsize=91\wd0
Defines\codehsize
(links are to index).Used above; previous and next definitions.
*
\defspace
is the space we would like on the right of navigational info
that appears on definition lines, so that it lines up with the text above
and below.
<Chunk Style Parameters>+= \newdimen\nwdefspace \nwdefspace=\codehsize \advance\nwdefspace by -\nwpagewidth \relax
Used above; previous and next definitions.
\nwmarginglue
defines how far into the left margin a chunk tag is
placed. \nwtagstyle
determines how it is printed.
<Chunk Style Parameters>+= \newdimen\nwmarginglue\nwmarginglue=7.5mm \def\nwtagstyle{\bf}%
Defines\nwmarginglue
,\nwtagstyle
(links are to index).Used above; previous definition.
* % **** Options ********************************************************* \section{Options} Not much defined in this section as yet. % **** Initialization ************************************************** \section{Initialization} Include the {\TeXIP} macros.
<Initialization For Macros>= \input inputd.tip \InputD{inputc.tip} \InputD{ts-fonts.tip} \InputD{list-mac.tip} \InputD{namedef.tip} \InputD{printco.tip} <Type Setting Initialization>
Used above; next definition.
We need some redefinitions for compatibility between TiP and noweave.
<Initialization For Macros>+= \catcode`\@=11 \let\@namedef=\NameDef \let\@nameuse=\NameUse
Defines\@namedef
,\@nameuse
(links are to index).Used above; previous and next definitions.
Define the macro that appears at the start of each input file. The markup program and filters put this `filename' flag at the start of the text. This is used to generate an appropriate banner to each page.
<Initialization For Macros>+= \def\nwfilename#1{% \vfil\eject% start a new page for this file \mark{#1}% set the banner for this and subsequent pages }%
Defines\nwfilename
(links are to index).Used above; previous definition.
* % **** Type Setting Management ******************************************* \section{Type Setting Management} *\subsection{Two Column Handling} Most of the document is set in single column mode, however, for the indices we wish to provide a two-column mode. This is imported from the {\TeXIP} macros. Since the double column macro defines its own ({\TeX}) output routine, we have to setup the page size and header and footer lines as well.
<Type Setting Initialization>= \InputD{out-ds.tip}% \SetUpDSC{\nwpagewidth}{0.45\nwpagewidth}{0pt}{\nwpageheight}{1}{0}% \def\DSCHeader{% \iftwopagelayout \ifodd\pageno <Right Page Heading> \else <Left Page Heading> \fi \else <Right Page Heading> \fi }% \def\DSCFooter{\hfil}% \catcode`\@=11% reset to allow @ in macro names
Used above; next definition.
We allow alternating headings for double sided printing. Only difference between the two is the order of file name, date and page number, which is reversed for the left hand side of a page spread.
<Right Page Heading>= \hbox to \nwpagewidth{% \tentt\firstmark \hfil \tenrm\today \hbox to 4em{\hss\folio}% }%
Used above.
<Left Page Heading>= \hbox to \nwpagewidth{% \hbox to 4em{\folio\hss}% \tenrm\today \hfil \tentt\firstmark }%
Used above.
We start off in single column mode by default.
Since the double-column macros also redefine \bye
, we should
save that for later use when we redefine \bye
!
<Type Setting Initialization>+= \let\DSC@bye=\bye
Used above; previous definition.
\subsection{Page-breaking strategy}
We want to insert penalties aiming for:
\enumskip=0pt\BeginEnumerate
\Item No page breaks in the middle of a code chunk unless necessary to
avoid an overfull vbox;
\Item Documentation immediately preceding a code chunk should appear on
the same page as that code chunk unless doing so would violate rule 1.
\EndEnumerate
\filbreak
is useful for this sort of thing (see {\it The {\TeX}
book\/}) and is used to encourage breaks at the right places between
chunks. Appropriate penalties are inserted elsewhere, between code
lines in particular.
\eatline
is used to consume newlines that should be ignored, for
example, the newlines at the end of @ %def
{\it identifiers}
lines. I can't remember what \startline
or \newlines
are for;
I don't think {\tt noweave} ever emits them.
<Type Setting Management>= {% \catcode`\^^M=\active % make CR an active character \gdef\newlines{% \catcode`\^^M=\active % make CR an active character \def^^M{\par\startline}% }% \gdef\eatline#1^^M{\relax}% }% %%% DON'T \gdef^^M{\par\startline}}% in case ^^M appears in a \write \def\startline{% \noindent\hskip\parindent\ignorespaces }% \def\nwnewline{% \ifvmode \else\hfil\break \fi }%
Defines\eatline
,\newlines
,\nwnewline
,\startline
(links are to index).Used above.
*
% **** Chunk Management ************************************************
*\section{Chunk Management}
Here are the basics of the literate programming style. The
alternation of document and code chunks is managed by the environment
macros \nwbegindocs
,\nwenddocs
which bracket documentation
chunks, and \nwbegincode
,\nwendcode
which bracket code chunks.
It is not essential that documentation and code are strictly
alternating, they can be interleaved in arbitrary order.
Start a documentation chunk. This is a good place to break, hence
the \filbreak
.
<Chunk Management>= \def\nwbegindocs#1{% \filbreak }%
Defines\nwbegindocs
(links are to index).
End a documentation chunk. Not much to it, really.
<Chunk Management>+= \def\nwenddocs{% \par }%
Defines\nwenddocs
(links are to index).Used above; previous and next definitions.
Start a code chunk. A bit more involved, as we have to begin a group
(which gets closed by the matching \nwendcode
), and set up the
environment for typesetting that code (sse chunk
\subref{ref:setupcode}).
<Chunk Management>+= \def\nwbegincode#1{% \par\nobreak \begingroup% matching \endgroup appears in \nwendcode \setupcode \newlines \advance\leftskip by \codemargin \parindent=0pt\parskip=0pt \let\oendmoddef=\endmoddef \let\oplusendmoddef=\plusendmoddef \def\endmoddef{\oendmoddef\par}% \def\plusendmoddef{\oplusendmoddef\par}% \hsize=\codehsize \noindent\bchack }%
Defines\nwbegincode
(links are to index).Used above; previous and next definitions.
End a code chunk
<Chunk Management>+= \def\nwendcode{% \endgroup }%
Defines\nwendcode
(links are to index).Used above; previous and next definitions.
Don't really know what a \nwdocspar
does.
<Chunk Management>+= \def\nwdocspar{% \par\semifilbreak }%
Defines\nwdocspar
(links are to index).Used above; previous and next definitions.
<Chunk Management>+= \def\semifilbreak{% \vskip0pt plus1.5in \penalty-200 \vskip0pt plus -1.5in }% \raggedbottom
Defines\semifilbreak
(links are to index).Used above; previous and next definitions.
*
*\sublabel{ref:setupcode}%
Most code is set in an environment in which \setupcode
has been
executed. In this environment, only \
, {
, and }
have
their usual categories; every other character represents itself.
Appropriate \chardef
s ensure that the special characters can be
escaped with a backslash.
<Chunk Management>+= \chardef\other=12 \def\setupcode{% \chardef\\=`\\ \chardef\{=`\{ \chardef\}=`\} \catcode`\$=\other \catcode`\&=\other \catcode`\#=\other \catcode`\%=\other \catcode`\~=\other \catcode`\_=\other \catcode`\^=\other \obeyspaces\tt }
Defines\setupcode
(links are to index).Used above; previous and next definitions.
* Within a code environment, it may be necessary to restore the category codes in order to set a module (chunk) name.
<Chunk Management>+= {\obeyspaces\global\let =\ }% from texbook, p 381 \def\setupmodname{% \catcode`\$=3 \catcode`\&=4 \catcode`\#=6 \catcode`\%=14 \catcode`\~=13 \catcode`\_=8 \catcode`\^=7 \catcode`\ =10 \catcode`\^^M=5 \rm }%
Defines\setupmodname
(links are to index).Used above; previous and next definitions.
*
*{\tt noweave} brackets uses of chunk names with \LA
and \RA
, which
handle the angle brackets, font, and environment.
As it stands, chunk names can be broken across lines (or pages). This
could result in unnecessary page breaks in code. \let\\maybehbox=\hbox
to
avoid breaking them (or to make them work in math mode); this is done
in code chunks, but could be done in general.
<Chunk Management>+= \def\LA{\begingroup\maybehbox\bgroup\setupmodname\it$\langle$} \def\RA{\/$\rangle$\egroup\endgroup} \def\code{% \leavevmode \begingroup \setupcode \newlines }% \def\edoc{% \endgroup }% \let\maybehbox\relax
Defines\LA
,\RA
,\code
,\edoc
,\maybehbox
(links are to index).Used above; previous and next definitions.
*
\equivbox
and \plusequivbox
are used to set the
``\unhcopy\equivbox'' and ``\unhcopy\plusequivbox'' that open a chunk
definition or its continuation. {\tt noweave} brackets definitions of
chunk names with \moddef
and either \endmoddef
or
\plusendmoddef
.
<Chunk Management>+= \newbox\equivbox \setbox\equivbox=\hbox{$\equiv$}% \newbox\plusequivbox \setbox\plusequivbox=\hbox{$\mathord{+}\mathord{\equiv}$}%
Defines\equivbox
,\plusequivbox
(links are to index).Used above; previous and next definitions.
\moddef
can't have an argument because there might be
\code
$\ldots$\edoc
nested within the argument.
<Chunk Management>+= \def\moddef{% \leavevmode \kern-\codemargin \LA }%
Defines\moddef
(links are to index).Used above; previous and next definitions.
<Chunk Management>+= \def\endmoddef{ \RA \ifmmode \equiv \else \unhcopy\equivbox \fi \nobreak\hfill\nobreak }%
Defines\endmoddef
(links are to index).Used above; previous and next definitions.
<Chunk Management>+= \def\plusendmoddef{% \RA \ifmmode \mathord{+}\mathord{\equiv}% \else \unhcopy\plusequivbox \fi \nobreak\hfill\nobreak }%
Defines\plusendmoddef
(links are to index).Used above; previous and next definitions.
*
\bchack
({\it b\/}egin {\it c\/}ode {\it hack} serves to consume
the carriage return following the \nwbegincode
start environment
macro.
<Chunk Management>+= {% \catcode`\^^M=\active % make CR an active character \gdef\bchack#1^^M{\relax#1}% }%
Defines\bchack
(links are to index).Used above; previous definition.
*
% **** Labels **********************************************************
\section{Labels}
\subsection{Basic Referencing Macros}
{\LaTeX} supplies the macros \ref
and \pageref
to do cross
referencing. We need to supply definitions for these.
The basic principle of cross referencing is to plant {\it label\/}s in
the source text that identify the places that we want to talk about.
Along with the label, we can give a user-defined {\it name}.
Then the \ref
macro is used to reference that place by name, and
\pageref
is used to refer to the location by page number.
Here's the macro to plant a label. I pinched this straight from
{\LaTeX}, and commented out the bits not needed.
<Labels>= \def\label#1{% %\@bsphack %\if@filesw {% \let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \xdef\@gtempa{% \write\@auxout{% \string\newlabel{#1}{{0}{\thepage}}% }% }% }% \@gtempa %\if@nobreak \ifvmode\nobreak\fi %\fi %\fi %\@esphack }%
Defines\label
(links are to index).
\ref
takes a single parameter which is a label, and generates the
name. If the label has not been defined, an error message is issued,
and the name represented by two question marks.
<Labels>+=
\def\ref#1{%
\@ifundefined{r@#1}%
{{\bf ??}<warn of undefined reference to #1
>}%
{\expandafter\expandafter\expandafter
\@car\csname r@#1\endcsname\@nil\null}%
}%
Defines\ref
(links are to index).Used above; previous and next definitions.
\pageref
is the same as \ref
, except that it generates the
page number of the location of the referenced label.
<Labels>+= \def\pageref#1{% \@ifundefined{r@#1}% {{\bf ??}<warn of undefined reference to#1
>}% {\expandafter\expandafter\expandafter \@cdr\csname r@#1\endcsname\@nil\null}% }% \def\@refpair#1{% \@ifundefined{r@#1}% {{0}{0}<warn of undefined reference to#1
>}% {\@nameuse{r@#1}}% }%
Defines\pageref
,\@refpair
(links are to index).Used above; previous and next definitions.
<warn of undefined reference to #1
>=
\@warning{Reference `#1' on page \thepage \space undefined}
Used below (1), below (2).
\subsection{Sub-page references}
This is the wonderful code that Dave Love provided to make page
references like 7a, 7b, and so on.
This code provides a mechanism for defining `page sub-references'
using \sublabel{foo}
referenced with \subpageref{foo}
.
Sub-references will be numbered like these real examples:
\subpageref{ref:foo}, \subpageref{ref:bar},
\subpageref{ref:baz}\sublabel{ref:foo}\sublabel{ref:bar}\sublabel{ref:baz}
etc.\ unless there is only one on the page, in which case the letter
will be dropped like this: \subpageref{ref:fred}.
To be able to use \subpageref
we must define the label with
\sublabel
, used like label. (Using \ref
with a label defined
by \sublabel
will produce the sub-reference number, by the way,
and \pageref
works as expected.) Note that \subpageref
is
robust and \ref
and \pageref
are redefined to be robust also,
as they will be in future \LaTeX{} releases. Incidentally, these
expand to the relevant text plus \null
---you might want to strip
this off, e.g.\ for sorting lists.
There are various ways we could attack this task (which is made
non-trivial by the well-known asynchrony of (La)\TeX's output
routine), but
they all must depend on hacks in the .aux
file or a similar one.
Joachim Schrod's fnpag.sty
does the same sort of thing differently
to this \LaTeX-specific approach. See latex.tex
for enlightenment
on the cross-referencing mechanism and the \LaTeX{} internals used
below. [DL: The internals change in \LaTeX2e compared with
\LaTeX~2.09. The code here still works, though.]
The \subpageref
macro first does a normal \pageref
. If the
reference is actually defined, it then goes on to check whether the
control sequence 2on
\LA{}{page referenced}\RA{} is defined and
sets the \ref
value to get a
etc.\ if so. The magic, of
course, is in defining the 2on
bit appropriately.
Define a \subref
to be the same as a \subpageref
<Labels>+= \def\subref#1{% \subpageref{#1}% }%
Defines\subref
(links are to index).Used above; previous and next definitions.
<Labels>+= \def\subpageref#1{% \@ifundefined{r@#1}% {% \pageref{#1}% }% {% \@ifundefined{2on\@pageref{#1}}% {% %\edef\@spref{\@subref{#1}} %\expandafter\nwthepagenum\@spref \pageref{#1}% }% {% \expandafter\expandafter\expandafter \nwthepagenum\csname r@#1\endcsname }% }% }%
Defines\subpageref
(links are to index).Used above; previous and next definitions.
*
\@subref
is a hangover from the {\LaTeX} version, and could well
be reinstated, except that I now achieve the same thing (I hope!) by
directly calling the \pageref
macro. The difference is whether
the label is used directly (current), or whether the stored page in
the list associated with the label is used. (See \ref{ref:sublabel}.)
<Labels>+= \def\@subref#1{% \edef\@tempb{\@car\csname r@#1\endcsname\@nil}% \@tempb %\message{\string\@subref:\noexpand\@tempb}% }%
Defines\@subref
(links are to index).Used above; previous and next definitions.
*
\subpagepair
produces a {subpage}{page}
pair.
<Labels>+= \def\subpagepair#1{% % produces {subpage}{page} \@ifundefined{r@#1}% {{0}{0}}% {% \@ifundefined{2on\@pageref{#1}}% {{0}{\expandafter\expandafter\expandafter \@cdr\csname r@#1\endcsname\@nil}}% {\@nameuse{r@#1}}% }% }%
Defines\subpagepair
(links are to index).Used above; previous and next definitions.
*
\@pageref
is like \pageref
, but it expands to \relax
without a warning if the reference is undefined.
<Labels>+= \def\@pageref#1{% \expandafter\expandafter\expandafter \@cdr\csname r@#1\endcsname\@nil }%
Defines\@pageref
(links are to index).Used above; previous and next definitions.
*
\subsubsection{The \sublabel
macro}\label{ref:sublabel}
\sublabel
is called with just one argument, unlike \Label
.
This is because it computes the second argument to \Label
itself.
The argument is the label name.
The whole effect of this is that labels map to a pair of values, the
first of which is, in the case of ordinary labels, a user defined
value, and the second of which is the page number. Here, when using
`sublabels', the first argument becomes the subpage chunk number, and
this is automatically computed.
This is a major change from the algorithm used in the {\LaTeX} case,
where labels are mapped to a pair of values, as above, but where the
first value is itself a tuple value containing the subpage number, and
then the page number, follwed by the second value, which is the page
number again! This duplication seemed unnecessary, and so I removed
it. Perhaps there was a deeper need for it in {\LaTeX}? If so, I
couldn't find it in the documentation above. There is a need to also
practice what is preached!
\sublabel
is like the \label
command, except that it writes
\newsublabel
onto the .aux
file rather than \newlabel
.
<Labels>+= \def\sublabel#1{% %\@bsphack %\if@filesw {% \let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{% \write\@auxout{\string\newsublabel{#1}{{}{\thepage}}} }% \expandafter }% \@tempa %\if@nobreak \ifvmode\nobreak\fi %\fi %\fi %\@esphack }%
Defines\sublabel
(links are to index).Used above; previous and next definitions.
*
\nosublabel
creates a label with a sub-page part of~0.
<Labels>+= \def\nosublabel#1{% %\@bsphack %\if@filesw {% \let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{% \write\@auxout{\string\newlabel{#1}{{0}{\thepage}}}% }% \expandafter }% \@tempa %\if@nobreak \ifvmode\nobreak\fi %\fi %\fi %\@esphack }%
Defines\nosublabel
(links are to index).Used above; previous and next definitions.
*
\newsublabel
is the macro that does the important work. It is
called with the same sort of arguments as \newlabel
: the first
argument is the label name and the second is {
\LA ref
value}{
page number\RA}
. (Note that the only definition here
which needs to be global is the one which is, and that \global
is
redefined by \enddocument
, which will bite you if you use it\dots)
<Labels>+=
<definition of \newsublabel
>
Used above; previous and next definitions.
First we extract the page number into \this@page
.
<definition of \newsublabel
>=
\def\newsublabel#1#2{%
\edef\this@page{\@cdr#2\@nil}%
% definition continues
Defines\newsublabel
(links are to index).
Then we see whether it's changed from the value of \last@page
which was stashed away by the last \newsublabel
(or is \relax
if
this is the first one). If the page has changed, we reset the
counter \sub@page
telling us how many sub-labels there have been
on the page.
<definition of \newsublabel
>+=
\ifx\this@page\last@page
\else\sub@page=0
\fi
\edef\last@page{\this@page}%
\advance\sub@page by 1
Used below; previous and next definitions.
If we've had at least two on the page, we define the
2on
\LA{}{page no.}\RA{} macro to indicate the fact.
<definition of \newsublabel
>+=
\ifnum\sub@page=2
\global\@namedef{2on\this@page}{}%
\fi
Used below; previous and next definitions.
Then we write a normal \newlabel
with the sub-reference as the
normal reference value in the second argument.
<definition of \newsublabel
>+=
\edef\@tempa{%
\noexpand\newlabel{#1}%
{%
{\number\sub@page}{\this@page}%
}%
}%
\@tempa
}%
Used below; previous definition.
Define the \last@page
macro, which expands to the page number of
the last chunk number, or to \relax
if no previous chunk label
defined. \sub@page
counts the number of chunk labels on the
current page. \thepage
is simply a convenient redefinition.
<Labels>+= \def\last@page{\relax}% \newcount\sub@page \def\thepage{\the\pageno}%
Defines\last@page
,\sub@page
,\thepage
(links are to index).Used above; previous and next definitions.
Define the newlabel macro
<Labels>+= \def\newlabel#1#2{% \@ifundefined{r@#1}% {}% {\@warning{Label `#1' multiply defined}}% \global\@namedef{r@#1}{#2}% }% \def\@newlabel#1#2#3{% \NameDef{r@#1}{{#2}{#3}}% }%
Defines\@newlabel
,\newlabel
(links are to index).Used above; previous and next definitions.
*
Now for the referencing of subpages. The \subref
and
\subpageref
macros are equivalent. If the reference is actually
defined, it then goes on to check whether the control sequence
2on
\LA{}{page referenced}\RA{} is defined and sets the \ref
value to get a
etc.\ if so. The magic, of course, is in defining
the 2on
bit appropriately.
(AJH) Yes, but this doesn't exactly explain what the purpose of the
2on
bit is!
\subsubsection{Margin Identification of Chunks}
So that chunks can be easily identified, a marginal indication of the
chunk number is given. This is in the form of a page number and
subpage label, derived from looking up the label \subpageref
reference. The left end of the label is displaced \nwmarginglue
from the current left margin, and typeset according to the definition
of \nwtagstyle
. The kerning to the indented codemargin
\codemargin
should really be done in \moddef
, I think (AJH).
\moddef
is defined in the \LA kernel\RA part of this document.
The macros are invoked by the typical {\TeX} fragment:
\begin{verbatim}
\nwbegincode{2}
\sublabel{NWtt.5-cod4-1}
\nwmargintag{{\nwtagstyle{}\subpageref{NWtt.5-cod4-1}}}
\moddef{code~{\nwtagstyle{}\subpageref{NWtt.5-cod4-1}}}\endmoddef
\end{verbatim}
\nwmargintag
places a chunk label in the margin.
<Labels>+= \def\nwmargintag#1{% \leavevmode \llap{#1\kern\nwmarginglue\kern\codemargin}% }%
Defines\nwmargintag
(links are to index).Used above; previous and next definitions.
* *\subsubsection{Styles for Formatting Sub-page Numbers} Here a a couple of hooks for formatting sub-page numbers, which can be alphabetic, numeric, roman, or omitted.
<Labels>+= \def\@alphasubpagenum#1#2{#2\ifnum#1=0 \else\alph{#1}\fi} \def\@nosubpagenum#1#2{#2} \def\@numsubpagenum#1#2{#2\ifnum#1=0 \else.\arabic{#1}\fi} \def\@romansubpagenum#1#2{#2\ifnum#1=0 \else.\roman{#1}\fi} \def\nwopt@nosubpage{\let\nwthepagenum=\@nosubpagenum\nwopt@nomargintag} \def\nwopt@numsubpage{\let\nwthepagenum=\@numsubpagenum} \def\nwopt@alphasubpage{\let\nwthepagenum=\@alphasubpagenum} \def\nwopt@romansubpage{\let\nwthepagenum=\@romansubpagenum} \nwopt@alphasubpage
Definesalphasubpage
,nosubpage
,numsubpage
,\nwthepagenum
(links are to index).Used above; previous and next definitions.
*
*\subsection{{\tt WEB}-like chunk numbering}
We get the effect of WEB-like chunk numbers just by redefining
\sublabel
to use a counter instead of the current page number.
Since the numbers are all distinct, no sub-page number is ever used.
<Labels>+= \newcount\nw@chunkcount \nw@chunkcount=\@ne \def\weblabel#1{% {% \let\thepage\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{% \write\@auxout{% \string\newsublabel{#1}{{}{\number\nw@chunkcount}}% }% }% \expandafter }% \@tempa \global\advance\nw@chunkcount by \@ne \ifvmode\nobreak\fi }% \def\nwopt@webnumbering{% \let\sublabel=\weblabel \def\nwpageword{chunk}% \def\nwpageprep{in}% }%
Defines\nw@chunkcount
,\nwopt@webnumbering
,\weblabel
(links are to index).Used above; previous definition.
* % **** Cross Referencing ******************************************************** \section{Cross Referencing between Chunks} At the end of each code chunk, two pieces of cross referencing information are given. Since code chunk definition can be continued in other chunks, an indication of where the definition is continued is given. Other chunks using this chunk are also identified. The other piece of information given is a list of identifiers defined by the chunk, and where they are used, together with a list of identifiers used by this chunk and where they are defined. These useful bits of information are given in a `chunk comment', usually printed in a smaller font at the end of each code chunk:
<Cross Referencing of Chunks and Identifiers>= \def\nwcodecomment#1{% \penalty\nwcodepenalty \hskip-\codemargin \begingroup \rightskip=0pt plus1in \interlinepenalty\nwcodepenalty \small\rm #1\par\penalty\nwcodepenalty \endgroup }% \newskip\nwcodecommentsep\nwcodecommentsep=3pt plus 1pt minus 1pt \newif\if@firstnwcodecomment\@firstnwcodecommenttrue \newcount\nwcodepenalty\nwcodepenalty=1000
Defines\@firstnwcodecommentfalse
,\@firstnwcodecommenttrue
,\if@firstnwcodecomment
,\nwcodecomment
,\nwcodecommentsep
,\nwcodepenalty
(links are to index).
*
To handle this, information is written to the label file about chunks
and identifiers as they are processed. This information can then be
used by a second pass over the source text so that forward references
are properly handled.
Now we go about building the lists of definitions and uses, for
both chunks and identifiers. The macros involved are
\nwidentdefs
, \nwidentuses
for the identifier definition and use,
\nwalsodefined
for continued chunk definition, and \nwused
for
chunk use. Each of these takes a {\TeX} list as parameter (see later
for definition of a {\TeX} list, or see the {\it {\TeX}-in-Practice}
volumes.
Let's look next at the work done in the second pass, because this
processes the definitions written out in the above macros. It is the
macro \nwixadd
that does the work here. It takes three
parameters, the first of which is a macro that indicates whether we
have a definition or use. The second parameter is the identifier
itself, and the third parameter is the code chunk label wherein this
definition or use appears.
Suppose the identifier is {\it example}. We check to see if the name
*{\tt nwixl@example} is defined. If it is, then we have already seen
this identifier, and this use or definition (as indicated by the
marker macro) is appended to the list of use/definitions for the
identifier. This list is kept as the replacement text for the macro
named as above, that is, {\tt nwixl@example}.
If this name is not defined, then it is now, with the replacement
text given by {\marker{chunk label}}
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwixadd#1#2#3{% % #1 marker % #2 idlabel % #3 subpage label \if\NameDefinedConditional{nwixl@#2}% \expandafter\nwix@cons\csname nwixl@#2\endcsname{#1{#3}}% \else \global\NameDef{nwixl@#2}{#1{#3}}% \fi }%
Defines\nwixadd
(links are to index).Used above; previous and next definitions.
* *\subsection{Cross Referencing of Chunks} A simple case is where a code chunk is never referenced by any other chunk in this document. This is taken to be a root chunk. Note that multiple root chunks may be specified, since noweb allows code chunks to be extracted by name to separate files.
<Cross Referencing of Chunks and Identifiers>+= \def\nwnotused#1{% \nwcodecomment{Root chunk (not used in this document).}% }%
Defines\nwnotused
(links are to index).Used above; previous and next definitions.
*
Let's take \nwused
next. The {\TeX}-list of code chunk
labels is passed to the (sub)page listing macro.
<Cross Referencing of Chunks and Identifiers>+= \def\nwused#1{% \def\@nwtokens{#1}% \nwcodecomment{This code is used in \pagesl{\@nwtokens}.}% }%
Defines\nwused
(links are to index).Used above; previous and next definitions.
* Where a code fragment (such as {\LA\it Cross Referencing of Chunks and Identifiers\RA}) is multiply defined, a pointer(s) to the continuation chunks is given.
<Cross Referencing of Chunks and Identifiers>+= \def\nwalsodefined#1{% \def\@nwtokens{#1}% \nwcodecomment{% This definition is continued in \pagesl{\@nwtokens}.}% }%
Defines\nwalsodefined
(links are to index).Used above; previous and next definitions.
*
A list of definitions made by this code chunk is printed.
Each element in the TeX-list is processed by this macro, which itself
prints, for each identifier in the definition list, a list of places
where that identifier is used.
\nwix@id@uses
macro, which
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@id@uses#1#2{% {ident}{label} \nwix@usecount{#2}% \def\@id@uses{\nwix@uses{#2}}% \ifnum\nwix@counter>0 {% \advance\leftskip by \codemargin \nwcodecomment{{\tt #1}, used in chunk\@pagesl{\nwix@uses{#2}}.% }% }% \else \ifnw@hideunuseddefs \else {% \advance\leftskip by \codemargin \nwcodecomment{{\tt #1}, never used.}% }% \fi \fi }%
Defines\nwix@id@uses
(links are to index).Used above; previous and next definitions.
*
If definitions are unused, a message to this effect is normally
printed. This can be turned off by the option
\nwopt@hideunuseddefs
.
<Cross Referencing of Chunks and Identifiers>+= \newif\ifnw@hideunuseddefs\nw@hideunuseddefsfalse \def\nwopt@hideunuseddefs{\nw@hideunuseddefstrue}
Used above; previous and next definitions.
If we are not interested in the actual definitions, here just total
up the number of definitions added by this chunk. The current number
of uses is maintained in the global counter \nwix@counter
: this is
incremented by the number seen in this definition.
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@totaluses#1{% list of index pairs {% \count@=0 \def\\##1{% \nwix@usecount{\@cdr##1\@nil} \advance\count@ by\nwix@counter }% #1 \global\nwix@counter\count@ }% }%
Used above; previous and next definitions.
*\subsection{Cross Referencing of Identifiers}
As identifier definitions are encountered in the marked up source, a macro
\nwindexdefn
is issued to flag the definition. We add this
definition to the database, and cross reference it in this code chunk.
All index definitions and uses are associated with a label defined
with \sublabel
or \nosublabel
. Either the label is the
\sublabel
of the code chunk in which the definition or use
appears, or it is a \nosublabel
appearing in the middle of a
documentation chunk.
The macro \nwindexdefn
takes three parameters, the first two of
which denote the identifier. A distinction is made between the
printable name of the identifier, and a possibly sanitized version
used as a label. The macro adds this identifier to the list of
identifiers defined by the chunk whose label is given as the third
parameter. The main purpose of this macro is to write the definitions
to the label file: a second pass will then pick up the information for
actual printing.
<Cross Referencing of Chunks and Identifiers>+= % \nwindexdefn{printable name}{identifying label}{label of chunk} \def\nwindexdefn#1#2#3{% %\message{\string\nwindexdefn:#1:#2:#3}% \@auxix{\protect\nwixd}{#2}{#3}% }%
Defines\nwindexdefn
(links are to index).Used above; previous and next definitions.
*
Uses of identifiers are flagged by the macro \nwindexuse
, with
similar parameters to \nwindexdefn
.
<Cross Referencing of Chunks and Identifiers>+= % \nwindexuse{printable name}{identifying label}{label of chunk} \def\nwindexuse#1#2#3{% \@auxix{\protect\nwixu}{#2}{#3}% }%
Defines\nwindexuse
(links are to index).Used above; previous and next definitions.
*
The marker macros \nwixd
and \nwixu
flag definitions and
uses respectively within a list. By setting their definitions, the
list may be processed to count definitions or uses, generate various
layouts, and so on.
<Cross Referencing of Chunks and Identifiers>+= \def\nwixd#1{{\bf\subref{#1}}}% \def\nwixu#1{\subref{#1}}% \def\@auxix#1#2#3{% {marker}{id label}{subpage label} %\@bsphack %\if@filesw {% \let\nwixd\relax\let\nwixu\relax \def\protect{\noexpand\noexpand\noexpand}% \edef\@tempa{\write\@auxout{\string\nwixadd{#1}{#2}{#3}}}% \expandafter }% \@tempa %\if@nobreak \ifvmode\nobreak\fi %\fi %\fi %\@esphack }%
Defines\@auxix
,\nwindexdefn
,\nwindexuse
(links are to index).Used above; previous and next definitions.
*
Now for something a little more involved. Identifiers are defined in
the source by virtue of the hack of including a \verb.@ %def id1 id2.
line. This could be generated by other filters in the noweb
pipeline, such as finduses
(q.v.). Lines of this
form \verb.@ %def id1 id2. get translated by the noweave
pipe to
macro calls of the form:
\begin{verbatim}
\nwidentdefs{\\{{do}{do}}\\{{dont}{dont}}}
\end{verbatim}
and it is this macro which we now define. This macro counts the
number of definitions first, and if this is non-zero, prints the list
of identifiers using the auxiliary macro \nwix@id@uses
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwidentdefs#1{% list of index pairs \ifnw@hideunuseddefs\nwix@totaluses{#1}% \else\nwix@listcount{#1}% \fi \ifnum\nwix@counter>0 \nwcodecomment{Defines:}% {% \def\\##1{\nwix@id@uses ##1}% #1 }% \fi }%
Defines\nwidentdefs
(links are to index).Used above; previous and next definitions.
*
Here we count the number of identifiers in the argument. The list
processing template macro \\
is set to count each element of the
list.
<Cross Referencing of Chunks and Identifiers>+= \newcount\nwix@counter \def\nwix@listcount#1{% #1 is a TeX-list {% \count@=0 \def\\##1{\advance\count@ by 1}% #1% \global\nwix@counter=\count@ }% }%
Defines\nwix@listcount
(links are to index).Used above; previous and next definitions.
count just uses. Flag this by making \nwixu
the counting macro
\\
, and \nwixd
null, then calling \nwix@listcount
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@usecount#1{% \let\nwixd=\@gobble \def\nwixu{\\} \nwix@listcount{\nwix@uses{#1}}% }%
Defines\nwix@usecount
(links are to index).Used above; previous and next definitions.
count just definitions. Flag this by making \nwixd
the counting
macro \\
, and \nwixu
null, then calling \nwix@listcount
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@defcount#1{% \let\nwixd=\relax\let\nwixu=\@gobble \nwix@listcount{\nwix@defs{#1}}% }%
Defines\nwix@defcount
(links are to index).Used above; previous and next definitions.
* Macro to process the list of uses, printing out the code chunk locations where used. This macro is called for both identifier and chunk use lists.
<Cross Referencing of Chunks and Identifiers>+= \def\nwidentuses#1{% list of index pairs \nwcodecomment{Uses \let\\=\nwix@id@defs\commafy{#1}.}% }%
Defines\nwidentuses
(links are to index).Used above; previous and next definitions.
nwixs@c
and nwixs@i
are sorted lists of chunks and
identifiers, respectively.
<Cross Referencing of Chunks and Identifiers>+= \def\nwixadds#1#2{% %\message{\string\nwixadds:#1}% \@ifundefined{nwixs@#1}% {\global\@namedef{nwixs@#1}{\\{#2}}}% {\expandafter\nwix@cons\csname nwixs@#1\endcsname{\\{#2}}}% }% \let\nwixaddsx=\@gobbletwo
Used above; previous and next definitions.
\subsection{Cross Referencing (identifier cross-reference) support}
*\subsubsection{Tracking definitions and uses}
All index definitions and uses are associated with a label defined
with \sublabel
or \nosublabel
. Either the label is the
\sublabel
of the code chunk in which the definition or use
appears, or it is a \nosublabel
appearing in the middle of a
documentation chunk.
\subsubsection{New, improved index code}
There are two kinds of lists.
One kind is a generic list in which elements are preceded by \\
.
If the elements are index elements, they are {\it{
printable
identifier}{
label}
} pairs.
The other kind is a list of sub-page labels, in which each element is
preceded by either \nwixd
or \nwixu
.
The reference list for an identifier labelled {\it id}
is always called \nwixl@
{\it id}.
Most applications will work with reference lists by applying \\
either to the defs or to the uses.
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@uses#1{% {label} \def\nwixu{\\}% \let\nwixd\@gobble \@nameuse{nwixl@#1}% }% \def\nwix@defs#1{% {label} \def\nwixd{\\}\let\nwixu\@gobble\@nameuse{nwixl@#1}} \def\@gobble#1{}%
Defines\nwix@defs
,\nwix@uses
(links are to index).Used above; previous and next definitions.
*\subsubsection{Supporting a mini-index at the end of each chunk} When displaying identifiers used, show the identifier and its definitions.
<Cross Referencing of Chunks and Identifiers>+= \def\@car#1#2\@nil{#1}% \def\@cdr#1#2\@nil{#2}% \def\nwix@id@defs#1{% index pair {% {\tt \@car#1\@nil}% \def\\##1{~\subpageref{##1}}\nwix@defs{\@cdr#1\@nil}% }% }%
Defines\@car
,\@cdr
,\nwix@id@defs
(links are to index).Used above; previous and next definitions.
* The definitions section is a bit more complex, because it is omitted if none of the identifiers defined is ever used.
<Cross Referencing of Chunks and Identifiers>+= \def\nwix@totaluses#1{% list of index pairs {% \count@=0 \def\\##1{% \nwix@usecount{\@cdr##1\@nil}% \advance\count@ by\nwix@counter }% #1 \global\nwix@counter\count@ }% }%
Defines\nwix@totaluses#
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+= \def\nwopt@noidentxref{% %\let\nwidentdefs\@gobble %\let\nwidentuses\@gobble }%
Defines\nwopt@noidentxref
(links are to index).Used above; previous and next definitions.
* *\subsubsection{Support for chunk and identifier indices} The index in the back shows absolutely all the pages.
<Cross Referencing of Chunks and Identifiers>+= \def\nw@underlinedefs{% {list with \nwixd, \nwixu} \let\\=\relax\def\nw@comma{, }% \def\nwixd##1{% \\\underline{\subpageref{##1}}\let\\\nw@comma }% \def\nwixu##1{% \\\subpageref{##1}\let\\\nw@comma }% }%
Defines\nw@underlinedefs
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+= \newcount\@nwpagetemp
Defines\@nwpagetemp
(links are to index).Used above; previous and next definitions.
*
The sequence \@pagesl
makes a range of pages from a list of labels.
\subpages
works from a list of {{subpage}{page}}
.
<Cross Referencing of Chunks and Identifiers>+=
\newcount\@nwpagecount
\def\@nwfirstpagel#1{% label
\@ifundefined{r@#1}
{<tex warn of undefined reference to #1
and add page ??>}%
{\edef\@tempa{#1}\@tempa}%
}%
Defines\@nwfirstpagel
,\@nwpagecount
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+=
\def\@nwnextpagel#1{% label
\@ifundefined{r@#1}%
{<tex warn of undefined reference to #1
and add page ??>}
{\edef\@tempa{#1}\@tempa}%
}%
Defines\@nwnextpagel
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+= \def\@pagenumsl#1{% list of labels % doesn't include word `pages', commas, or `and' \gdef\nw@pages{}\@nwpagecount=0 \def\\##1{\@nwfirstpagel{##1}\let\\=\@nwnextpagel}#1% <add range to range list> \def\\{\let\\=~}\nw@pages }%
Defines\@pagenumsl
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+= \def\subpages#1{% list of {{subpage}{page}} \gdef\nw@pages{}\@nwpagecount=0 \def\\##1{% \edef\@tempa{\noexpand\@nwfirstpage##1}% \@tempa \def\\####1{% \edef\@tempa{\noexpand\@nwnextpage####1}% \@tempa }% }% #1% <add range to range list>\let\\=\relax \nwpageword \ifnum\@nwpagecount=1 \else s% \fi \space \commafy{\nw@pages}% }%
Defines\subpages
(links are to index).Used above; previous and next definitions.
<Cross Referencing of Chunks and Identifiers>+= \def\@nwaddrange{% <add range to range list> }%
Defines\@nwaddrange
(links are to index).Used above; previous and next definitions.
*
\nwpageword
and \nwpageprep
let you change the wording of
the cross-reference information.
<Cross Referencing of Chunks and Identifiers>+= \def\nwpageword{chunk} % was page \def\nwpageprep{in} % was on
Used above; previous and next definitions.
% **** Indexing ***********************************************
\section{Indexing}
\subsection{Indexing of Chunks}
At the end of the code and documentation listings, an index of all
chunk definitions can be made. This is invoked by the
\nowebchunks
macro.
<Chunk Index Construction>= \def\nowebchunks{% \@ifundefined{nwixs@c}% {\@warning{The are no \string\nowebchunks}}% %\else {% \begingroup \thenowebchunks\@nameuse{nwixs@c}% \endgroup }% }%
Defines\nowebchunks
(links are to index).
<Chunk Index Construction>+= \def\nowebchunks@external{% {% \let\nwixadds@i=\@gobble \def\nwixadds@c##1{\nw@onechunk##1}% \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% \begin{thenowebchunks}\@input{\jobname.nwi}\end{thenowebchunks}% }% \@namedef{nw@notdef}{{0}{(never defined)}}% }%
Defines\nowebchunks@external
(links are to index).Used above; previous and next definitions.
<Chunk Index Construction>+= \let\@@underline\underline \def\underline#1{% \relax \ifmmode \@@underline{#1}% \else $\@@underline{\hbox{#1}}$% \relax \fi }%
Defines\@@underline
,\underline
(links are to index).Used above; previous and next definitions.
<Chunk Index Construction>+= \def\thenowebchunks{% \vskip3pt \parskip=\z@\parindent=-10pt \advance\leftskip by 10pt \advance\rightskip by 0pt plus10pt \def\\##1{\nw@onechunk##1} }%
Defines\thenowebchunks
(links are to index).Used above; previous and next definitions.
* Typeset a list of chunks, with the definition occurrences underlined.
<Chunk Index Construction>+= \def\nw@chunkunderlinedefs{% {list of labels with \nwixd, \nwixu} \let\\=\relax\def\nw@comma{, }% \def\nwixd##1{% \\\underline{\subpageref{##1}}% \let\\\nw@comma }% \def\nwixu##1{% \\\subpageref{##1}% \let\\\nw@comma }% }%
Defines\nw@chunkunderlinedefs
(links are to index).Used above; previous and next definitions.
* Typeset one chunk name and its uses and definitions.
<Chunk Index Construction>+= \def\nw@onechunk#1#2#3{% % parameters: % #1 {name} % #2 {label of first definition} % #3 {list with \nwixd, \nwixu} %\message{Chunking #1:#2}% \@ifundefined{r@#2}% {\message{`#2' is undefined.}}% {% \indent\LA #1~{\nwtagstyle\subpageref{#2}}\RA %\if@nwlongchunks {~\nw@chunkunderlinedefs#3}% %\fi \par }% }%
Defines\nw@onechunk
(links are to index).Used above; previous definition.
<Cross Referencing of Chunks and Identifiers>+= \newif\if@nwlongchunks \@nwlongchunksfalse \let\nwopt@longchunks\@nwlongchunkstrue
Defines\if@nwlongchunks
,\@nwlongchunksfalse
,\@nwlongchunkstrue
(links are to index).Used above; previous and next definitions.
*
*\subsection{Indexing of Identifiers}
The macros here generate single lines of index material. Note that if
double column output is required, that is handled elsewhere by a
general purpose double column output routine.
The identifier index is built by a call on the \nowebindex
macro. The actual indices are generated by scanning the lists
contained in the expansion of the \nwixs@i
macro.
<Cross Referencing of Chunks and Identifiers>+= \def\nowebindex{% \@ifundefined{nwixs@i}% {% \@warning{The \string\nowebindex\space is empty}% }% {% \begingroup\thenowebindex \@nameuse{nwixs@i}% \endgroup }% }%
Defines\nowebindex
(links are to index).Used above; previous and next definitions.
*
\nowebindex
in turn invokes \thenowebindex
to create the
environment.
<Cross Referencing of Chunks and Identifiers>+= \def\thenowebindex{% \parindent=-10pt \parskip=\z@ \advance\leftskip by 10pt \advance\rightskip by 0pt plus1in\par%\@afterindenttrue \def\\##1{\nw@indexline##1}% }%
Defines\thenowebindex
(links are to index).Used above; previous and next definitions.
* Each line of the index is generated by this macro.
<Cross Referencing of Chunks and Identifiers>+= \def\nw@indexline#1#2{% {% \indent {\tt #1}: \nw@underlinedefs\@nameuse{nwixl@#2}\par }% }%
Defines\nw@indexline
(links are to index).Used above; previous and next definitions.
*
The information comes from the list nwisx@i
.
Here's a more efficient version for the external case:
<Cross Referencing of Chunks and Identifiers>+= \def\nowebindex@external{% {% \let\nwixadds@c=\@gobble \def\nwixadds@i##1{\nw@indexline##1}% \def\nwixaddsx##1##2{\@nameuse{nwixadds@##1}{##2}}% \begin{thenowebindex}% \@input{\jobname.nwi}% \end{thenowebindex} }% }%
Defines\nowebindex@external
(links are to index).Used above; previous and next definitions.
*
That list (nwisx@i
) is created by calls to \nwixlogsorted{i}
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwixlogsorted#1#2{% list data \toks0={#2}% \immediate\write\@auxout{\string\nwixadds{#1}{\the\toks0}}% \ifvmode\nobreak\fi }%
Defines\nwixlogsorted
(links are to index).Used above; previous and next definitions.
*
If an external index is used, we need a .nwi
file,
\nwixadds
is to be ignored, and we use \nwixaddsx
.
<Cross Referencing of Chunks and Identifiers>+= \def\nwopt@externalindex{% \ifx\nwixadds\@gobbletwo % already called \else \let\nwixaddsx=\nwixadds \let\nwixadds=\@gobbletwo \let\nowebindex=\nowebindex@external \let\nowebchunks=\nowebchunks@external \fi }%
Defines\nwopt@externalindex
(links are to index).Used above; previous definition.
*
% **** Support Routines ************************************************
\section{Support Routines}
\subsection{List Management Routines}
Lists of identifiers, etc., are managed as ``{\TeX} lists'', wherein
as sequence of values $a_0, a_1, \ldots, a_n$ is represented as the
text {\\{
$a_0$}\\{
$a_1$}
$\ldots$\{
$a_n$}}
.
Given a list #1
, append the new element #2
to it.
<Housekeeping and Support Routines>= \def\nwix@cons#1#2{% {list}{\marker{element}} {% \toks0=\expandafter{#1}% \def\@tempa{#2}% \toks2=\expandafter{\@tempa}% \xdef#1{\the\toks0 \the\toks2 }% }% }%
Defines\nwix@cons
(links are to index).
\subsubsection{Writing lists with commas and ``and''}
These macros are used to construct lists of things which are separated
by commas, except for the last pair of the list, whch are separated by
the word ``and''. You get one of
\begin{itemize}\itemskip=0pt
\item ``$a$''
*\item ``$a$ and $b$''
\item ``$a$, $\ldots$, $b$, and $c$''
\end{itemize}
Each element of the list has the macro \\
(whatever its current
definition happens to be) applied to it. The `list' is a standard
\TeX{} list, namely elements wrapped in \\{}
and concatenated
together. For example, ``$a$ and $b$'' is \\{a}\\{b}
.
<Housekeeping and Support Routines>+= \newcount\@commacount \def\commafy#1{% \begingroup \nwix@listcount{#1}% \@commacount=\nwix@counter \let\@comma@each=\\% \ifcase\@commacount \let\\=\@comma@each \or \let\\=\@comma@each \or \def\\{\def\\{ and \@comma@each}\@comma@each}% \else \def\\{% \def\\{, % \advance\@commacount by -1 \ifnum\@commacount=1 and~\fi \@comma@each }% \@comma@each }% \fi #1% \endgroup }%
Defines\@commacount
,\commafy
(links are to index).Used above; previous and next definitions.
*
With \commafy
under our belt, it is a simple matter to generate
a list of subpage references, as required by chunk cross referencing.
<Housekeeping and Support Routines>+= \def\pagesl#1{% list of labels \let\\=\nwpagel\commafy{#1}% }% \def\nwpagel#1{% \subref{#1}% }%
Used above; previous and next definitions.
*\subsection{Section, SubSection Headings, etc.}
These are macros to support headings and subheadings. They routine
which does all the work is \startsection
.
<Housekeeping and Support Routines>+= % \startsection{LEVEL}{INDENT}{BEFORESKIP}{AFTERSKIP}{STYLE}{HEADING} % #1 #2 #3 #4 #5 #6 % % LEVEL: depth; e.g. part=0 chapter=1 sectino=2... % INDENT: indentation of heading from left margin % BEFORESKIP: skip before header % AFTERSKIP: skip after header % STYLE: style of heading; e.g.\bf % HEADING: heading of the sectino % \def\startsection#1#2#3#4#5#6{% \par\vskip#3 plus 2in \penalty-200\vskip 0pt plus -2in \noindent{% \leftskip=#2 \rightskip=0.5true in plus 4em minus 0.5 true in \hyphenpenalty=9999 \exhyphenpenalty=9999 #5#6\par% }% \vskip#4% {% \def\code##1{[[}\def\edoc##1{]]}%\message{[#6]}% }% \settocparms{#1}% \def\themodtitle{#6}% {% \def\code{\string\code}\def\edoc{\string\edoc}% \edef\next{% \noexpand\write\cont{% \tocskip \tocline{% \hskip\tocindent\tocstyle\relax\themodtitle }% {% \noexpand\the\pageno }% }% }% \next % write to toc }% }%
Defines\startsection
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \def\settocparms#1{% \count@=#1 \ifnum\count@<1 \def\tocskip{\vskip3ptplus1in\penalty-100\vskip0ptplus-1in}% \def\tocstyle{\bf}% \def\tocindent{0pt}% \else \def\tocskip{}% \def\tocstyle{\rm}% \dimen@=2em \advance\count@ by \m@ne \dimen@=\count@\dimen@ \edef\tocindent{\the\dimen@}% \fi }%
Defines\settocparms
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \def\tocline#1#2{% \line{% {% \ignorespaces#1% }% \leaders\hbox to .5em{.\hfil}% \hfil \hbox to1.5em{\hss#2}% }% }%
Defines\tocline
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \def\chapter#1{% \vfil\eject \startsection{0}{0pt}{6ex}{3ex}{\frtbf\chapcenter}{#1}% }%
Defines\chapter
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \newcount \sectionnumber \sectionnumber=0 \def\headingfont{\Large\bf}% \def\section#1{% \advance\sectionnumber by 1 \subsectionnumber=0 \subsubsectionnumber=0 \def\sno{\number\sectionnumber}% \setbox0\hbox{\headingfont\sno\ }% \dimen0=\wd0 \def\titleline{\sno\ #1}% \startsection{1}{0pt}{4ex}{2ex}{\headingfont}{\titleline}% }%
Defines\section
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \newcount \subsectionnumber \subsectionnumber=0 \def\subheadingfont{\large\bf}% \def\subsection#1{% \advance\subsectionnumber by 1 \subsubsectionnumber=0 \def\ssno{\number\sectionnumber.\number\subsectionnumber}% \setbox0\hbox{\subheadingfont\ssno\enspace}% \dimen0=\wd0 \edef\titleline{\ssno\enspace#1}% \startsection{2}{0pt}{2ex}{1ex}{\subheadingfont}{\titleline}% }%
Defines\subsection
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \newcount \subsubsectionnumber \subsubsectionnumber=0 \def\subsubheadingfont{\normal\bf}% \def\subsubsection#1{% \advance\subsubsectionnumber by 1 \def\sssno{\number\sectionnumber.\number\subsectionnumber .\number\subsubsectionnumber }% \setbox0\hbox{\subsubheadingfont\sssno\enspace}% \dimen0=\wd0 \edef\titleline{\sssno\enspace#1}% \startsection{3}{0pt}{1ex}{0.5ex}{\subsubheadingfont}{\titleline}% }%
Defines\subsubsection
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \newcount \subsubsubsectionnumber \subsubsubsectionnumber=0 \def\subsubsubheadingfont{\normal\it}% \def\paragraph#1{% \advance\subsubsubsectionnumber by 1 \def\ssssno{\number\sectionnumber.\number\subsectionnumber .\number\subsubsectionnumber .\number\subsubsubsectionnumber }% \setbox0\hbox{\subsubsubheadingfont\ssssno\enspace}% \dimen0=\wd0 \edef\titleline{\ssssno\enspace#1}% \startsection{4}{0pt}{1.5ex}{0ex}{\subsubsubheadingfont}{titleline}% }% \let\subsubsubsection=\paragraph
Defines\paragraph
,\subsubsubsection
(links are to index).Used above; previous and next definitions.
<Housekeeping and Support Routines>+= \def\stylehook{}%
Used above; previous and next definitions.
The \today
macro generates today's date in the format 11 August
1995.
<Housekeeping and Support Routines>+= \def\today{% \number\day\space \ifcase\month \or % nothing for \month=0 January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December% \fi \space \number\year }%
Defines\today
(links are to index).Used above; previous definition.
*
% **** Finalization ****************************************************
\section{Finalization}
Redefine the \bye
macro to do all the work. Don't forget that we
redefined \bye
in the double column macro, so we have to do that
one as well.
<Finalizing and Washup>= \def\bye{% \closeout\@auxout \write\cont{}% ensure that the contents file isn't empty \closeout\cont \vfil\eject\pageno=-1 % new page causes contents to be really closed \topofcontents\readcontents\botofcontents \DSC@bye }% \def\topofcontents{% \vfil\mark{{\bf Contents}}% }% \def\botofcontents{}%
Defines\botofcontents
,\bye
,\topofcontents
(links are to index).
*
IMHO (AJH), rather than redefining \bye
, a better approach is to
define a separate macro \nwendprocessing
, and put all the windup
stuff in here. An explicit call to \nwendprocessing
should then
be generated by the markup filters. For the moment, I do nothing.
<Finalizing and Washup>+= \def\nwendprocessing{% finalize anything that needs it. }%
Used above; previous definition.
% **** Startup Processing **************************************** \section{Startup Processing} Now ready to go, time for centre bounce. First set up cross referencing:
<Startup Processing>= \catcode`\@=11 \newwrite\@auxout \InputCWithAt{\jobname.lab}% \catcode`\@=11 \immediate\openout\@auxout = \jobname.lab %\message{**** label processing done}% \edef\contentsfile{\jobname.toc } % file that gets table of contents info \def\readcontents{\expandafter\input \contentsfile} \newwrite\cont \openout\cont=\contentsfile \write\cont{\string\catcode`\string\@=11}% a hack to make contents
Defines\cont
,\readcontents
(links are to index).
*
Finally we make @
`other' again.
<Startup Processing>+= \catcode`\@=12
Used above; previous definition.
*\section{Miscellaneous Bits and Pieces not yet Documented} % **** other stuff not yet updated **********************************
<other stuff not yet updated>=
\def\@refpair#1{%
%\message{\string\@refpair:#1}%
\if\NameDefinedConditional{#1}%
\Ref{#1}%
\else
{0}{0}%
<tex warn of undefined reference to #1
>
\fi
}%
Defines\@refpair
(links are to index).
\subpagepair
produces a {subpage}{page}
pair.
<other stuff not yet updated>+= \def\subpagepair#1#2{% produces {subpage}{page} \@ifundefined{r@#1}% {{0}{0}}% {% \@ifundefined{2on\@pageref{#1}}% {{0}{\expandafter\expandafter\expandafter \@cdr\csname #1\endcsname\@nil}}% {\@nameuse{#1}}% }% }%
Defines\subpagepair
(links are to index).Used above; previous and next definitions.
<other stuff not yet updated>+= %\def\nwoutput#1{% % \nwcodecomment{This code is written to file % {\tt \@stripstar#1*\stripped}.}% %}% \def\@stripstar#1*#2\stripped{#1}
Used above; previous and next definitions.
<other stuff not yet updated>+= \def\@pagesl#1{% list of labels %\message{\string\@pagesl:\noexpand#1}% \gdef\nw@pages{}% \@nwpagecount=0% \def\\##1{% \@nwpagelref{##1}% %\@nwfirstpagel{##1}% %\let\\=\@nwnextpagel }% #1% \let\\=\relax %\nwpageword \ifnum\@nwpagecount=1% \else s% \fi ~% \commafy{\nw@pages}% }%
Defines\@pagesl
,\@stripstar
(links are to index).Used above; previous and next definitions.
<other stuff not yet updated>+= \def\swap@#1#2{{#2#1}}% \def\@nwpagelref#1{% %\message{\string\@nwpagelref:#1}% \edef\@pagelpageno{\NameUse{r@#1}}% \edef\@pagelsubpageno{\expandafter\nwthepagenum\@pagelpageno}% %\message{\string\@nwpagelref:\@pagelsubpageno}% \LeftAppendElement{\nw@pages}{\@pagelsubpageno}% %\message{\string\@nwpagelref:\noexpand\nw@pages}% }% \def\@nwpagel#1{\subref{#1},}%
Defines\@nwpagel
,\@nwpagelref
,\swap@
(links are to index).Used above; previous and next definitions.
<other stuff not yet updated>+= % scale cmbx10 instead of using cmbx12 because {\LaTeX} does, so fonts exist \font\twlbf=cmbx10 scaled \magstep1 \font\frtbf=cmbx10 scaled \magstep2 % These fonts don't work with xdvi!
Used above; previous and next definitions.
<other stuff not yet updated>+= \long\def\@ifundefined#1#2#3{% \expandafter\ifx\csname#1\endcsname\relax #2% \else#3% \fi}
Defines\@ifundefined
(links are to index).Used above; previous and next definitions.
<other stuff not yet updated>+= % % \chapcenter macro to produce nice centered chapter titles % \def\chapcenter{\leftskip=0.5 true in plus 4em minus 0.5 true in \rightskip=\leftskip \parfillskip=0pt \spaceskip=.3333em \xspaceskip=.5em \pretolerance=9999 \tolerance=9999 \hyphenpenalty=9999 \exhyphenpenalty=9999}
Defines\chapcenter
(links are to index).Used above; previous and next definitions.
*\let\begindocument=\relax The following code is largely transliterated from the LaTeX stuff.
<other stuff not yet updated>+= \def\protect{}% \def\@warning#1{\message{#1}}%
Used above; previous definition.
<tex warn of undefined reference to #1
>=
\@warning{Reference `#1' on page \the\pageno\space undefined}
Used above (1), below (2).
<tex warn of undefined reference to#1
and add page ??>= <tex warn of undefined reference to#1
>% \nwix@cons\nw@pages{\\{\bf ??}}%
Used above (1), below (2).
<add range to range list>= <set\@tempa
to page range(s), marked with\\
>% \edef\@tempa{\noexpand\nwix@cons\noexpand\nw@pages{\@tempa}}\@tempa
Used below (1), below (2), below (3).
<set\@tempa
to page range(s), marked with\\
>= \advance\@nwhipage by \m@ne \ifnum\@nwhipage=\@nwlopage \edef\@tempa{\noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}}% \else \count@=\@nwhipage \advance\count@ by \m@ne \ifnum\count@=\@nwlopage % consecutive pages \edef\@tempa{\noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwlosub}{\number\@nwlopage}}% \noexpand\noexpand\noexpand\\% {\nwthepagenum{\number\@nwhisub}{\number\@nwhipage}}}% \else <use rules from Chicago style manual>% \fi \fi
Used above.
<use rules from Chicago style manual>= \ifnum\@nwlopage<110 <normal range>\else \count@=\@nwlopage \divide\count@ by 100 \multiply\count@ by 100 \ifnum\count@=\@nwlopage <normal range>\else \count@=\@nwlopage \divide\count@ by 100 \@nwpagetemp=\@nwhipage \divide\@nwpagetemp by 100 \ifnum\count@=\@nwpagetemp % lo--least 2 digits of hi \multiply\@nwpagetemp by 100 \advance \@nwhipage by -\@nwpagetemp <normal range>% \else <normal range>% \fi \fi \fi
Used above.
<normal range>= \edef\@tempa{% \noexpand\noexpand\noexpand \\{\number\@nwlopage--\number\@nwhipage}% }%
Used above.
\vfill\eject
\section{Chunks}
\sublabel{ref:fred}
\nowebchunks
\vfill\eject
\section{Index}
\BeginDoubleColumns
\nowebindex
\EndDoubleColumns
*\vfill\eject
\section{To DO}
\enumerate
\item resolve (reintroduce) distinction between \label
and
\newlabel
, \sublabel
and \newsublabel
(see chunk
\subpageref{ref:setupcode}).
\item Should generate a warning message if labels change, to indicate
that {\TeX} should be rerun to get them right.
\endenumerate
\newsublabel
>: U1, D2, D3, D4, D5
\@tempa
to page range(s), marked with \\
>: U1, D2
#1
>: U1, D2, U3
#1
and add page ??>: U1, U2, D3
#1
>: U1, U2, D3