bugGNU roff - Bugs: bug #42675, [troff] \} treated as macro...

 
 

bug #42675: [troff] \} treated as macro argument

Submitter:  None
Submitted:  Thu 03 Jul 2014 09:35:26 PM UTC
   
 
Category:  Core Severity:  2 - Minor
Item Group:  Incorrect behaviour Status:  None
Privacy:  Public Assigned to:  None
Open/Closed:  Open Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Tue 09 Apr 2024 03:32:36 PM UTC, comment #12: 

comment #5:

>   This is not a bug, as the results of the test cases are
> according to the description of how macros work, CSTR #54,
> chapter 7.3.  Arguments.


That claim is undermined by the subsequent comment #10 demonstration that groff produces different results from DWB 3.3 and Unix V7 (which also intriguingly produce different results from each other).

But even if we don't presume that their behaviors are complaint with CSTR#54 section 7.3, I don't see anything there to indicate that a \} that performs flow control should also (see comment #11) be taken as a macro parameter.  Below is the complete text of that section.  Can you point to the wording that you think supports groff's overloading of \}?




7.3. Arguments. When a macro is invoked by name, the remainder of the line is taken to contain up to nine arguments. The argument separator is the space character (not tab), and arguments may be surrounded by double quotes to permit embedded space characters. Pairs of double quotes may be embedded in double-quoted arguments to represent a single double-quote character. The argument "" is explicitly null. If the desired arguments won’t fit on a line, a concealed newline may be used to continue on the next line. A trailing double quote may be omitted.
     When a macro is invoked the input level is pushed down and any arguments available at the previous level become unavailable until the macro is completely read and the previous level is restored. A macro’s own arguments can be interpolated at any point within the macro with \$N, which interpolates the Nth argument (1≤N≤9). If an invoked argument does not exist, a null string results. For example, the macro xx may be defined by

     .de xx    \" begin definition
     Today is \\$1 the \\$2.
     ..        \" end definition

and called by

     .xx Monday 14th

to produce the text

     Today is Monday the 14th.

     Note that each \$ was concealed in the definition with a prepended \. The number of arguments is in the .$ register.
     No arguments are available at the top (non-macro) level, within a string, or within a trap-invoked macro.
     Arguments are copied in copy mode onto a stack where they are available for reference. It is advisable to conceal string references (with an extra \) to delay interpolation until argument reference time.

Dave <barx>
Group Member
Sun 07 Apr 2024 11:22:34 AM UTC, comment #11: 

The output of Carsten's example in http://lists.gnu.org/r/groff/2014-07/msg00024.html tells us is that sections 1 and 3 call .A with no parameters; section 2 effectively calls it with one parameter, which is "\}".  Thus, the "\}" in section 2 of the code, being interpreted as a parameter to .A, should not be used for flow control.  So the second .if branch is never terminated.

This is testable by changing the ".if 1" in section 2 to ".if 0".  Then the entirety of section 3--still inside an unclosed open brace--should be skipped, as it's all inside the branch associated with ".if 0".

But this is not what happens.  Section 2 is indeed skipped, but section 3 runs as normal.

So the \} in section 2 is acting both as a literal parameter to macro .A and as flow control.  To me, this seems like the bug.

Dave <barx>
Group Member
Sun 07 Apr 2024 11:04:27 AM UTC, comment #10: 

comment #9:

> comment #8:
> > .if n \{.CA \}
> > .if n \{.CA \}
>
> Are those two lines intended to be identical?  In Ingo's original, the first one has no space between the macro call and the following backslash.


No.  Looks like I managed to screw that up.  Trying again...


