Further tweaks to perluniintro.pod
[p5sagit/p5-mst-13.2.git] / pp_pack.c
index d3fd37a..4476454 100644 (file)
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -2101,7 +2101,18 @@ Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beg
                     afloat = _float_constants[0];   /* single prec. inf. */
                else afloat = (float)SvNV(fromstr);
 #else
+# if defined(VMS) && !defined(__IEEE_FP)
+/* IEEE fp overflow shenanigans are unavailable on VAX and optional
+ * on Alpha; fake it if we don't have them.
+ */
+               if (SvNV(fromstr) > FLT_MAX)
+                    afloat = FLT_MAX;
+               else if (SvNV(fromstr) < -FLT_MAX)
+                    afloat = -FLT_MAX;
+               else afloat = (float)SvNV(fromstr);
+# else
                afloat = (float)SvNV(fromstr);
+# endif
 #endif
                sv_catpvn(cat, (char *)&afloat, sizeof (float));
            }
@@ -2122,7 +2133,18 @@ Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beg
                     adouble = _double_constants[0];   /* double prec. inf. */
                else adouble = (double)SvNV(fromstr);
 #else
+# if defined(VMS) && !defined(__IEEE_FP)
+/* IEEE fp overflow shenanigans are unavailable on VAX and optional
+ * on Alpha; fake it if we don't have them.
+ */
+               if (SvNV(fromstr) > DBL_MAX)
+                    adouble = DBL_MAX;
+               else if (SvNV(fromstr) < -DBL_MAX)
+                    adouble = -DBL_MAX;
+               else adouble = (double)SvNV(fromstr);
+# else
                adouble = (double)SvNV(fromstr);
+# endif
 #endif
                sv_catpvn(cat, (char *)&adouble, sizeof (double));
            }
@@ -2264,7 +2286,7 @@ Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beg
                    /* Copy string and check for compliance */
                    from = SvPV(fromstr, len);
                    if ((norm = is_an_int(from, len)) == NULL)
-                       Perl_croak(aTHX_ "can compress only unsigned integer");
+                       Perl_croak(aTHX_ "Can only compress unsigned integers");
 
                    New('w', result, len, char);
                    in = result + len;
@@ -2277,15 +2299,25 @@ Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beg
                    SvREFCNT_dec(norm); /* free norm */
                 }
                else if (SvNOKp(fromstr)) {
-                   char   buf[sizeof(NV) * 2]; /* 8/7 <= 2 */
+                   /* 10**NV_MAX_10_EXP is the largest power of 10
+                      so 10**(NV_MAX_10_EXP+1) is definately unrepresentable
+                      given 10**(NV_MAX_10_EXP+1) == 128 ** x solve for x:
+                      x = (NV_MAX_10_EXP+1) * log (10) / log (128)
+                      And with that many bytes only Inf can overflow.
+                   */
+#ifdef NV_MAX_10_EXP
+                   char   buf[1 + (int)((NV_MAX_10_EXP + 1) * 0.47456)];
+#else
+                   char   buf[1 + (int)((308 + 1) * 0.47456)];
+#endif
                    char  *in = buf + sizeof(buf);
 
                     anv = Perl_floor(anv);
                    do {
                        NV next = Perl_floor(anv / 128);
-                       *--in = (unsigned char)(anv - (next * 128)) | 0x80;
                        if (in <= buf)  /* this cannot happen ;-) */
                            Perl_croak(aTHX_ "Cannot compress integer");
+                       *--in = (unsigned char)(anv - (next * 128)) | 0x80;
                        anv = next;
                    } while (anv > 0);
                    buf[sizeof(buf) - 1] &= 0x7f; /* clear continue bit */
@@ -2300,7 +2332,7 @@ Perl_pack_cat(pTHX_ SV *cat, char *pat, register char *patend, register SV **beg
                    /* Copy string and check for compliance */
                    from = SvPV(fromstr, len);
                    if ((norm = is_an_int(from, len)) == NULL)
-                       Perl_croak(aTHX_ "can compress only unsigned integer");
+                       Perl_croak(aTHX_ "Can only compress unsigned integers");
 
                    New('w', result, len, char);
                    in = result + len;