Hi Paul, On Wed, Mar 19, 2025 at 12:27:07PM -0700, Paul Eggert wrote: > On 2025-03-18 17:15, Bruno Haible wrote: > > If you don't want to do that, I can only repeat what I said in the previous > > mail: The proposal*does not achieve the goal* of avoiding the most common > > programmer mistakes. For a robust API, the success test should*only* involve > > testing the returned 'status', nothing else. > > This was my initial reaction as well. Although strtol has real problems, the > proposed interface is even more complicated and confusing and I suspect that > in practice it'd be misused even more often than strtol is. Please comment on the subthread where Bruno mentioned a number of places in gnulib and gettext where you use strtoul(3). I found there a few bugs, plus some ways to just simplify with strtou(3). The concerns about the case where one doesn't want to check ERANGE but wants to check ENOTSUP need justification. I suspect it's rather missing error handling in that code. I've never seen code calling strtoi/u(3) that wants that. > I suggest starting from scratch. I'm doing that in shadow-utils and liba2i, but I don't feel ready for standardization yet. In particular, I have two competing APIs in my head. > In particular, use a functional style, with > no side effects (no pointers-to-results). Just return the result you want, > as a struct, and keep the struct simple. Two struct components should > suffice: the scanned numeric value and a success/error indicator. That's going to complicate usage significantly. If I had invented strtoi/u(3) myself, I would have used errno instead of the *status parameter, but I don't feel too strongly about it to scrape that API. Regarding my APIs that are under development, here are the two alternatives: int alt_1(typename T, T *n, QChar *s, QChar **_Nullable endp, int base, T min, T max); if (alt_1(time_t, &time, s, NULL, 0, now, later) == -1) err(1, "alt_1"); which returns 0 on success, or -1 on error and sets errno on error, so usual libc behavior. QChar * alt_2(typename T, T *n, QChar *s, int base, T min, T max); errno = 0; alt_2(time_t, &time, s, 0, now, later); if (errno != 0) err(1, "alt_2"); which guarantees not setting errno on success, and sets it on error. It always returns 'end' (instead of having the output parameter *endp). Each one has benefits and drawbacks. But the number we do want it as an output parameter, since it gives us type safety: if you pass something of a type other than the one specified in the first parameter, you get a compiler error. I'm still undecided which one I prefer. So far, we're using alt_1 in shadow-utils. Feel free to comment about them. If you have any idea that will simplify usage or improve type safety, please present it, and show how the API would look like, and an example of use. But, these APIs are implemented in terms of strtoi/u(3), so even if we want to eventually get these APIs, we'd benefit of standardizing the NetBSD ones now, which will allow easier deployment of my wrappers. Have a lovely night! Alex -- <https://www.alejandro-colomar.es/>
Attachment:
signature.asc
Description: PGP signature