$ cat EXPERIMENTS/count-args.roff
.de CA
\\n(.$
..
.if n \{.CA\}
.if n \{.CA \}
.if n \{.CA foo\}
.if n \{.CA foo \}



$ (cd ~/dwb && DWBHOME=. ./bin/nroff count-args.roff | cat -s)
0 0 1 1

$ (cd ~/heirloom && ./bin/nroff count-args.roff | cat -s)
0 0 1 1

$ ~/groff-1.22.3/bin/nroff ./EXPERIMENTS/count-args.roff | cat -s
0 1 1 2

$ /usr/bin/nroff ./EXPERIMENTS/count-args.roff | cat -s
0 1 1 2

$ ~/groff-stable/bin/nroff ./EXPERIMENTS/count-args.roff | cat -s
0 1 1 2

$ ./build/test-groff -T ascii ./EXPERIMENTS/count-args.roff | cat -s
0 1 1 2

PDP-11 simulator V3.8-1
Disabling XQ
@boot
New Boot, known devices are hp ht rk rl rp tm vt
: rl(0,0)rl2unix
mem = 177856
# Restricted rights: Use, duplication, or disclosure
is subject to restrictions stated in your contract with
Western Electric Company, Inc.
Thu Sep 22 22:15:29 EDT 1988

login: dmr
$ cat > count-args.roff
.de CA
\\n(.$
..
.if n \{.CA\}
.if n \{.CA \}
.if n \{.CA foo\}
.if n \{.CA foo \}
$ nroff count-args.roff | sed -n '/./p'
1 1 1 2


I venture no opinion at this point.

G. Branden Robinson <gbranden>
Group administrator
Sun 07 Apr 2024 10:54:28 AM UTC, comment #9: 

comment #8:

> .if n \{.CA \}
> .if n \{.CA \}


Are those two lines intended to be identical?  In Ingo's original, the first one has no space between the macro call and the following backslash.

Dave <barx>
Group Member
Sun 07 Apr 2024 07:26:56 AM UTC, comment #8: 

Ingo's exhibit, rewritten for AT&T portability, manifests the richest divergence of formatter behaviors that I've yet seen.

Input:


.de CA
\\n(.$
..
.if n \{.CA \}
.if n \{.CA \}
.if n \{.CA foo\}
.if n \{.CA foo \}


Command:


$ nroff ./count_args.roff


Output:

DWB 3.3 nroff:


0 0 1 1


Heirloom Doctools nroff:


0 0 1 1


Solaris 10 nroff:


1 1 1 2


GNU nroff:


1 1 1 2


Unix Version 7 nroff:


1 1 1 2


G. Branden Robinson <gbranden>
Group administrator
Sun 07 Apr 2024 06:33:57 AM UTC, comment #7: 

More wisdom from the email threads cited in comment #1 and comment #2:

Ralph observes (http://lists.gnu.org/r/groff/2014-07/msg00020.html) "as well as \n(.$ including \} in its count, it naturally follows that \$3, for example, is \}."  Carsten posted an example (http://lists.gnu.org/r/groff/2014-07/msg00024.html) illustrating this.

(Carsten says "it differs for use for normal output or for .tm", but I suspect that when the \} is not behind a .tm, the parser eats it.)

So the scope of the bug is not just the .$ register, but the set of parameters passed to a macro.  Updating the Summary field accordingly.

(And despite Bjarni's protestations, there is a bug here, but as the original comment points out, it might be in either behavior or groff documentation.  The document he cites in comment #5 is not part of groff.)

Dave <barx>
Group Member
Thu 04 Apr 2024 08:43:18 AM UTC, comment #6: 

original submission:

> Output with groff-1.22.2 on OpenBSD:
> 0 1 1 2


[The above is what was entered in the original submission; savannah interprets a leading "0" on a line as list markup, so it renders incorrectly in the original post.]

In the thread linked in comment #1, Carsten says (http://lists.gnu.org/r/groff/2014-07/msg00014.html) "Heirloom and Plan 9 have the same behavior."  But this was subsequently fixed in Heirloom (http://github.com/n-t-roff/heirloom-doctools/commit/3275936388e794a337f8d53426d2d394176bb3ba from September 2014), and indeed, when I run this in Heirloom today (with the -x3 flag, so that long macro names are recognized), I get the output "0 0 1 1".

Dave <barx>
Group Member
Tue 15 Feb 2022 11:29:35 PM UTC, comment #5: 

  This is not a bug, as the results of the test cases are according to
the description of how macros work, CSTR #54, chapter 7.3.  Arguments.

Bjarni Ingi Gislason <bjarniig>
Tue 01 Dec 2020 06:49:00 PM UTC, comment #4: 

  The examples do not show a bug in the software.

  They can serve as an exercise in understanding, to give people an
opportunity to test their "solving" skills, understanding of concepts.

  So nobody should "publish" a solution, as that deprives the readers
to tackle the exercise on their own.

  Otherwise their "brain software" does not grow to be better.

  Maybe this could be put in a file called "EXERCISES".

  This issue shows (me at least), that the examples are

1) too simple in one aspect

2) too complicated in another aspect.

  And people should start (to teach themselves) to ask themselves
questions to help themselves solve "mysteries".

Bjarni Ingi Gislason <bjarniig>
Fri 19 Sep 2014 07:49:47 PM UTC, comment #3: 

Although this bug seems to be in any existing *roff implementation, it should be fixed.  At the moment the \n(.$ register can't be used in a macro that may be invoked by other users because it has a random value, which depends on if the user writes

.A \}

or

.A
.\}

To make \n(.$ meaningful again and make it fit it's documentation this bug should be fixed.  This breaks "compatibility" with traditional *roff but only in cases where the input relies on side effects of this bug.  Because of it's random nature such cases are unlikely.

Carsten Kunze <carstenkunze>
Group Member
Tue 29 Jul 2014 11:18:22 AM UTC, comment #2: 
Anonymous
Tue 29 Jul 2014 11:16:02 AM UTC, comment #1: 
Anonymous
Thu 03 Jul 2014 09:35:26 PM UTC, original submission:  

(Attention: This may or may not be a bug! It could have been intentionally be introduced to groff to implement traditional nroff behavior perfectly. In this case it should be added to the documentation only.)

If a macro is used as the last statement of a conditional statement block (a block enclosed in \{ and \}), the closing \} is on the same line as the macro call and there is white space before \} the register .$ is increased by 1.

How to reproduce (thanks to Ingo Schwarze):

Minimal input file:
.de count_args
\\n(.$
..
.if n \{.count_args\}
.if n \{.count_args \}
.if n \{.count_args foo\}
.if n \{.count_args foo \}

Run this through:
groff -Wall -Tascii

Output with groff-1.22.2 on OpenBSD:

  1. 1 1 2
Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by gbranden (Posted a comment)
  • -email is unavailable- added by barx (Posted a comment)
  • -email is unavailable- added by bjarniig (Posted a comment)
  • -email is unavailable- added by bgarrigues (Updated the item)
  • -email is unavailable- added by carstenkunze (Posted a comment)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 5 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-04-07 gbranden Summary\} considered as macro argument [troff] \} treated as macro argument
    2024-04-07 barx Summary\} considered as macro argument regarding register .$ \} considered as macro argument
    2018-11-26 bgarrigues CategoryNone Core
        Severity3 - Normal 2 - Minor
        Item GroupNone Incorrect behaviour

    Back to the top

    Powered by Savane 3.13-4448.
    Corresponding source code