This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
perl5db: extract a function.
[perl5.git] / pp_pack.c
index be9b115..4f1a266 100644 (file)
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -1660,7 +1660,7 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
            break;
        case 'U':
            if (len == 0) {
-                if (explicit_length) {
+                if (explicit_length && howlen != e_star) {
                    /* Switch to "bytes in UTF-8" mode */
                    if (symptr->flags & FLAG_DO_UTF8) utf8 = 0;
                    else
@@ -1690,10 +1690,10 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
                    len = UTF8SKIP(result);
                    if (!uni_to_bytes(aTHX_ &ptr, strend,
                                      (char *) &result[1], len-1, 'U')) break;
-                   auv = utf8n_to_uvuni(result, len, &retlen, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANYUV);
+                   auv = utf8n_to_uvuni(result, len, &retlen, UTF8_ALLOW_DEFAULT);
                    s = ptr;
                } else {
-                   auv = utf8n_to_uvuni((U8*)s, strend - s, &retlen, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANYUV);
+                   auv = utf8n_to_uvuni((U8*)s, strend - s, &retlen, UTF8_ALLOW_DEFAULT);
                    if (retlen == (STRLEN) -1 || retlen == 0)
                        Perl_croak(aTHX_ "Malformed UTF-8 string in unpack");
                    s += retlen;
@@ -2234,7 +2234,7 @@ S_unpack_rec(pTHX_ tempsym_t* symptr, const char *s, const char *strbeg, const c
 
         if (symptr->flags & FLAG_SLASH){
             if (SP - PL_stack_base - start_sp_offset <= 0)
-                Perl_croak(aTHX_ "'/' must follow a numeric type in unpack");
+               break;
             if( next_symbol(symptr) ){
               if( symptr->howlen == e_number )
                Perl_croak(aTHX_ "Count after length/code in unpack" );
@@ -2455,7 +2455,8 @@ marked_upgrade(pTHX_ SV *sv, tempsym_t *sym_ptr) {
     if (m != marks + sym_ptr->level+1) {
        Safefree(marks);
        Safefree(to_start);
-       Perl_croak(aTHX_ "panic: marks beyond string end");
+       Perl_croak(aTHX_ "panic: marks beyond string end, m=%p, marks=%p, "
+                  "level=%d", m, marks, sym_ptr->level);
     }
     for (group=sym_ptr; group; group = group->previous)
        group->strbeg = marks[group->level] - to_start;
@@ -2557,18 +2558,7 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
                if (lookahead.howlen == e_number) count = lookahead.length;
                else {
                    if (items > 0) {
-                       if (SvGAMAGIC(*beglist)) {
-                           /* Avoid reading the active data more than once
-                              by copying it to a temporary.  */
-                           STRLEN len;
-                           const char *const pv = SvPV_const(*beglist, len);
-                           SV *const temp
-                               = newSVpvn_flags(pv, len,
-                                                SVs_TEMP | SvUTF8(*beglist));
-                           *beglist = temp;
-                       }
-                       count = DO_UTF8(*beglist) ?
-                           sv_len_utf8(*beglist) : sv_len(*beglist);
+                       count = sv_len_utf8(*beglist);
                    }
                    else count = 0;
                    if (lookahead.code == 'Z') count++;
@@ -2789,7 +2779,9 @@ S_pack_rec(pTHX_ SV *cat, tempsym_t* symptr, SV **beglist, SV **endlist )
                GROWING(0, cat, start, cur, len);
                if (!uni_to_bytes(aTHX_ &aptr, end, cur, fromlen,
                                  datumtype | TYPE_IS_PACK))
-                   Perl_croak(aTHX_ "panic: predicted utf8 length not available");
+                   Perl_croak(aTHX_ "panic: predicted utf8 length not available, "
+                              "for '%c', aptr=%p end=%p cur=%p, fromlen=%"UVuf,
+                              (int)datumtype, aptr, end, cur, (UV)fromlen);
                cur += fromlen;
                len -= fromlen;
            } else if (utf8) {
@@ -3184,7 +3176,12 @@ extern const double _double_constants[];
            Zero(&anv, 1, NV); /* can be long double with unused bits */
            while (len-- > 0) {
                fromstr = NEXTFROM;
+#ifdef __GNUC__
+               /* to work round a gcc/x86 bug; don't use SvNV */
+               anv.nv = sv_2nv(fromstr);
+#else
                anv.nv = SvNV(fromstr);
+#endif
                DO_BO_PACK_N(anv, NV);
                PUSH_BYTES(utf8, cur, anv.bytes, sizeof(anv.bytes));
            }
@@ -3197,7 +3194,12 @@ extern const double _double_constants[];
            Zero(&aldouble, 1, long double);
            while (len-- > 0) {
                fromstr = NEXTFROM;
+#  ifdef __GNUC__
+               /* to work round a gcc/x86 bug; don't use SvNV */
+               aldouble.ld = (long double)sv_2nv(fromstr);
+#  else
                aldouble.ld = (long double)SvNV(fromstr);
+#  endif
                DO_BO_PACK_N(aldouble, long double);
                PUSH_BYTES(utf8, cur, aldouble.bytes, sizeof(aldouble.bytes));
            }
@@ -3556,7 +3558,7 @@ extern const double _double_constants[];
            from_utf8 = DO_UTF8(fromstr);
            if (from_utf8) {
                aend = aptr + fromlen;
-               fromlen = sv_len_utf8(fromstr);
+               fromlen = sv_len_utf8_nomg(fromstr);
            } else aend = NULL; /* Unused, but keep compilers happy */
            GROWING(utf8, cat, start, cur, (fromlen+2) / 3 * 4 + (fromlen+len-1)/len * 2);
            while (fromlen > 0) {
@@ -3574,7 +3576,9 @@ extern const double _double_constants[];
                                      'u' | TYPE_IS_PACK)) {
                        *cur = '\0';
                        SvCUR_set(cat, cur - start);
-                       Perl_croak(aTHX_ "panic: string is shorter than advertised");
+                       Perl_croak(aTHX_ "panic: string is shorter than advertised, "
+                                  "aptr=%p, aend=%p, buffer=%p, todo=%ld",
+                                  aptr, aend, buffer, (long) todo);
                    }
                    end = doencodes(hunk, buffer, todo);
                } else {
@@ -3600,11 +3604,11 @@ extern const double _double_constants[];
 PP(pp_pack)
 {
     dVAR; dSP; dMARK; dORIGMARK; dTARGET;
-    register SV *cat = TARG;
+    SV *cat = TARG;
     STRLEN fromlen;
     SV *pat_sv = *++MARK;
-    register const char *pat = SvPV_const(pat_sv, fromlen);
-    register const char *patend = pat + fromlen;
+    const char *pat = SvPV_const(pat_sv, fromlen);
+    const char *patend = pat + fromlen;
 
     MARK++;
     sv_setpvs(cat, "");
@@ -3622,8 +3626,8 @@ PP(pp_pack)
  * Local variables:
  * c-indentation-style: bsd
  * c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
  * End:
  *
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
  */