[texhax] macro for numbering footnotes on each page

Adam Fenn acwfenn at hotmail.com
Sat May 29 10:10:47 CEST 2010

I found the file below (schrod.txh) in the texhax archives which resets the footnote number to 1 on each new page.
However, I cannot get it to work. I assume that ~ ought to be ^ but other than that I am at a loss. Can anyone here 
get it to work or have a more up to date plain TeX solution?


---------- cut here ------------------------------------------------------

% 1. (@*) Introduction.
% This macro set numbers footnotes subsequently on each page.
% It was written by J. Schrod on August 1, 1987.
% A footnote is typeset by the command \footnote. This command
% has one parameter, the text of the footnote. The macro
% package assumes that the conventions set up by PLAIN are in
% effect and is written primarily for use with PLAIN. With two minor
% changes it runs with LaTeX, but in LaTeX better approaches
% are available. Every place in the macro set where the used
% macro package is important has the line
%          @~ system dependencies @>
% added (WEB lives!). We use the private macros of PLAIN
% and for that reason we catcode the character `@' to letter.

\begingroup                             % to get the catcode change local

% 2. But let's regard first the implementation strategy. Because
%    the contents of one page is determined at (nearly) random places
% with an asynchronous invogation of the output routine, we can not
% give numbers to every footnote subsequently between output and
% output: a footnote at the top of a page will perhaps get a number
% before the output is triggered and there is no way to change
% this number. The problem is like forward references to text
% places and it is solved in a similar fashion. We need two TeX runs
% to get the numbering right but this is acceptable (who's got a
% finished text after one run?!). In the first run we gather up in
% a file the information where the footnotes are standing and in
% the second run we use this information.

% 3. This leads to our first code, the initialization of the
%    macro set. We need a file descriptor, \foot at file, which we
% use for the file interaction. The name of the file is built
% from the jobname and the suffix `.fot' (I hope that no macro
% package uses this suffix).
% @~ system dependencies @>
% The \init at footnote macro reads the contents of the footnote
% file if it exists (\ifeof returns true if the file doesn't
% exist). The description of the reading of this file
% (\read at foot@file) is deferred until we know the structure
% of the contents. After reading, the file is closed and we
% can open it for writing. For security, i.e. to have a defined
% minimal contents, we immediately write \relax to the file.
% In the end the macro defines itself to \relax to allow calling
% it again.
% Please note here the placement of `%' chars. Because we don't
% know if this macro is used only in vertical mode,
% (italics on)
%      every line not ending with a macro name is ended by a %.
% (italics off)

\newwrite\foot at file
\gdef\foot at file@name{\jobname.fot \relax}
\gdef\init at footnote{%
   \openin\foot at file=\foot at file@name
   \ifeof\foot at file  \closein\foot at file
   \else  \closein\foot at file
      \read at foot@file
   \immediate\openout\foot at file=\foot at file@name
   \immediate\write\foot at file{\relax}%
   \let\init at footnote=\relax

% 4. Now comes the first real macro package dependent part.
%    We want to set the footnote with a number in the superscript
% position (or with a corresponding symbol for that number). This
% is done with the macro \@footnote, which gets the number as its
% parameter. Below are the definitions for PLAIN TeX and LaTeX,
% the LaTeX part is commented out. To activate it, simply comment
% the PLAIN part out and remove the other `%'-signs.
% I think here is the place to state that I'm no LaTeX wizard.
% I don't know if there are any other (better) ways to get the
% footnote.

\let\@@footnote=\footnote        % original meaning of \footnote
 \gdef\@footnote#1{%             % set footnote with mark #1 (PLAIN)
%\gdef\@footnote#1{%             % set footnote with mark #1 (LaTeX)
%   \xdef\@thefnmark{#1}\@footnotemark\@footnotetext
%   }

