groff
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff] Re: gpic bug


From: Russ Cox
Subject: [Groff] Re: gpic bug
Date: Thu, 2 May 2002 10:35:17 -0400

The Plan 9 manual page is basically the appendix from CSTR116.
(I'm sure they both derived from the Unix manual page.)

They are both wrong about `with' productions.  I think we
agree there.  These are the WITH attribute rules, and have
been since 1985 at least.

attr:
        ...
        | WITH CORNER           { makeiattr(WITH, $2); }
        | WITH '.' PLACENAME    { makeoattr(PLACE, getblock(getlast(1,BLOCK), 
$3)); }
        | WITH '.' PLACENAME CORNER
                { makeoattr(PLACE, getpos(getblock(getlast(1,BLOCK), $3), $4)); 
}
        | WITH position         { makeoattr(PLACE, $2); }
        ...

PLACENAME is any C-style identifier beginning with an upper-case
letter or an underscore.  (First lower case letter => variable.)

The lex rules for CORNER look like this:

        <A>"."(e|east)          { yylval.i = EAST; return(CORNER); }
        <A>"."(r|right)         { yylval.i = EAST; return(CORNER); }
        <A>"."(w|west)          { yylval.i = WEST; return(CORNER); }
        <A>"."(l|left)          { yylval.i = WEST; return(CORNER); }
        <A>"."(n|north)         { yylval.i = NORTH; return(CORNER); }
        <A>"."(t|top)           { yylval.i = NORTH; return(CORNER); }
        <A>"."(s|south)         { yylval.i = SOUTH; return(CORNER); }
        <A>"."(b|bot|bottom)    { yylval.i = SOUTH; return(CORNER); }
        <A>"."(c|center)        { yylval.i = CENTER; return(CORNER); }
        <A>".start"             { yylval.i = START; return(CORNER); }
        <A>".end"               { yylval.i = END; return(CORNER); }
        <A>".ne"                { yylval.i = NE; return(CORNER); }
        <A>".se"                { yylval.i = SE; return(CORNER); }
        <A>".nw"                { yylval.i = NW; return(CORNER); }
        <A>".sw"                { yylval.i = SW; return(CORNER); }

        <A>top" "+of            { yylval.i = NORTH; return(CORNER); }
        <A>north" "+of          { yylval.i = NORTH; return(CORNER); }
        <A>bottom" "+of         { yylval.i = SOUTH; return(CORNER); }
        <A>south" "+of          { yylval.i = SOUTH; return(CORNER); }
        <A>left" "+of           { yylval.i = WEST; return(CORNER); }
        <A>west" "+of           { yylval.i = WEST; return(CORNER); }
        <A>right" "+of          { yylval.i = EAST; return(CORNER); }
        <A>east" "+of           { yylval.i = EAST; return(CORNER); }
        <A>center" "+of         { yylval.i = CENTER; return(CORNER); }
        <A>start" "+of          { yylval.i = START; return(CORNER); }
        <A>end" "+of            { yylval.i = END; return(CORNER); }

The last set is admittedly very weird.  I think it was only
intended to be used with these productions for place:

place:
          PLACENAME             { y = getvar($1); $$ = y.o; }
        | PLACENAME CORNER      { y = getvar($1); $$ = getpos(y.o, $2); }
        | CORNER PLACENAME      { y = getvar($2); $$ = getpos(y.o, $1); }
        | HERE                  { $$ = gethere(); }
        | last type             { $$ = getlast($1, $2); }
        | last type CORNER      { $$ = getpos(getlast($1, $2), $3); }
        | CORNER last type      { $$ = getpos(getlast($2, $3), $1); }
        | NTH type              { $$ = getfirst($1, $2); }
        | NTH type CORNER       { $$ = getpos(getfirst($1, $2), $3); }
        | CORNER NTH type       { $$ = getpos(getfirst($2, $3), $1); }
        | blockname
        | blockname CORNER      { $$ = getpos($1, $2); }
        | CORNER blockname      { $$ = getpos($2, $1); }
        ;

These too have been in place since 1985.  (The intent might have
been better served with a CORNERSUFFIX and CORNERPREFIX, of course.)

Thus, the following all work for me:

        .PS
        box with .top at (0,0)
        box with top of at (0,0)
        box with (0,0) at (0,0)
        [
                A: box at (1,1)
        ] with (0,0) at (0,0)
        [
                A: box
        ] with .A.n at (0,0)
        .PE

while

        .PS
        box with top at (0,0)
        .PE

doesn't.  I suspect that the grammar was cleaned up for
presentation in the manual and inadvertently changed.  It may
also be that the manual was written to a still older grammar.

The CSTR itself is clearly contradictory, since it suggests
in the grammar that the only with rules are things like "with n"
while the paper is littered with examples saying "with .n".

The middle of page 13 seems to suggest the extended usage
that we are discussing here:

        Blocks have the same compass corners as boxes (determined
        by the bounding box). It is also possible to position a block
        by placing either an absolute coordinate (like 0,0) or an
        internal label (like A) at some external point, as in

                [ ...; A: ...; ... ] with .A at ...

        By default, blocks join with other things as boxes do,
        at the center of the appropriate side.

If you need more information, let me know.  I don't presume
to know what you should do, of course, though I will note that
I've always found the "with position" production extremely
useful for positioning complicated blocks.

Russ

reply via email to

[Prev in Thread] Current Thread [Next in Thread]