scan_num() sticks to UVs rather than IVs (now -2147483648 doesn't
Gurusamy Sarathy [Sun, 5 Mar 2000 04:30:02 +0000 (04:30 +0000)]
end up being promoted to an NV)

p4raw-id: //depot/perl@5533

pp.c
t/op/inc.t
toke.c

diff --git a/pp.c b/pp.c
index ebfe985..fcae1e4 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1391,9 +1391,23 @@ PP(pp_negate)
        dTOPss;
        if (SvGMAGICAL(sv))
            mg_get(sv);
-       if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv) && SvIVX(sv) != IV_MIN)
-           SETi(-SvIVX(sv));
-       else if (SvNIOKp(sv))
+       if (SvIOKp(sv) && !SvNOKp(sv) && !SvPOKp(sv)) {
+           if (SvIsUV(sv)) {
+               if (SvIVX(sv) == IV_MIN) {
+                   SETi(SvIVX(sv));    /* special case: -((UV)IV_MAX+1) == IV_MIN */
+                   RETURN;
+               }
+               else if (SvUVX(sv) <= IV_MAX) {
+                   SETi(-SvUVX(sv));
+                   RETURN;
+               }
+           }
+           else if (SvIVX(sv) != IV_MIN) {
+               SETi(-SvIVX(sv));
+               RETURN;
+           }
+       }
+       if (SvNIOKp(sv))
            SETn(-SvNV(sv));
        else if (SvPOKp(sv)) {
            STRLEN len;
index e5a2a92..f59115e 100755 (executable)
@@ -1,9 +1,6 @@
 #!./perl
 
-
-# $RCSfile$
-
-print "1..6\n";
+print "1..12\n";
 
 # Verify that addition/subtraction properly upgrade to doubles.
 # These tests are only significant on machines with 32 bit longs,
@@ -50,3 +47,51 @@ if ($a == -2147483649)
        {print "ok 6\n"}
 else
        {print "not ok 6\n";}
+
+$a = 2147483648;
+$a = -$a;
+$c=$a--;
+if ($a == -2147483649) 
+       {print "ok 7\n"}
+else
+       {print "not ok 7\n";}
+
+$a = 2147483648;
+$a = -$a;
+$c=--$a;
+if ($a == -2147483649) 
+       {print "ok 8\n"}
+else
+       {print "not ok 8\n";}
+
+$a = 2147483648;
+$a = -$a;
+$a=$a-1;
+if ($a == -2147483649) 
+       {print "ok 9\n"}
+else
+       {print "not ok 9\n";}
+
+$a = 2147483648;
+$b = -$a;
+$c=$b--;
+if ($b == -$a-1) 
+       {print "ok 10\n"}
+else
+       {print "not ok 10\n";}
+
+$a = 2147483648;
+$b = -$a;
+$c=--$b;
+if ($b == -$a-1) 
+       {print "ok 11\n"}
+else
+       {print "not ok 11\n";}
+
+$a = 2147483648;
+$b = -$a;
+$b=$b-1;
+if ($b == -(++$a)) 
+       {print "ok 12\n"}
+else
+       {print "not ok 12\n";}
diff --git a/toke.c b/toke.c
index 79ee972..8a21303 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -5640,7 +5640,7 @@ S_checkcomma(pTHX_ register char *s, char *name, char *what)
 
 STATIC SV *
 S_new_constant(pTHX_ char *s, STRLEN len, const char *key, SV *sv, SV *pv,
-              const char *type) 
+              const char *type)
 {
     dSP;
     HV *table = GvHV(PL_hintgv);                /* ^H */
@@ -5700,8 +5700,7 @@ S_new_constant(pTHX_ char *s, STRLEN len, const char *key, SV *sv, SV *pv,
     SPAGAIN ;
     
     /* Check the eval first */
-    if (!PL_in_eval && SvTRUE(ERRSV))
-    {
+    if (!PL_in_eval && SvTRUE(ERRSV)) {
        STRLEN n_a;
        sv_catpv(ERRSV, "Propagated");
        yyerror(SvPV(ERRSV, n_a)); /* Duplicates the message inside eval */
@@ -5724,9 +5723,9 @@ S_new_constant(pTHX_ char *s, STRLEN len, const char *key, SV *sv, SV *pv,
        why2 = key;
        sv = res;
        goto report;
-     }
+    }
 
-     return res;
+    return res;
 }
   
 STATIC char *
@@ -6684,7 +6683,7 @@ Perl_scan_num(pTHX_ char *start)
     register char *s = start;          /* current position in buffer */
     register char *d;                  /* destination in temp buffer */
     register char *e;                  /* end of temp buffer */
-    IV tryiv;                          /* used to see if it can be an IV */
+    UV tryuv;                          /* used to see if it can be an UV */
     NV value;                          /* number read, as a double */
     SV *sv = Nullsv;                   /* place to put the converted number */
     bool floatit;                      /* boolean: int or float? */
@@ -6954,9 +6953,9 @@ Perl_scan_num(pTHX_ char *start)
           Note: if floatit is true, then we don't need to do the
           conversion at all.
        */
-       tryiv = I_V(value);
-       if (!floatit && (NV)tryiv == value)
-           sv_setiv(sv, tryiv);
+       tryuv = U_V(value);
+       if (!floatit && (NV)tryuv == value)
+           sv_setuv(sv, tryuv);
        else
            sv_setnv(sv, value);
        if ( floatit ? (PL_hints & HINT_NEW_FLOAT) :