[ID 19990613.003 linklibperl set incorrectly in Makefile.SH for OpenBSD]
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index edf1f1e..a61d2ea 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -435,12 +435,12 @@ S_more_xiv(pTHX)
 STATIC XPVNV*
 S_new_xnv(pTHX)
 {
-    double* xnv;
+    NV* xnv;
     LOCK_SV_MUTEX;
     if (!PL_xnv_root)
        more_xnv();
     xnv = PL_xnv_root;
-    PL_xnv_root = *(double**)xnv;
+    PL_xnv_root = *(NV**)xnv;
     UNLOCK_SV_MUTEX;
     return (XPVNV*)((char*)xnv - STRUCT_OFFSET(XPVNV, xnv_nv));
 }
@@ -448,9 +448,9 @@ S_new_xnv(pTHX)
 STATIC void
 S_del_xnv(pTHX_ XPVNV *p)
 {
-    double* xnv = (double*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv));
+    NV* xnv = (NV*)((char*)(p) + STRUCT_OFFSET(XPVNV, xnv_nv));
     LOCK_SV_MUTEX;
-    *(double**)xnv = PL_xnv_root;
+    *(NV**)xnv = PL_xnv_root;
     PL_xnv_root = xnv;
     UNLOCK_SV_MUTEX;
 }
@@ -458,17 +458,17 @@ S_del_xnv(pTHX_ XPVNV *p)
 STATIC void
 S_more_xnv(pTHX)
 {
-    register double* xnv;
-    register double* xnvend;
-    New(711, xnv, 1008/sizeof(double), double);
-    xnvend = &xnv[1008 / sizeof(double) - 1];
-    xnv += (sizeof(XPVIV) - 1) / sizeof(double) + 1; /* fudge by sizeof XPVIV */
+    register NV* xnv;
+    register NV* xnvend;
+    New(711, xnv, 1008/sizeof(NV), NV);
+    xnvend = &xnv[1008 / sizeof(NV) - 1];
+    xnv += (sizeof(XPVIV) - 1) / sizeof(NV) + 1; /* fudge by sizeof XPVIV */
     PL_xnv_root = xnv;
     while (xnv < xnvend) {
-       *(double**)xnv = (double*)(xnv + 1);
+       *(NV**)xnv = (NV*)(xnv + 1);
        xnv++;
     }
-    *(double**)xnv = 0;
+    *(NV**)xnv = 0;
 }
 
 STATIC XRV*
@@ -631,7 +631,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
     U32                cur;
     U32                len;
     IV         iv;
-    double     nv;
+    NV         nv;
     MAGIC*     magic;
     HV*                stash;
 
@@ -656,7 +656,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        cur     = 0;
        len     = 0;
        iv      = SvIVX(sv);
-       nv      = (double)SvIVX(sv);
+       nv      = (NV)SvIVX(sv);
        del_XIV(SvANY(sv));
        magic   = 0;
        stash   = 0;
@@ -683,7 +683,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        cur     = 0;
        len     = 0;
        iv      = (IV)pv;
-       nv      = (double)(unsigned long)pv;
+       nv      = (NV)(unsigned long)pv;
        del_XRV(SvANY(sv));
        magic   = 0;
        stash   = 0;
@@ -1017,7 +1017,7 @@ Perl_sv_setuv_mg(pTHX_ register SV *sv, UV u)
 }
 
 void
