Hi Lennart,

I composed this back in February but postponed it, and I don't know
remember why.

At 2024-02-26T14:40:53+0000, Lennart Jablonka wrote:
> Quoth G. Branden Robinson:
> > I'm attaching my progress so far.
> 
> Nice!  I guess I’ll drop a few comments on it.  (Uncommented hunks
> omitted.)

No worries.

> > +    const int bufsz = len + sizeof msg1 + sizeof msg2 + 1 /* `\0` */;
> 
> bufsz should be size_t.  len is size_t, the sizeof expressions are
> size_t, and calloc takes size_t.

Yup.  You can tell I'm old, instinctively using an `int` instead of a
proper type.

> > +    char *errbuf = static_cast<char *>(calloc(bufsz, sizeof (char)));
> > +    (void) snprintf(errbuf, bufsz, "%s%s%s", msg1, terminal_type, msg2);
> 
> You could simplify that string handling using any of
>   • snprintf(malloc((size = snprintf(NULL, 0, …))), size, …),
>   • asprintf,
>   • the string class,
>   • the std::string class,

The last is not desirable, I think, until and unless we overhaul groff
to drop its own string class and use std::string _everywhere_.  I
shudder at the potential horrors of mixing up objects of these two
classes.

Apart from that, I dither over when and where to use C strings vs. groff
strings in the code.  I have groped in vain for an organizing principle
that would tell me, apart from "I need to call a standard libc function
that expects a C string".

> but …
> 
> > +    const char no_database[] = "terminfo database entry not found";
> > +
> > +    switch (err) {
> > +    case -1:
> > +      fatal(no_database);
> > +      break;
> > +    case 0:
> > +      fatal(errbuf);
> 
> Did I miss something on why you’re allocating the error buffer even if
> never used (err == 1), not freeing it in that case, and introducing a
> bug à la printf(user_input) (when TERM=%)

Insufficient attention on my part, most likely.

> instead of doing:
>
>       fatal("entry for '%1' not found in terminal database", terminal_type);

I'm sure I thought I had a reason at the time, but I don't recollect it
now.

> For the record, I think fatal() should be a simple wrapper for
> vfprintf.

That's not up to grotty.  `fatal()` is defined by libgroff and I would
prefer to land this change with no disturbance to any other part of the
system.  It should be easier to detect and remedy regressions that way.

https://git.savannah.gnu.org/cgit/groff.git/tree/src/libs/libgroff/error.cpp?h=1.23.0#n123

> > +  if (tigetflag("hc")) {
> 
> Why are you using tigetflag instead of accessing the long names
> defined by term.h?  They do seem a little underspecified by X/Open
> Curses, but do exist, both there, somewhat, and in the
> implementations.

1.  I prefer narrow interfaces to broad ones;
2.  It seems clear enough;
3.  It communicates the type of the capability.

On the other hand, I also prefer communicative identifiers to cryptic
ones, and even terminfo codes (_usually_ limited to 5 characters) are on
the cryptic side.

So, not a hill I mean to die on.

> > +    // hardcopy terminal
> > +    do_sgr_italics = false;
> > +    do_reverse_video = false;
> > +
> > +    if (want_sgr_italics) {
> > +      if (want_capability_warnings)
> > +   warning("terminal type %1 is incapable of SGR italics",
> > +           terminal_type);
> 
> Above, you 'quoted' terminal_type; here, you don’t.

Good catch--thank you!

Regards,
Branden

Attachment: signature.asc
Description: PGP signature

Reply via email to