URL: <https://savannah.gnu.org/bugs/?61632>
Summary: [me] delayed text numbering doesn't seem to quite work Project: GNU troff Submitted by: gbranden Submitted on: Tue 07 Dec 2021 01:56:19 PM UTC Category: Macro - me Severity: 3 - Normal Item Group: Incorrect behaviour Status: In Progress Privacy: Public Assigned to: gbranden Open/Closed: Open Discussion Lock: Any Planned Release: None _______________________________________________________ Details: The "delayed text" feature of me(7) has a somewhat mysterious name but really it seems to be almost ideal for endnotes. Or it would be if it didn't have a bug that prevents incrementation of the note numbers before the first emission of delayed texts (endnotes). Input: $ cat delayed.me .pp paragraph 1 .(d \*# foo .)d .(d \*# bar .)d .pd .(d \*# baz .)d .pp paragraph 2 .(d \*# qux .)d .pd .pp paragraph 3 Heirloom Doctools troff output (e.tmac 2.14): $ ./bin/nroff -me ./delayed.me |cat -s paragraph 1 [1] foo [1] bar paragraph 2 [1] baz [2] qux paragraph 3 (I've snipped extra lines at the end; for some reason this version of me(7) emits invisible [backspaced-over] garbage, and this fools "cat -s". This doesn't affect later versions of me(7) so I'll spend no more time on it.) groff 1.22.4 me(7) output: $ nroff -me EXPERIMENTS/delayed.me | cat -s paragraph 1 [1] foo [1] bar paragraph 2 [1] baz [2] qux paragraph 3 Root-cause analysis: Allman appears to _nowhere_ interpolate auto-incrementing registers in e.tmac such that the incrementation will apply (see e.tmac 8.1 from 4.4BSD <https://svnweb.freebsd.org/csrg/share/me/tmac.orig_me?revision=61635&view=co>), despite their obvious utility for things like the .sh section number components and footnote numbers. Maybe the feature was broken in the troff available to him. Instead, what he does is set a mark register with `\k`: '#' for delayed text and '*' for footnotes, and embeds this in string definitions of the same name which also interpolate the footnote/delayed text number. The mark is never set if the string is never emitted, which I think explains some curious language in {me,}ref.me about how these numbers are incremented if they've been "referenced". But even this does not work in the case of delayed text, as seen above. Only after `.pd` has been called the first time does the incrementation occur. Here's what happens at initialization: .nr $d 1 1 \" delayed text number .ds # [1]\k#\" \" delayed text "name" An auto-incrementing register `$d` is set up, but it is _never_ interpolated with `\n+($d`. The `#` string is defined, and if it is ever interpolated, the horizontal position will be stored in register `#`. Here are the macros that start, end, and emit delayed text. .de (d \" *** begin delayed text .am |d )d .sp \\n(bsu .. . .de )d \" *** end delayed text .if \\n# \ . nr $d +1 .ds # [\\n($d]\k# .rr # .. . .de pd \" *** print delayed text .|d .rm |d .nr $d 1 1 .ds # [1]\k# .. Notice how in the delayed-text-closing macro `)d`, the `#` string is defined again...but it _still hasn't been interpolated_. One could argue that this was a deliberate design choice, that Allman meant for people to be able to accumulate a single "item", in some sense, of delayed text in stages...but this approach would only work for the first batch of delayed texts, say for the first chapter. When those are emitted, the `#` string is interpolated and the `#` _register_ comes to know sin (is assigned a nonzero value). (Observe that the `#` register is never modified except by further interpolations of the `#` string.) Moreover, there's an easier way to achieve that effect: simply don't interpolate the `#` string inside the delayed text except when you want it, and/or manage the value of the `$d` register yourself. Both are documented in the reference manual and extend an invitation thus. To me this seems like unintended behavior arising from failure to leverage auto-incrementing registers. One might wonder why footnotes don't exhibit the same problem. Observe that there is no `pf` macro counterpart to `pd`. Footnotes, being at the foot of the page, don't rely on the user to call a macro to emit then; this is handled automatically by me(7)--though an enterprising user can defeat it, of course, by clobbering package internals. I have a fix in preparation. Here is the output. $ nroff -M./tmac -me EXPERIMENTS/delayed.me | cat -s paragraph 1 [1] foo [2] bar paragraph 2 [1] baz [2] qux paragraph 3 _______________________________________________________ Reply to this item at: <https://savannah.gnu.org/bugs/?61632> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/