Re: [SC22WG14.29900] alx-0008 - Standardize strtoi(3) and strtou(3) from NetBSD

Alejandro Colomar <[email protected]> Tue, 18 Mar 2025 21:18:50 +0100
Newsgroups dev.linux.lists.liba2i
Message-ID <apcaf4epns6px3d2ve2kfxxt57qo7wysvb5o36hi77dt75y6ya@bug7eieb6oti>
--u45phu363kshup5b
Content-Type: text/plain; protected-headers=v1; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
From: Alejandro Colomar <[email protected]>
To: Joseph Myers <[email protected]>
Cc: [email protected], [email protected], [email protected], 
	[email protected], [email protected], Bruno Haible <[email protected]>, 
	christos <[email protected]>, 
	=?utf-8?B?xJBvw6BuIFRy4bqnbiBDw7RuZw==?= Danh <[email protected]>, Paul Eggert <[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: [SC22WG14.29900] alx-0008 - Standardize strtoi(3) and strtou(3)
 from NetBSD
References: <[email protected]>
 <[email protected]>
MIME-Version: 1.0
In-Reply-To: <[email protected]>

Hi Joseph,

Thanks for the feedback!

On Tue, Mar 18, 2025 at 05:20:19PM +0000, Joseph Myers wrote:
> On Tue, 18 Mar 2025, Alejandro Colomar wrote:
>=20
> >     7.24.2  Numeric conversion functions
> > 	New section _before_ 7.24.2.2 (The atof function).
>=20
> You're missing corresponding <wchar.h> functions.

As with other proposals, I prefer leaving it for a different paper.
I'm not an expert in wchar stuff.

> Maybe there should also be a reference to N3183 (discussed in Strasbourg)=
=20
> - which dealt with UB for numeric conversions in scanf rather than strto*=
,=20
> but still seems related to this proposal.

I have something in mind about it.  My idea was to change the definition
of atoi(3) et al. to be in terms of strtoi(3):

	int
	atoi(const char *s)
	{
		int  n, e;

		n =3D strtoi(s, NULL, 10, INT_MIN, INT_MAX, &e);
		errno =3D e ?: errno;

		return n;
	}

Which would make atoi(3) behave just like one would expect.
And then define scanf(3) %d in terms of atoi(3).

I'll add a 'Future directions' section mentioning that.

> > 	While all this section is new, some text is pasted verbatim from
> > 	7.24.2.8.  I'll write that text as if it was already existing
> > 	in the diff below.
> >=20
> > 	I also renamed the parameters of strtol(3):
> > 	nptr =3D> s	Because it's a string, not a pointer to a number.
> > 	endptr =3D> endp	It's shorter and just as readable (if not more).
> >=20
> > 	@@
> > 	+7.24.2.*  The <b>strtoi</b> and <b>strtou</b> functions
> > 	+
> > 	+Synopsis
> > 	+1	#include <stdlib.h>
> > 	+	intmax_t strtoi(const char *restrict s, char **restrict endp, int ba=
se,
> > 	+	    intmax_t min, intmax_t max, int *rstatus);
> > 	+	uintmax_t strtou(const char *restrict s, char **restrict endp, int b=
ase,
> > 	+	    uintmax_t min, uintmax_t max, int *rstatus);
>=20
> intmax_t and uintmax_t are not declared in <stdlib.h>.  Either the=20
> synopsis should mention <stdint.h> as well, or those types should be adde=
d=20
> to the ones declared by that header.

Hmmm, my bad.  This function is from <inttypes.h>.  I should move it.

> I'm also concerned that the names sound like int / unsigned int analogues=
=20
> of strtol, but aren't.

I don't get to choose the name.  Anyway, my plans are to erradicate
strtol(3) from history, eventually.

I'm not especially concerned because the number and type of arguments is
significantly different that mistakes are unlikely to happen; and I also
don't have a better name for it.

> > 	+Description
> > 	+2	The <b>strtoi</b> and <b>strtou</b> functions
> > 		convert the initial portion of
> > 		the string pointed to by <tt>s</tt>
> > 	+	to <b>intmax_t</b> and <b>uintmax_t</b>,
> > 		respectively.
> > 		First,
> > 		they decompose the input string into three parts:
> > 		an initial, possibly empty, sequence of white-space characters,
> > 		a subject sequence resembling an integer
> > 		represented in some radix determined by the value of <tt>base</tt>,
> > 		and a final string of one or more unrecognized characters,
> > 		including the terminating null character of the input string.
> > 	+	Then,
> > 		they attempt to convert the subject sequence to an integer.
> > 	+	Then,
> > 	+	they coerce the integer into the range [min, max].
> > 	+	Finally,
> > 		they return the result.
> >=20
> > 	Paste p3, p4, p5, p6 from 7.24.2.8, replacing the function and
> > 	type names as appropriate.
>=20
> So the conversion is still locale-specific (p6).  One thing that can be=
=20
> useful for numeric conversions, and isn't covered well by the standard at=
=20
> present, is ones that are guaranteed to be in the C locale.  (That would=
=20
> require a flags argument or similar to configure the functions.)

NetBSD has strtoi_l(3), which has an extra parameter in which you can
specify the locale.

That should have a dedicated paper, though, just like the wchar variant.

<https://man.netbsd.org/strtoi_l.3>

I'll add this to 'Future directions'.

> > 	@@
> > 	+7	If the value of <tt>base</tt> is different from
> > 	+	the values specified in the preceding paragraphs,
> > 	+	the behavior is implementation defined.
>=20
> It's "implementation-defined", with a hyphen.

True.

>  And for that to be useful,=20
> you need clear bounds on what is permitted (that is, an=20
> implementation-defined set of sequences is accepted, and interpreted as=
=20
> having implementation-defined numeric values).

The choices should be:

	-  Report an error.
	-  Convert in an implementation-defined manner.

> > 	@@
> > 	 Returns
> > 	+10	The <b>strtoi</b> and <b>strtou</b> functions
> > 		return the converted and coerced value, if any.
> > 		If no conversion could be performed,
> > 	+	zero is coerced into the range,
> > 	+	and then returned.
> >=20
> > 	The paragraph above doesn't mention the range of representable
> > 	values (unlike 7.24.2.8) because that's already covered by the
> > 	range coercion specified in p2 above.
>=20
> You don't seem to define how the coercion works.  Modulo?  Saturation? =
=20
> Something else?  ("Coerce" is not a term defined in the C standard, nor i=
n=20
> ISO 2382.  So it has no semantics without them being explicitly defined=
=20
> for these functions.)

I have some wording in p2, but I should improve it.  It is saturation.

> What happens if min > max?  You say below that there is an ERANGE error=
=20
> for this case, but don't say what the return value is when it can't be in=
=20
> the range.

I don't have much to say.  To be honest, when implementing it I just
left it to chance.  I do

	return MAX(min, MIN(max, n));

NetBSD has a slightly different algorithm which may or may not return
the same value.  We should say it returns an unspecified value.

> > 	+Returns
> > 	+10	The <b>strtoi</b> and <b>strtou</b> functions
> > 	+	return the converted value, if any.
> > 	+	If no conversion is returned,
> > 	+	these functions return the value in the range [min, max]
> > 	+	that is closer to 0.
>=20
> What if both are equally close to 0?

"both" refers to min or max, but the paragraph specifies the entire
range.  Assuming that min<=3Dmax,
-  if 0<min, then min is the closest value
-  if min<0<max, then 0 is the closest value
-  if max<0, then max is the closest value.

And if min>max, then it would be covered by the suggestion above of
saying it returns an unspecified value.

However, this duplication of p10 was an accident.  I first wrote the
second one, then the first one but forgot to remove the second one.
I like the wording of the first better (with some tweaks I'll do).

> > 	+Errors
> > 	+11	These functions don't set <b>errno</b>.
>=20
> The standard does not use the abbreviation "don't", but says "do not".

Ok.

> > 	+	Instead, they set the object pointed to by <tt>rstatus</tt>
> > 	+	to an error code,
> > 	+	or to zero on success.
> > 	+
> > 	+12	-- EINVAL	The value in <tt>base</tt> is not supported.
> > 	+	-- ECANCELED	The given string did not contain
> > 	+			any characters that were converted.
> > 	+	-- ERANGE	The converted value was out of range
> > 	+			and has been coerced,
> > 	+			or the range was invalid (e.g., min > max).
> > 	+	-- ENOTSUP	The given string contained characters
> > 	+			that did not get converted.
>=20
> Of these names, only ERANGE is actually defined in the C standard.  You=
=20
> don't have any updates to <errno.h> to add the others.

Ok.

> These functions would clearly also need several examples added to the=20
> standard to illustrate their functionality, which are missing from this=
=20
> proposal.

Ok.

I'll post r1 soon.


Have a lovely night!
Alex

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

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

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

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmfZ1RwACgkQ64mZXMKQ
wqnThRAAncsxQgN4QEQBpHp9Pkp2xYRNrPwzcsCEj3Vlv5/wPHJfL1pQAXGiZ5E5
VXYKy19Tpef/wxFIRc8zzWD754PiwCZu5KVCg/WbR9/9zHwU7JCtNhfChwP/yWnK
zuhJmq42YFGQ1HhK/v09j7O4VLew8Y0fXShmwSGHJad3XWdHoi0t0QUvxN6cW28r
rHYi1s0BFf2XHAZV7B3V4a2/6aCMyk8EGdLIuFxw0laUWgRl/Gn7tj7HdcjHlTy/
dad/ZkC3J0cTb1m7wtswrSb1zRnlodaLv5HTbevcWIF65I13VnMWcnDmj0wHj9PK
KHxiWl5+w8fhEES1X8lRuDdOWiHr9oIQM+40MVaZ3kiNK9GVbtbkCUEBd0JZEQyh
1rV0suICrHOqZ3Xkggh41luVohraSbnV/S3Ajoqw7rbnGKO0Dunn7SI1SRF7PgQD
lQ09hJAr5Ql2QXK1Za9MxcHOl+oQi1ATEfgjZcuppOuvZB/gZGuRO4/UNXi7Fxyj
W03VnnhqbJTK+Hshc9ruTzQDuwS9Px0Xe59zwx/OdPZL6BL14JpMwDVuIzEEDnpp
WeosPF9wZ4ugb5hJaEm3UOLP9UGuhp5P7/Zuf5LNMbPGFzB8w9vzFvXyKhWifcZe
J8njr0kMi4gUqZHiVWysNj5Od8Bvi70eDdWegaxGKJ2s/4hRGfg=
=yFoy
-----END PGP SIGNATURE-----

--u45phu363kshup5b--