-Perl_sv_setnv(pTHX_ register SV *sv, double num)
+Perl_sv_setnv(pTHX_ register SV *sv, NV num)
 {
     SV_CHECK_THINKFIRST(sv);
     switch (SvTYPE(sv)) {
@@ -1049,7 +1049,7 @@ Perl_sv_setnv(pTHX_ register SV *sv, double num)
 }
 
 void
-Perl_sv_setnv_mg(pTHX_ register SV *sv, double num)
+Perl_sv_setnv_mg(pTHX_ register SV *sv, NV num)
 {
     sv_setnv(sv,num);
     SvSETMAGIC(sv);
@@ -1181,7 +1181,7 @@ Perl_sv_2iv(pTHX_ register SV *sv)
            sv_upgrade(sv, SVt_PVNV);
 
        (void)SvIOK_on(sv);
-       if (SvNVX(sv) < (double)IV_MAX + 0.5)
+       if (SvNVX(sv) < (NV)IV_MAX + 0.5)
            SvIVX(sv) = I_V(SvNVX(sv));
        else {
            SvUVX(sv) = U_V(SvNVX(sv));
@@ -1208,20 +1208,23 @@ Perl_sv_2iv(pTHX_ register SV *sv)
        if (numtype & IS_NUMBER_NOT_IV) {
            /* May be not an integer.  Need to cache NV if we cache IV
             * - otherwise future conversion to NV will be wrong.  */
-           double d;
+           NV d;
 
-           SET_NUMERIC_STANDARD();
-           d = atof(SvPVX(sv));
+           d = Atof(SvPVX(sv));
 
            if (SvTYPE(sv) < SVt_PVNV)
                sv_upgrade(sv, SVt_PVNV);
            SvNVX(sv) = d;
            (void)SvNOK_on(sv);
            (void)SvIOK_on(sv);
-           DEBUG_c(PerlIO_printf(Perl_debug_log,
-                                 "0x%lx 2nv(%g)\n",(unsigned long)sv,
-                                 SvNVX(sv)));
-           if (SvNVX(sv) < (double)IV_MAX + 0.5)
+#if defined(USE_LONG_DOUBLE)
+           DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%Lg)\n",
+                                 (unsigned long)sv, SvNVX(sv)));
+#else
+           DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%g)\n",
+                                 (unsigned long)sv, SvNVX(sv)));
+#endif
+           if (SvNVX(sv) < (NV)IV_MAX + 0.5)
                SvIVX(sv) = I_V(SvNVX(sv));
            else {
                SvUVX(sv) = U_V(SvNVX(sv));
@@ -1349,19 +1352,22 @@ Perl_sv_2uv(pTHX_ register SV *sv)
        if (numtype & IS_NUMBER_NOT_IV) {
            /* May be not an integer.  Need to cache NV if we cache IV
             * - otherwise future conversion to NV will be wrong.  */
-           double d;
+           NV d;
 
-           SET_NUMERIC_STANDARD();
-           d = atof(SvPVX(sv));        /* XXXX 64-bit? */
+           d = Atof(SvPVX(sv));        /* XXXX 64-bit? */
 
            if (SvTYPE(sv) < SVt_PVNV)
                sv_upgrade(sv, SVt_PVNV);
            SvNVX(sv) = d;
            (void)SvNOK_on(sv);
            (void)SvIOK_on(sv);
-           DEBUG_c(PerlIO_printf(Perl_debug_log,
-                                 "0x%lx 2nv(%g)\n",(unsigned long)sv,
-                                 SvNVX(sv)));
+#if defined(USE_LONG_DOUBLE)
+           DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%Lg)\n",
+                                 (unsigned long)sv, SvNVX(sv)));
+#else
+           DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%g)\n",
+                                 (unsigned long)sv, SvNVX(sv)));
+#endif
            if (SvNVX(sv) < -0.5) {
                SvIVX(sv) = I_V(SvNVX(sv));
                goto ret_zero;
@@ -1422,7 +1428,7 @@ Perl_sv_2uv(pTHX_ register SV *sv)
     return SvIsUV(sv) ? SvUVX(sv) : (UV)SvIVX(sv);
 }
 
-double
+NV
 Perl_sv_2nv(pTHX_ register SV *sv)
 {
     if (!sv)
@@ -1435,14 +1441,13 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            dTHR;
            if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !looks_like_number(sv))
                not_a_number(sv);
-           SET_NUMERIC_STANDARD();
-           return atof(SvPVX(sv));
+           return Atof(SvPVX(sv));
        }
        if (SvIOKp(sv)) {
            if (SvIsUV(sv)) 
-               return (double)SvUVX(sv);
+               return (NV)SvUVX(sv);
            else
-               return (double)SvIVX(sv);
+               return (NV)SvIVX(sv);
        }       
         if (!SvROK(sv)) {
            if (!(SvFLAGS(sv) & SVs_PADTMP)) {
@@ -1458,21 +1463,20 @@ Perl_sv_2nv(pTHX_ register SV *sv)
          SV* tmpstr;
          if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)))
              return SvNV(tmpstr);
