summaryrefslogtreecommitdiff
path: root/info/digests/texhax/txh/schrod.txh
blob: d9ec586199ffde740fd7e1b34f63c55130017329 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
 4-Aug-87 23:16:27-PDT,14596;000000000000
Return-Path: <XITIJSCH%DDATHD21.BITNET@forsythe.stanford.edu>
Date:     04. August 1987,  17:04:55 (CET)
From: XITIJSCH%DDATHD21.BITNET@forsythe.stanford.edu
Subject:  Re: footnote numbering
To: TEXHAX@score.stanford.edu


In the TeXhax issue #60 Malcolm Brown asked for a possibility
to number footnotes subsequently on each page. He didn't state
if he needs this possibility, i.e. these macros, in a special
environment. In my eyes this is a nice small exercise to show
the development of TeX macros and therefore I send you this
contribution.

First I introduce a macro set to number footnotes subsequently
on each page. This macro set is written with the concept of
literate programming in mind and is portable in the manner that few
changes have to be made to the macros to get them running with
every macro package that uses the PLAIN definitions (LaTeX does).
The macro set has been tested with PLAIN TeX, LaTeX and an other
macro package of my own, always with correct results.
But I have only spent a few hours to write and test the macros,
so don't blame me if errors occur.

After introducing the macro set I close with some remarks on
TeX macro development, i.e. in TeX programming and I also
describe possible improvements to the macros and an other
solution strategy using LaTeX.


----------------------------------------------
macro set for numbering footnotes on each page
---------- 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
\catcode`\@=11



% 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@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@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@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@file
\gdef\foot@file@name{\jobname.fot \relax}
\gdef\init@footnote{%
   \openin\foot@file=\foot@file@name
   \ifeof\foot@file  \closein\foot@file
   \else  \closein\foot@file
      \read@foot@file
   \fi
   \immediate\openout\foot@file=\foot@file@name
   \immediate\write\foot@file{\relax}%
   \let\init@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)
    \@@footnote{\hbox{$~{#1}$}}%
    }
%\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@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.


\gdef\footnote{%
   \init@footnote
   \global\advance\footno by \@ne
   \edef\@dowrite{%
      \write\foot@file{%
         \string\advance\@footno\@ne
         \string\expandafter\xdef
                  \string\csname\space f@\number\footno \endcsname{%
            \string\number\@footno
            }%
         }%
      }%
   \@dowrite
   \expandafter\ifx \csname f@\number\footno \endcsname \relax
      \expandafter\gdef \csname f@\number\footno \endcsname {?}%
   \fi
   \@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@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@restore@penalty
%        <original output>
%     \else
%        \global\@utputpenalty = \outputpenalty
%        \write\foot@file{ \@footno = 0 }
%        \unvbox 255
%        \penalty -\foot@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@penalty=20001  % penalty not used in macro package

\output=\expandafter{%
   \expandafter\ifnum
         \expandafter\outputpenalty \expandafter<%
               \expandafter-\expandafter\@maxpenalty
      \expandafter\perhaps@restore@penalty
      \the\output
   \else  \global\@utputpenalty=\outputpenalty
      \write\foot@file{\@footno\z@}%
      \nobreak
      \unvbox\@cclv
      \penalty -\foot@penalty
   \fi
   }
\gdef\perhaps@restore@penalty{%
   \ifnum \outputpenalty=-\foot@penalty
      \global\outputpenalty=\@utputpenalty
   \fi
   }



% 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@foot@file{%
   \begingroup
      \catcode`\@=11 \catcode`\~~M=9 \relax
      \input \foot@file@name
   \endgroup
   }


\catcode`\@=12
\endgroup





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


For the use of the above macro set the following fact must be
obeyed:

      IT IS STATED EXPLICITLY THAT THE COMMENTS ARE AN INTEGRAL
      PART OF THIS MACRO SET. IF THE MACRO SET IS ALTERED THE
      COMMENTS HAVE TO BE ALTERED, TOO. THEY MUST NOT BE DELETED.

The writing of TeX macros is a task of programming. The computer
science community has struggled for years to encourage structured
program development. The idea of literate programming is promoted
more and more (e.g. in the CACM).

      WHY DO WE THROW ALL THIS AWAY WHEN TeX MACROS ARE WRITTEN??

It is my opinion that the only satisfactory way to write TeX
macros which can be maintained is to use the principles of
literate programming: describing the macros for a human reader,
not for TeX. (Perhaps the time will come, when we get a TeX-WEB.)

It could be said very much about this topic, but back to the
macros. They are not fully developed, some features are still
missing, e.g. warnings when new footnotes are inserted or
when footnote numbers have been changed. Other improvements
can be made on the construction of the footnote names. By
involving section numbers or analogous numbers the ``running
away'' of the footnote numbers (caused by the insertion of a
new footnote) can be limited.

Scanning through the LaTeX source it seems to me that the
same realization idea can be implemented by writing appropriate
\newlabel commands to the auxiliary file and referencing
them. But I'm not sure---perhaps L.Lamport can state a comment.


Well, this has become a rather long piece. I hope, it helps you.


                              Joachim Schrod

----------------------------------------------------------------

       TH Darmstadt
       Institut fuer Theoretische Informatik
       Joachim Schrod
       Alexanderstr. 24

       D-6100 Darmstadt
       West Germany

-------