% 5. (@*) Realisation.
% We must identify all footnotes if we write their numbers to
% the footnote file, so each footnote gets an unary name
% built with the counter \footno. The name is `f@<footno>',
% where <footno> is the footnote name number. This name
% building scheme has several disadvantages, e.g. the insertion
% of a new footnote destroys the knowledge of the former run
% about the following footnotes. In the beginning of every
% footnote \init at footnote is called to guarantee that the
% handling is initialized (this especially means that the
% footnote numbers are read in by the first footnote).

\newcount\footno                 % for generating footnote mark names
\newcount\@footno                % numbers of footnotes

% 6. It remains an open problem how to get the numbers there.
%    The footnote numbering must be initialized to zero in the
% output routine and every footnote must increment this footnote
% number. The only thing that is expanded during the output
% process is the output routine itself and the \write's, but
% the expanded tokens of \write are written out, not interpreted.
% Well, the idea is simple: We defer the counting to the second
% run and write the instructions that do this to the file. The
% counting is then done while reading the footnote file.
% That means that the output routine adds entries like
%    \@footno = 0
% and every footnote adds an entry that looks like
%    \advance\@footno by 1 \xdef\csname f@<footno> \endcsname{\number\@footno}
% where <footno> is replaced by the current footnote name number.
% The expansion of \footno must be made in \footnote, therefore
% we first define the macro \@dowrite which contains the \write
% and the expanded tokens which are to be put out. Every token
% that should not be expanded is prefixed by \string (resulting
% in character tokens that represent the token name) and a \space
% must be inserted to separate \csname from f.
% After writing the entry to the footnote file the \footnote
% macro defines the footnote mark to `?' if it is not already
% defined (from a previous run). To build the token name first
% and test afterwards an \expandafter is needed. At the end the
% \@footnote command is issued.

   \init at footnote
   \global\advance\footno by \@ne
      \write\foot at file{%
                  \string\csname\space f@\number\footno \endcsname{%
   \expandafter\ifx \csname f@\number\footno \endcsname \relax
      \expandafter\gdef \csname f@\number\footno \endcsname {?}%
   \@footnote{\csname f@\number\footno \endcsname}%

% 7. Now let's look at the intervention in the output routine. The
%    goal is to be (almost) independent from the used output routine.
% This is done by forming a layer around the originial output routine,
% but relies on the fact that the output routine is not altered
% by itself. For macro packages doing so an expansion of the
% output routine has to be made.
% @~ system dependencies @>
% Output routines serve for two purposes: they put out text
% to the file and they collect information. Usually macro packages
% communicate with the output routine by inserting special
% penalties. This macro set assumes that penalties above
% -\@maxpenalty are used to output text and penalties below
% -\@maxpenalty do other things (look at LATEX.TEX if you
% wonder what one can do in the output routine...). For every
% macro package \@maxpenalty has to be adjusted. If the precondition
% of one range of penalties for text output doesn't hold the
% following algorithm has to be altered. As with the definition
% of \@footnote, both the values for PLAIN TeX and for LaTeX are
% given, the LaTeX value is commented out.
% @~ system dependencies @>

 \mathchardef\@maxpenalty=20000  % maximal used penalty for text pages (PLAIN)
%\mathchardef\@maxpenalty=10000  % maximal used penalty for text pages (LaTeX)

% 8. We must insert a \write in front of the output. There are two
%    ways to do this. (1) We can shipout a box copy with the \write
% in it before the rest of the box (but this must be done in one
% shipout or an empty page will result). This approach needs deep
% intervention in the original output routine and is therefore not
% used. (2) We can trigger the output routine two times for each
% page. The first time we insert the \write, put the page back to
% the page builder and insert a special penalty, -\foot at penalty,
% which must be less than -\@maxpenalty and which must not be used
% by the macro package. The value 20001 is suitable for PLAIN TeX
% and LaTeX.
% @~ system dependencies @>
% The next time the \outputpenalty of the first time is restored
% and the original output routine is called. This handling is only
% done if text output appears, otherwise the original output routine
% is called directly. The following output routine evolves:
%  \output={
%     \ifnum \outputpenalty < -\@maxpenalty
%        \perhaps at restore@penalty
%        <original output>
%     \else
%        \global\@utputpenalty = \outputpenalty
%        \write\foot at file{ \@footno = 0 }
%        \unvbox 255
%        \penalty -\foot at penalty
%     \fi
%     }
% <original output> is the contents of the output token register
% before executing the statement below. To insert it in the new
% contents of the output register, the old output register must
% be evaluated before the assignment is done. We use \expandafter
% to skip over all preceding tokens.

\newcount\@utputpenalty       % save register for \outputpenalty
\mathchardef\foot at penalty=20001  % penalty not used in macro package

         \expandafter\outputpenalty \expandafter<%
      \expandafter\perhaps at restore@penalty
   \else  \global\@utputpenalty=\outputpenalty
      \write\foot at file{\@footno\z@}%
      \penalty -\foot at penalty
\gdef\perhaps at restore@penalty{%
   \ifnum \outputpenalty=-\foot at penalty

% 9. The last section is the reading of the footnote file. We have
%    to read in macros with names containing `@' characters. This
% will be done in horizontal mode, so we have to ignore lineends
% to discard undesired spaces.

\gdef\read at foot@file{%
      \catcode`\@=11 \catcode`\~~M=9 \relax
      \input \foot at file@name


---------- cut here ------------------------------------------------------

We want to hear all your funny, exciting and crazy Hotmail stories. Tell us now

More information about the texhax mailing list