-         return (double)(unsigned long)SvRV(sv);
+         return (NV)(unsigned long)SvRV(sv);
        }
        if (SvREADONLY(sv)) {
            dTHR;
            if (SvPOKp(sv) && SvLEN(sv)) {
                if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !looks_like_number(sv))
                    not_a_number(sv);
-               SET_NUMERIC_STANDARD();
-               return atof(SvPVX(sv));
+               return Atof(SvPVX(sv));
            }
            if (SvIOKp(sv)) {
                if (SvIsUV(sv)) 
-                   return (double)SvUVX(sv);
+                   return (NV)SvUVX(sv);
                else
-                   return (double)SvIVX(sv);
+                   return (NV)SvIVX(sv);
            }
            if (ckWARN(WARN_UNINITIALIZED))
                Perl_warner(aTHX_ WARN_UNINITIALIZED, PL_warn_uninit);
@@ -1484,23 +1488,34 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            sv_upgrade(sv, SVt_PVNV);
        else
            sv_upgrade(sv, SVt_NV);
-       DEBUG_c(SET_NUMERIC_STANDARD());
-       DEBUG_c(PerlIO_printf(Perl_debug_log,
-                             "0x%lx num(%g)\n",(unsigned long)sv,SvNVX(sv)));
+#if defined(USE_LONG_DOUBLE)
+       DEBUG_c({
+           RESTORE_NUMERIC_STANDARD();
+           PerlIO_printf(Perl_debug_log, "0x%lx num(%Lg)\n",
+                         (unsigned long)sv, SvNVX(sv));
+           RESTORE_NUMERIC_LOCAL();
+       });
+#else
+       DEBUG_c({
+           RESTORE_NUMERIC_STANDARD();
+           PerlIO_printf(Perl_debug_log, "0x%lx num(%g)\n",
+                         (unsigned long)sv, SvNVX(sv));
+           RESTORE_NUMERIC_LOCAL();
+       });
+#endif
     }
     else if (SvTYPE(sv) < SVt_PVNV)
        sv_upgrade(sv, SVt_PVNV);
     if (SvIOKp(sv) &&
            (!SvPOKp(sv) || !strchr(SvPVX(sv),'.') || !looks_like_number(sv)))
     {
-       SvNVX(sv) = SvIsUV(sv) ? (double)SvUVX(sv) : (double)SvIVX(sv);
+       SvNVX(sv) = SvIsUV(sv) ? (NV)SvUVX(sv) : (NV)SvIVX(sv);
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        dTHR;
        if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) && !looks_like_number(sv))
            not_a_number(sv);
-       SET_NUMERIC_STANDARD();
-       SvNVX(sv) = atof(SvPVX(sv));
+       SvNVX(sv) = Atof(SvPVX(sv));
     }
     else  {
        dTHR;
@@ -1512,9 +1527,21 @@ Perl_sv_2nv(pTHX_ register SV *sv)
        return 0.0;
     }
     SvNOK_on(sv);
-    DEBUG_c(SET_NUMERIC_STANDARD());
-    DEBUG_c(PerlIO_printf(Perl_debug_log,
-                         "0x%lx 2nv(%g)\n",(unsigned long)sv,SvNVX(sv)));
+#if defined(USE_LONG_DOUBLE)
+    DEBUG_c({
+       RESTORE_NUMERIC_STANDARD();
+       PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%Lg)\n",
+                     (unsigned long)sv, SvNVX(sv));
+       RESTORE_NUMERIC_LOCAL();
+    });
+#else
+    DEBUG_c({
+       RESTORE_NUMERIC_STANDARD();
+       PerlIO_printf(Perl_debug_log, "0x%lx 1nv(%g)\n",
+                     (unsigned long)sv, SvNVX(sv));
+       RESTORE_NUMERIC_LOCAL();
+    });
+#endif
     return SvNVX(sv);
 }
 
@@ -1522,7 +1549,7 @@ STATIC IV
 S_asIV(pTHX_ SV *sv)
 {
     I32 numtype = looks_like_number(sv);
-    double d;
+    NV d;
 
     if (numtype & IS_NUMBER_TO_INT_BY_ATOL)
        return atol(SvPVX(sv));         /* XXXX 64-bit? */
@@ -1531,8 +1558,7 @@ S_asIV(pTHX_ SV *sv)
        if (ckWARN(WARN_NUMERIC))
            not_a_number(sv);
     }
