This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]