This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: Portability of idiom
On Thu, Jan 31, 2002 at 09:32:11PM -0600, Loren James Rittle wrote:
> > [...] Sometimes we may have to work around a buggy libc, but let's
> > not pretend it's OK.
>
> To pretend it's OK was never my intention. This is exactly why I
> posted the situation with as much context as possible.
I meant no criticism.
> > Maybe we should abort if we get a disallowed errno value, unless
> > it's one that configure has identified as a known bug on the target.
>
> Under the assumption that there are no buggy libc, the code as written
> was 100% perfect since there is only one documented errno setting
> strto* can make. Under that same assumption, the code as I patched it
> is still 100% perfect. The only thing I can agree to is that I have
> set the tradeoff for working with a buggy libc the other way. If
> there was a buggy libc that meant to signal an error via errno being
> set to nonzero and non-ERANGE, then I just helped a port I care about
> at their expense (doing that was not my intention).
I recognize that your intent is to make the library better, and to make
it do something useful on more platforms, even buggy ones. I appreciate
both your efforts and your explanations.
> You are asking for the code to be made even more robust than it was
> originally written or as a tweaked the detection tradeoff. This is
> not a bad thing. You are asking for a fast binary decision: ...
> to be turned into a three-way with more complex checks (pseudo): ...
> Or, written as somewhat optimized so only buggy ports pay the bulk of
> the overhead:
>
> #if _GLIBCPP_FUNCTION_HAS_GRATUITOUS_ERRNO
> // Heaven help us in general with multiple gratiutious values
> if (errno == _GLIBCPP_FUNCTION_HAS_GRATUITOUS_ERRNO)
> errno = 0;
> #endif
> if (!errno)
> use_results ();
> else if (errno == ERANGE)
> handle_error ();
> else
> abort ();
Actually, what I would like *best* would be to eliminate the call to
the C library strtod. However, users probably expect us to match their
C library's handling of least-significant bits bug-for-bug-compatibly,
which militates in favor of using the libc's strtod. (Sigh. Fortunately
that argument doesn't apply to strtol.)
I suppose my code would be more like
int old_errno = errno;
errno = 0;
double result = ::strtod( [...] );
if (!errno) {
if (old_errno) errno = old_errno;
use_results();
} else {
int new_errno = errno;
errno = old_errno;
#if defined(_GLIBCPP_STRTOD_WRONG_ERRNO)
if (new_errno == _GLIBCPP_STRTOD_WRONG_ERRNO)
#else
if (new_errno == ERANGE)
#endif
handle_error();
else
#if defined(_GLIBCPP_STRTOD_GRATUITOUS_ERRNO)
if (_GLIBCPP_STRTOD_GRATUITOUS_ERRNO(new_errno))
#endif
abort();
}
Notes:
1. In general, the error case doesn't need to be optimal because it had
better occur only rarely. We do want the (nearly dead) code to be
smallish, though.
2. num_get doesn't have license to clobber errno, so we have to save and
restore it.
3. On some platforms (e.g. some multi-threading environments) errno is a
macro for a function call or worse (it may be something like
#define errno (*__access_thread_local_storage(_ERRNO_OFFSET))
) so you don't want to "mention" it too too frequently.
> As people find aborts in the test cases (which hopefully cover all
> corner cases), they will have to add configure tests that correctly
> find the buggy libc behavior and set [various macros] appropriately.
>
> Is that, more or less, what you want to see?
Exactly (more or less :-)
Thank you for your scrupulous care. I apologize for posting unclearly,
and for complaining more than coding.
Nathan Myers
ncm at cantrip dot org