-    SET_NUMERIC_STANDARD();
-    d = atof(SvPVX(sv));
+    d = Atof(SvPVX(sv));
     return I_V(d);
 }
 
@@ -1550,8 +1576,7 @@ S_asUV(pTHX_ SV *sv)
        if (ckWARN(WARN_NUMERIC))
            not_a_number(sv);
     }
-    SET_NUMERIC_STANDARD();
-    return U_V(atof(SvPVX(sv)));
+    return U_V(Atof(SvPVX(sv)));
 }
 
 /*
@@ -1601,11 +1626,12 @@ Perl_looks_like_number(pTHX_ SV *sv)
 
     nbegin = s;
     /*
-     * we return 1 if the number can be converted to _integer_ with atol()
-     * and 2 if you need (int)atof().
+     * we return IS_NUMBER_TO_INT_BY_ATOL if the number can be converted
+     * to _integer_ with atol() and IS_NUMBER_TO_INT_BY_ATOF if you need
+     * (int)atof().
      */
 
-    /* next must be digit or '.' */
+    /* next must be digit or the radix separator */
     if (isDIGIT(*s)) {
         do {
            s++;
@@ -1616,17 +1642,25 @@ Perl_looks_like_number(pTHX_ SV *sv)
        else
            numtype |= IS_NUMBER_TO_INT_BY_ATOL;
 
-        if (*s == '.') {
+        if (*s == '.'
+#ifdef USE_LOCALE_NUMERIC 
+           || IS_NUMERIC_RADIX(*s)
+#endif
+           ) {
            s++;
            numtype |= IS_NUMBER_NOT_IV;
-            while (isDIGIT(*s))  /* optional digits after "." */
+            while (isDIGIT(*s))  /* optional digits after the radix */
                 s++;
         }
     }
-    else if (*s == '.') {
+    else if (*s == '.'
+#ifdef USE_LOCALE_NUMERIC 
+           || IS_NUMERIC_RADIX(*s)
+#endif
+           ) {
         s++;
        numtype |= IS_NUMBER_TO_INT_BY_ATOL | IS_NUMBER_NOT_IV;
-        /* no digits before '.' means we need digits after it */
+        /* no digits before the radix means we need digits after it */
         if (isDIGIT(*s)) {
            do {
                s++;
@@ -1725,7 +1759,6 @@ Perl_sv_2pv(pTHX_ register SV *sv, STRLEN *lp)
            goto tokensave;
        }
        if (SvNOKp(sv)) {
-           SET_NUMERIC_STANDARD();
            Gconvert(SvNVX(sv), DBL_DIG, 0, tmpbuf);
            tsv = Nullsv;
            goto tokensave;
@@ -1829,7 +1862,6 @@ Perl_sv_2pv(pTHX_ register SV *sv, STRLEN *lp)
        if (SvREADONLY(sv)) {
            if (SvNOKp(sv)) {           /* See note in sv_2uv() */
                /* XXXX 64-bit?  IV may have better precision... */
-               SET_NUMERIC_STANDARD();
                Gconvert(SvNVX(sv), DBL_DIG, 0, tmpbuf);
                tsv = Nullsv;
                goto tokensave;
@@ -1867,7 +1899,6 @@ Perl_sv_2pv(pTHX_ register SV *sv, STRLEN *lp)
        else
 #endif /*apollo*/
        {
-           SET_NUMERIC_STANDARD();
            Gconvert(SvNVX(sv), DBL_DIG, 0, s);
        }
        errno = olderrno;
@@ -3643,8 +3674,16 @@ thats_really_all_folks:
     }
    else
     {
+#ifndef EPOC
        /*The big, slow, and stupid way */
        STDCHAR buf[8192];
+#else
+       /* Need to work around EPOC SDK features          */
+       /* On WINS: MS VC5 generates calls to _chkstk,    */
+       /* if a `large' stack frame is allocated          */
+       /* gcc on MARM does not generate calls like these */
+       STDCHAR buf[1024];
+#endif
 
 screamer2:
        if (rslen) {
@@ -3741,13 +3780,13 @@ Perl_sv_inc(pTHX_ register SV *sv)
     if (flags & SVp_IOK) {
        if (SvIsUV(sv)) {
            if (SvUVX(sv) == UV_MAX)
-               sv_setnv(sv, (double)UV_MAX + 1.0);
+               sv_setnv(sv, (NV)UV_MAX + 1.0);
            else
                (void)SvIOK_only_UV(sv);
                ++SvUVX(sv);
        } else {
            if (SvIVX(sv) == IV_MAX)
-               sv_setnv(sv, (double)IV_MAX + 1.0);
+               sv_setnv(sv, (NV)IV_MAX + 1.0);
            else {
                (void)SvIOK_only(sv);
                ++SvIVX(sv);
@@ -3766,8 +3805,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
     while (isALPHA(*d)) d++;
     while (isDIGIT(*d)) d++;
     if (*d) {
-       SET_NUMERIC_STANDARD();
-       sv_setnv(sv,atof(SvPVX(sv)) + 1.0);  /* punt */
+       sv_setnv(sv,Atof(SvPVX(sv)) + 1.0);  /* punt */
        return;
     }
     d--;
@@ -3851,7 +3889,7 @@ Perl_sv_dec(pTHX_ register SV *sv)
            }       
        } else {
            if (SvIVX(sv) == IV_MIN)
-               sv_setnv(sv, (double)IV_MIN - 1.0);
+               sv_setnv(sv, (NV)IV_MIN - 1.0);
            else {
                (void)SvIOK_only(sv);
                --SvIVX(sv);
@@ -3866,8 +3904,7 @@ Perl_sv_dec(pTHX_ register SV *sv)
        (void)SvNOK_only(sv);
        return;
     }
-    SET_NUMERIC_STANDARD();
-    sv_setnv(sv,atof(SvPVX(sv)) - 1.0);        /* punt */
+    sv_setnv(sv,Atof(SvPVX(sv)) - 1.0);        /* punt */
 }
 
 /* Make a string that will exist for the duration of the expression
@@ -3970,7 +4007,7 @@ Perl_newSVpvf(pTHX_ const char* pat, ...)
 }
 
 SV *
-Perl_newSVnv(pTHX_ double n)
+Perl_newSVnv(pTHX_ NV n)
 {
     register SV *sv;
 
@@ -4262,7 +4299,7 @@ Perl_sv_uv(pTHX_ register SV *sv)
     return sv_2uv(sv);
 }
 
-double
+NV
 Perl_sv_nv(pTHX_ register SV *sv)
 {
     if (SvNOK(sv))
@@ -4438,7 +4475,7 @@ Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv)
 }
 
 SV*
-Perl_sv_setref_nv(pTHX_ SV *rv, const char *classname, double nv)
+Perl_sv_setref_nv(pTHX_ SV *rv, const char *classname, NV nv)
 {
     sv_setnv(newSVrv(rv,classname), nv);
     return rv;
@@ -4722,7 +4759,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        unsigned base;
        IV iv;
        UV uv;
-       double nv;
+       NV nv;
        STRLEN have;
        STRLEN need;
        STRLEN gap;
@@ -5040,7 +5077,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* This is evil, but floating point is even more evil */
 
            if (args)
-               nv = va_arg(*args, double);
+               nv = va_arg(*args, NV);
            else
                nv = (svix < svmax) ? SvNVx(svargs[svix++]) : 0.0;
 
@@ -5067,6 +5104,9 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            eptr = ebuf + sizeof ebuf;
            *--eptr = '\0';
            *--eptr = c;
+#ifdef USE_LONG_DOUBLE
+           *--eptr = 'L';
+#endif
            if (has_precis) {
                base = precis;
                do { *--eptr = '0' + (base % 10); } while (base /= 10);
@@ -5086,7 +5126,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                *--eptr = '#';
            *--eptr = '%';
 
-           (void)sprintf(PL_efloatbuf, eptr, nv);
+           {
+               RESTORE_NUMERIC_STANDARD();
+               (void)sprintf(PL_efloatbuf, eptr, nv);
+               RESTORE_NUMERIC_LOCAL();
+           }
 
            eptr = PL_efloatbuf;
            elen = strlen(PL_efloatbuf);