Re: alx-0008 - Standardize strtoi(3) and strtou(3) from NetBSD

Alejandro Colomar <[email protected]> Thu, 20 Mar 2025 02:15:51 +0100
Newsgroups gmane.os.netbsd.devel.general
Message-ID <hgqg7m4leyaam3rmeidg7zl26vvnpe4braqgcbj27ggbtuif7s@q67pd2w3yw6b>
--wajlvynyceu6b5rr
Content-Type: text/plain; protected-headers=v1; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
From: Alejandro Colomar <[email protected]>
To: Paul Eggert <[email protected]>
Cc: Bruno Haible <[email protected]>, [email protected], 
	[email protected], [email protected], [email protected], 
	christos <[email protected]>, 
	=?utf-8?B?xJBvw6BuIFRy4bqnbiBDw7RuZw==?= Danh <[email protected]>, Eli Schwartz <[email protected]>, 
	Guillem Jover <[email protected]>, Iker Pedrosa <[email protected]>, 
	Michael Vetter <[email protected]>, Robert Elz <[email protected]>, [email protected], 
	Sam James <[email protected]>, "Serge E. Hallyn" <[email protected]>
Subject: Re: alx-0008 - Standardize strtoi(3) and strtou(3) from NetBSD
References: <mgcfwxfmv3kpfnkkf6uj63kx5tdzl64p2zg2us4ntsu6q5xkwj@k52z5yyiywoo>
 <18739733.sWSEgdgrri@nimes>
 <mvwnrmk2xf45ivyk4kzxdxuwdk67666yt3kwafck6vo4vq2lru@wkqmoqsacqkf>
 <3237498.fEcJ0Lxnt5@nimes>
 <[email protected]>
 <azfxoxklec7hlxll52ocmjiooq7bahy7xgrplbzmfbdygbubxc@upuk7c6bckto>
 <[email protected]>
 <2bk4qlhebhsgby4dda4fshocgoyixmqwqlnlgwcyzywkhpbeum@yr5ko5sv6ezy>
 <[email protected]>
MIME-Version: 1.0
In-Reply-To: <[email protected]>

Hi Paul,

On Wed, Mar 19, 2025 at 05:39:33PM -0700, Paul Eggert wrote:
> On 3/19/25 14:23, Alejandro Colomar wrote:
>=20
> > I think not reporting errors or warnings on saturation needs
> > justification.
>=20
> I don't know what "justification" means, but if it means a comment in the
> code I'm not sure I agree. Code where saturation is ordinarily what's wan=
ted
> shouldn't need a comment on each nontrivial line saying "Saturation is OK
> here."

Nah, not a source-code comment.  I think comments are usually evil.

More like you telling me now why you do it that way.  Actually, Bruno
send detailed responses in his last email, and I think that you'd
benefit from range checks, actually.  (See my response to his email.)
<https://lore.kernel.org/liba2i/6oyljvsenypqnrmgjbcwskqpdsag677h2dzay6hvfoo=
sju4224@3j7iczm4d7nw/T/#m38066e6eec63a8906e3cbfea275c9d7940d8df98>

> > Thanks, those changes look good.  BTW, what do you think of using
> > strspn(3) to simplify the c_isspace loop?
>=20
> Not worth the trouble. The loop is easier to read and debug than the strs=
pn
> call,

I guess I got used to the niceties of strspn(3) that I find it easier to
read.  It's a matter of taste, so ok.  :)

> which got some minor details wrong and fixing that would complicate
> the strspn code even further.

Do you mean that the implementation of strspn(3) was temporarily broken?
Or that the specification is bad?  I'm curious about it; could you
please clarify?

> > However, would you mind clarifying why you don't diagnose huge values in
> > the two places that you have updated?
>=20
> For this particular resource, a limit of ULONG_MAX has the same practical
> effect as a limit of ULONG_MAX + 1. Since the user can't tell the differe=
nce
> in behavior, it's fine to implement the larger limit as the smaller one,
> with no diagnostic.

According to Bruno, that limit is later clamped at a much lower value,
so I think that clamping could be moved up to the strtou(3) call.

Of course, that would mean having to implement strtou(3) for now, since
it's non-standard, so keeping it as is is simpler.  I was just trying to
say that if strtou(3) was standard in libc, then you could just use it
and simplify code, while making it more robust.

> A reasonable amount of GNU code works that way.

Ok.

