Hi Ingo,

On Wed, Jun 04, 2025 at 07:14:47PM +0200, Ingo Schwarze wrote:
> Hello Alejandro,
> 
> Alejandro Colomar wrote on Wed, Jun 04, 2025 at 05:58:54PM +0200:
> 
> > +.P
> > +.SY int\~dl_iterate_phdr(
> > +.BI typeof(int\~(struct\~dl_phdr_info\~* info ,\~size_t\~ size ,
> > +.BI \~\~\~\~\~\~\~\~\~\~\~\~void\~* data ))
> > +.br
> > +.BI \~\~\~\~* callback ,
> > +.br
> > +.BI void\~* data );
> > +.YS
> 
> > which I'm relatively pleased with.
> 
> I find it hard to understand how anyone could possibly be pleased
> with the above code.  It certainly feels disgusting to me.

Hmmm, I'm not pleased, actually.  I should have said something like "I'm
not horrified by it, and I see no better alternatives".

What led me to this is working on nftw(3); that one is even worse than
this.  I have now this:

        .SY int\~nftw(
        .BI const\~char\~* dirpath ,
        .br
        .BI typeof(int\~(const\~char\~* fpath ,\~const\~struct\~stat\~* sb,
        .br
        .BI \~\~\~\~\~\~\~\~\~\~\~\~int\~ typeflag ,\~struct\~FTW\~* ftwbuf ))
        .br
        .BI \~\~\~\~* fn,
        .br
        .BI int\~ nopenfd ,
        .BI int\~ flags );
        .YS .

     int nftw( const char *dirpath,
               typeof(int (const char *fpath, const struct stat *sb,
                           int typeflag, struct FTW *ftwbuf))
                   *fn,
               int nopenfd, int flags);

which previously was

        .BI "int nftw(const char *" dirpath ,
        .BI "        typeof(int (const char *" fpath ", const struct stat *" sb,
        .BI "                    int " typeflag ", struct FTW *" ftwbuf ))
        .BI "            *" fn,
        .BI "        int " nopenfd ", int " flags );

     int nftw(const char *dirpath,
             typeof(int (const char *fpath, const struct stat *sb,
                         int typeflag, struct FTW *ftwbuf))
                 *fn,
             int nopenfd, int flags);

and in OpenBSD is

        .Ft int
        .Fo nftw
        .Fa "const char *path"
        .Fa "int (*fn)(const\ char\ *, const\ struct\ stat\ *, int, struct\ 
FTW\ *)"
        .Fa "int maxfds"
        .Fa "int flags"

     int
     nftw(const char *path,
         int (*fn)(const char *, const struct stat *, int, struct FTW *),
         int maxfds, int flags);

An issue I see with the OpenBSD version is not having names for the
parameters.  That makes the manual page more difficult to follow, IMO.
A reader can deduce to which parameter you're referring to because of
the type of the parameter, but I'd very much prefer explicitly calling
it by name.  This in turn results in the callback necessarily needing
more than one line.  Which in turn results in me needing to hand-tune
the formatting so that it is pretty.

Considering that I want names in the callback parameters, even if I had
4-space indentation like mdoc(7), I'd need several lines for a single
parameter, so I need manual intervention.

Now, I've done that in two pages so far, and I've transformed maybe an
80% of the project.  I haven't finished, so it might happen again in one
or two pages, but I don't expect this to be a common thing to do.

> The code uses a high-level macro which is supposed to be semantic.
> In spite of that, the code is littered with a large numbers of purely
> presentational low-level roff(7) constructions, which demonstrates
> that .SY is utterly unfit for its supposed job.
> 
>  * .P is not used in its semantical function here (there is no
>    paragraph of text), but abused as a presentational hack
>    to insert vertical spacing, similar to the .sp request,
>    which means that .SY fails at adequately controlling
>    vertical spacing.

In some (most) cases, I want function prototypes to not insert blanks
before them.  See man-pages(7), as written by Michael:

   SYNOPSIS
     Wrap  the function prototype(s) in a .nf/.fi pair to prevent fill‐
     ing.

     In general, where more than one function prototype is shown in the
     SYNOPSIS, the prototypes should not be separated by  blank  lines.
     However,  blank lines (achieved using .P) may be added in the fol‐
     lowing cases:

     •  to separate long lists  of  function  prototypes  into  related
        groups (see for example list(3));

     •  in other cases that may improve readability.

     In  the SYNOPSIS, a long function prototype may need to be contin‐
     ued over to the next line.  The continuation line is indented  ac‐
     cording to the following rules:

     (1)  If  there is a single such prototype that needs to be contin‐
          ued, then align the continuation line so that when  the  page
          is  rendered on a fixed‐width font device (e.g., on an xterm)
          the continuation line starts just below the start of the  ar‐
          gument  list  in the line above.  (Exception: the indentation
          may be adjusted if necessary to prevent a very long continua‐
          tion line or a further continuation line where  the  function
          prototype is very long.)  As an example:

              int tcsetattr(int fd, int optional_actions,
                            const struct termios *termios_p);

     (2)  But, where multiple functions in the SYNOPSIS require contin‐
          uation  lines, and the function names have different lengths,
          then align all continuation lines to start in the  same  col‐
          umn.   This provides a nicer rendering in PDF output (because
          the SYNOPSIS uses a variable width font where  spaces  render
          narrower than most characters).  As an example:

              int getopt(int argc, char * const argv[],
                         const char *optstring);
              int getopt_long(int argc, char * const argv[],
                         const char *optstring,
                         const struct option *longopts, int *longindex);


Michael and I agreed on those formatting conventions without much
discussion.

>  * Manual indentation with explicit space escape sequences
>    is not only extremely ugly, but whether it works as intended
>    is also output-device-dependent.

Yep.  The rule we have is that while PDF or other non-terminal devices
might have weird indentation, it will be consistent through a single
page.  (See the mention of PDF in man-pages(7).)

>  * And then we have the low-level .br requests.  Again, certainly
>    not the worst requests to sneak into a manual page, but in
>    the middle of a semantic macro?  Yikes.

As I said, I do want to control line breaks in parameters.  printf(3) is
an excellent example, and parameters that take up multiple lines --like
in ftw(3)-- are another good example.

> 
> Yours,
>   Ingo


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature

Reply via email to