Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 27 Jan 2002 07:44:20 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Chad David <davidc@acns.ab.ca>
Cc:        <arch@FreeBSD.ORG>
Subject:   Re: strtod()
Message-ID:  <20020127070622.K35323-100000@gamplex.bde.org>
In-Reply-To: <20020124135250.A454@colnta.acns.ab.ca>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 24 Jan 2002, Chad David wrote:

> On current (as of today) strtod() sets errno to EINVAL even when no error
> actually occurs.  While I understand that the value of errno is undefined
> if an error does not occur, there is confusion when 0.0 is passed and the
> conversion is successful.
> ...
> I'm not saying that just because Solaris chooses to implement the
> interface in this way that FreeBSD should, but I do think that there is a
> lot of room for introducing (needless) complexity when porting
> applications from Solaris (like I am), and that while FreeBSD does not
> have to set EINVAL when an error occurs, it should NOT set it when an
> error does not occur.
>
> Note that on stable errno does not get set to EINVAL.

I think you mean strtol().  strtod() hasn't changed significantly since
RELENG_4.  The integer strto*() functions now set it in the following
cases:
(1) if the base is weird, even if there are no weird digits.  This is a
    bug IMO.  All C standards seem to require that even negative bases
    just work.
(2) if no input is consumed.

I agree that errno shouldn't be set (by the strto* family at least)
when there is no error.  I think standards don't permit it (they permit
gratutiously clobbering errno, but not when the setting of errno is
explicitly documented).  Setting it when no input is consumed is not
very useful and has broken the the error handling of at least test(1)
and dd(1) so far.  This case can be detected easily by checking the
end pointer.  The breakage has been fixed in test(1).  Here it is in
dd/args.c:

%%%
	errno = 0;
	num = strtouq(val, &expr, 0);
	if (errno != 0)				/* Overflow or underflow. */
		err(1, "%s", oper);

	if (expr == val)			/* No valid digits. */
		errx(1, "%s: illegal numeric value", oper);
%%%

The "Overflow or underflow" comment has rotted in 3 steps:
(1) It was changed from "Overflow" to "Overflow or underflow" when
    strtuol() was changed to strtoq().  This was just an obfuscation.
    "Underflow" must be read as "overflow towards negative infinity",
    but it's less confusing to just say "overflow".
(2) The code was wrong because strto*() may set errno, and broke when
    strtoq() started setting it.  The "illegal numeric value" case
    became unreachable.
(3) "Overflow or underflow" wasn't changed back to "Overflow" when
    strtoq() was changed to strtouq().

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020127070622.K35323-100000>