> > 	struct foo {
> > 		long  val;
> > 		int   err;
> > 	}
> >=20
> > 	struct foo  ret;
> >=20
> > 	ret =3D f(time_t, ...);
> > 	if (ret.err !=3D 0)
> > 		err(1, "f");
> >=20
> > How do I know which variant of struct foo I need?
>=20
> I don't understand the question. There's no variant here; "variant" to me
> implies something like a union.
>=20
> But to fill in the details: C doesn't have a convenient notation for
> returning multiple values, you do need a struct. One convention is to use=
 a
> struct whose tag is the same as the function. So, something like this in a
> header file somewhere:
>=20
>     struct a2i { intmax_t val; ptrdiff_t len; }
>     a2i (char const *str, int base);

How do you get a uintmax_t?  Let's say I'm parsing an unsigned variable.

Also, how do I perform range checks in that call?  I need to specify
min and max limits.

> where LEN is negative for errors, and callers look like this:

How do you know how much has been parsed on error?  That's something
useful from strtoi/u(3).

>     struct a2i r =3D a2i(stringval, 10);
>     if (r.len < 0 || stringval[r.len])
>       err("a2i", stringval, r.len);
>=20
> the "|| stringval[r.len]" is needed only for callers that consider
> nonnumeric suffixes to be an error.

How do you perform range checks with this API?

> This is simpler than the pointers and "restrict"s in the proposed API.

Compare to

	QChar *alt_2(typename T,
	             T *restrict n, QChar *s, int base, T min, T max);


which can be called

	time_t  t;
	char    *end;

	errno =3D 0;
	end =3D alt_2(time_t, &t, s, 0, past, future);
	if (errno =3D=3D ERANGE && t =3D=3D past)
		goto too_old;
	if (errno =3D=3D ERANGE && t =3D=3D future)
		goto too_new;
	if (errno =3D=3D ENOTSUP)
		goto trailing_test;
	if (errno !=3D 0)
		goto hard_error;

	// All's good here.  Can use 't'.

	...
	return;

trailing_text:
	printf("Trailing text: %s", end);

which gives me for free checks that t is between past and future, and
of course saturation.  It also gives me for free type validation that t
is of type time_t.  It calls strtoi(3) if time_t is a signed type, and
strtou(3) if time_t is an unsigned type.

I can perform all the checks to errno that I want, or I can omit them if
I want.  This is the API I'm working on at the moment, and I don't think
a struct has anything more compelling than that.


Have a lovely night!
Alex

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

--wajlvynyceu6b5rr
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmfbbEEACgkQ64mZXMKQ
wqmwGg//Vj/SoNquvQ/kqgz+BUgGqrDZ2lVIh3ubfrdtee1aU1AwXqZ/So3CsggZ
ExHlIm96oJHYiQpz9Z+4CWOxEFVEtiNG2BLtOZpjV2uYqmE3a9e9G7zSVvmtZ1j0
Jkv6t1DYQrpyn5K1Ark//Yp25+J435dbiy6VvNVh0JzRrEucTG4QHreZVjCVB9ah
0F0hCCfsfMFF2aLoUQ5s7vDiNEJywGSEYXJNkFRyorOocvHnIAGTngss4sfIYhyE
tkYqS7DDnl6IA4xVn2UDuSMx7ItaOob5Hz3LMH6THQ1FE2e6IBdO9FQZIYWN/LWr
dYp30RwByKtpDIAl8jogrmYXnjbsrQ4yq8wfxwdu4UtVykcTM9GoP1Flade9ozqX
ygt5hHds6sVrWVyJ8Mgo5d2NuhgwB+v/1obPhEj6nBP072q5SKBvK6ctH9AMtW0B
WFXIudYxmUs0tbeBFcLzCoR8mCPBFjmZNSGkkzAHxYCxHLEmfWXXa0MQUYkO++yF
Ek9Oc8UQ5o3sH/8jBsjunNO4EveosZZQx3Xouyv0q5QRO3T6wxQgyqoj0m0NKT5m
RhlchZO6QBhOAiGvd9M75g0SGx3IXWKJKdnlfOI4mkZI8GWU1T8wNaDFTnpQTrGV
djvo9fdSnKDT5U8G2MBYHJ9bJcnmXDbNL9CnWmjAMvQJHVagpi0=
=dK0k
-----END PGP SIGNATURE-----

--wajlvynyceu6b5rr--