X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/e4c957f4746f290a051bc61b42b2e1d43920e7c4..5d288d736c2758c27a5943647f4a524f0e93a642:/perl.h diff --git a/perl.h b/perl.h index 8d817ab..8e81724 100644 --- a/perl.h +++ b/perl.h @@ -28,7 +28,14 @@ # include "config.h" #endif -#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(_STDC_C99) +/* NOTE 1: that with gcc -std=c89 the __STDC_VERSION__ is *not* defined + * because the __STDC_VERSION__ became a thing only with C90. Therefore, + * with gcc, HAS_C99 will never become true as long as we use -std=c89. + + * NOTE 2: headers lie. Do not expect that if HAS_C99 gets to be true, + * all the C99 features are there and are correct. */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ + defined(_STDC_C99) # define HAS_C99 1 #endif @@ -1843,23 +1850,6 @@ typedef NVTYPE NV; # include #endif -/* We need Perl_isfinitel (ends with ell) (if available) even when - * not USE_LONG_DOUBLE because the printf code (sv_catpvfn_flags) - * needs that. */ -#if defined(HAS_LONG_DOUBLE) && !defined(Perl_isfinitel) -/* If isfinite() is a macro and looks like we have C99, - * we assume it's the type-aware C99 isfinite(). */ -# if defined(isfinite) && defined(HAS_C99) -# define Perl_isfinitel(x) isfinite(x) -# elif defined(HAS_ISFINITEL) -# define Perl_isfinitel(x) isfinitel(x) -# elif defined(HAS_FINITEL) -# define Perl_isfinitel(x) finitel(x) -# elif defined(LDBL_MAX) -# define Perl_isfinitel(x) ((x) <= LDBL_MAX && (x) >= -LDBL_MAX) -# endif -#endif - #ifdef USE_LONG_DOUBLE # ifdef I_SUNMATH # include @@ -1962,7 +1952,7 @@ EXTERN_C long double modfl(long double, long double *); # define Perl_isinf(x) ((x) > LDBL_MAX || (x) < -LDBL_MAX) # endif # endif -# ifdef Perl_isfinitel +# ifndef Perl_isfinite # define Perl_isfinite(x) Perl_isfinitel(x) # endif #else @@ -2042,8 +2032,6 @@ EXTERN_C long double modfl(long double, long double *); # define Perl_isfinite(x) isfinite(x) # elif defined(HAS_FINITE) # define Perl_isfinite(x) finite(x) -# elif defined(DBL_MAX) -# define Perl_isfinite(x) ((x) <= DBL_MAX && (x) >= -DBL_MAX) # endif # endif #endif @@ -2300,13 +2288,15 @@ int isnan(double d); #ifndef Perl_isfinite # if defined(HAS_ISFINITE) && !defined(isfinite) -# define Perl_isfinite(x) isfinite((double)x) +# define Perl_isfinite(x) isfinite((double)(x)) # elif defined(HAS_FINITE) -# define Perl_isfinite(x) finite((double)x) +# define Perl_isfinite(x) finite((double)(x)) # elif defined(Perl_fp_class_finite) # define Perl_isfinite(x) Perl_fp_class_finite(x) # else -/* NaN*0 is NaN, [+-]Inf*0 is NaN, zero for anything else. */ +/* For the infinities the multiplication returns nan, + * for the nan the multiplication also returns nan, + * for everything else (that is, finite) zero should be returned. */ # define Perl_isfinite(x) (((x) * 0) == 0) # endif #endif @@ -2317,6 +2307,25 @@ int isnan(double d); # endif #endif +/* We need Perl_isfinitel (ends with ell) (if available) even when + * not USE_LONG_DOUBLE because the printf code (sv_catpvfn_flags) + * needs that. */ +#if defined(HAS_LONG_DOUBLE) && !defined(Perl_isfinitel) +/* If isfinite() is a macro and looks like we have C99, + * we assume it's the type-aware C99 isfinite(). */ +# if defined(HAS_ISFINITE) && defined(isfinite) && defined(HAS_C99) +# define Perl_isfinitel(x) isfinite(x) +# elif defined(HAS_ISFINITEL) +# define Perl_isfinitel(x) isfinitel(x) +# elif defined(HAS_FINITEL) +# define Perl_isfinitel(x) finitel(x) +# elif defined(HAS_INFL) && defined(HAS_NANL) +# define Perl_isfinitel(x) !(isinfl(x)||isnanl(x)) +# else +# define Perl_isfinitel(x) ((x) * 0 == 0) /* See Perl_isfinite. */ +# endif +#endif + /* The default is to use Perl's own atof() implementation (in numeric.c). * Usually that is the one to use but for some platforms (e.g. UNICOS) * it is however best to use the native implementation of atof. @@ -4133,9 +4142,8 @@ END_EXTERN_C # if !defined(NV_INF) && defined(HUGE_VAL) # define NV_INF HUGE_VAL # endif -# ifndef NV_NAN -# define NV_NAN (NV_INF-NV_INF) -# endif +/* For WIN32 the best NV_NAN is the __PL_nan_u trick, see below. + * There is no supported way of getting the NAN across all the crts. */ #endif /* If you are thinking of using HUGE_VAL for infinity, or using @@ -4232,6 +4240,9 @@ static const union { unsigned int __i; float __f; } __PL_nan_u = #if !defined(NV_NAN) # define NV_NAN ((NV)0.0/0.0) /* Some compilers will warn. */ #endif +/* Do NOT try doing NV_NAN based on NV_INF and trying (NV_INF-NV_INF). + * Though IEEE-754-logically correct, some compilers (like Visual C 2003) + * falsely misoptimize that to zero (x-x is zero, right?) */ #ifndef __cplusplus # if !defined(WIN32) && !defined(VMS)