Make the length overrun checking and stack extension table driven.
authorNicholas Clark <nick@ccl4.org>
Fri, 21 Jan 2005 16:46:49 +0000 (16:46 +0000)
committerNicholas Clark <nick@ccl4.org>
Fri, 21 Jan 2005 16:46:49 +0000 (16:46 +0000)
(Shaves about 3k off pp_pack.o)

p4raw-id: //depot/perl@23853

MANIFEST
genpacksizetables.pl [new file with mode: 0755]
pp_pack.c

index 7ace81f..28ed265 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -920,6 +920,7 @@ ext/XS/Typemap/Typemap.xs   XS::Typemap extension
 fakesdio.h                     stdio in terms of PerlIO
 fakethr.h                      Fake threads header
 form.h                         Public declarations for formats
+genpacksizetables.pl           Generate the size tables for pack/unpack
 globals.c                      File to declare global symbols (for shared library)
 global.sym                     Symbols that need hiding when embedded
 globvar.sym                    Global variables that need hiding when embedded
diff --git a/genpacksizetables.pl b/genpacksizetables.pl
new file mode 100755 (executable)
index 0000000..d7dabc7
--- /dev/null
@@ -0,0 +1,116 @@
+#!/usr/bin/perl -w
+# I'm assuming that you're running this on some kind of ASCII system, but
+# it will generate EDCDIC too. (TODO)
+use strict;
+use Encode;
+
+my @lines = grep {!/^#/} <DATA>;
+
+sub addline {
+  my ($arrays, $chrmap, $letter, $arrayname, $noone, $nocsum, $size) = @_;
+  my $line = "/* $letter */ $size";
+  $line .= " | PACK_SIZE_CANNOT_ONLY_ONE" if $noone;
+  $line .= " | PACK_SIZE_CANNOT_CSUM" if $nocsum;
+  $line .= ",";
+  $arrays->{$arrayname}->[ord $chrmap->{$letter}] = $line;
+  # print ord $chrmap->{$letter}, " $line\n";
+}
+
+sub output_tables {
+  my %arrays;
+
+  my $chrmap = shift;
+  foreach (@_) {
+    my ($letter, $shriek, $noone, $nocsum, $size)
+      = /^([A-Za-z])(!?)\t(\S*)\t(\S*)\t(.*)/;
+    die "Can't parse '$_'" unless $size;
+
+    unless ($size =~ s/^=//) {
+      $size = "sizeof($size)";
+    }
+
+    addline (\%arrays, $chrmap, $letter, $shriek ? 'shrieking' : 'normal',
+            $noone, $nocsum, $size);
+  }
+
+  my %earliest;
+  foreach my $arrayname (sort keys %arrays) {
+    my $array = $arrays{$arrayname};
+    die "No defined entries in $arrayname" unless $array->[$#$array];
+    # Find the first used entry
+    my $earliest = 0;
+    $earliest++ while (!$array->[$earliest]);
+    # Remove all the empty elements.
+    splice @$array, 0, $earliest;
+    print "unsigned char size_${arrayname}[", scalar @$array, "] = {\n";
+    my @lines = map {$_ || "0,"} @$array;
+    # remove the last, annoying, comma
+    chop $lines[$#lines];
+    print "  $_\n" foreach @lines;
+    print "};\n";
+    $earliest{$arrayname} = $earliest;
+  }
+
+  print "struct packsize_t packsize[2] = {\n";
+
+  my @lines;
+  foreach (qw(normal shrieking)) {
+    my $array = $arrays{$_};
+    push @lines, "  {size_$_, $earliest{$_}, " . (scalar @$array) . "},";
+  }
+  # remove the last, annoying, comma
+  chop $lines[$#lines];
+  print "$_\n" foreach @lines;
+  print "};\n";
+}
+
+my %asciimap = (map {chr $_, chr $_} 0..255);
+my %ebcdicmap = (map {chr $_, Encode::encode ("posix-bc", chr $_)} 0..255);
+
+print <<'EOC';
+#if 'J'-'I' == 1
+/* ASCII */
+EOC
+output_tables (\%asciimap, @lines);
+print <<'EOC';
+#else
+/* EBCDIC (or bust) */
+EOC
+output_tables (\%ebcdicmap, @lines);
+print "#endif\n";
+
+__DATA__
+#Symbol        nooone  nocsum  size
+c                      char
+C                      unsigned char
+U                      char
+s!                     short
+s                      =SIZE16
+S!                     unsigned short
+v                      =SIZE16
+n                      =SIZE16
+S                      =SIZE16
+v!                     =SIZE16
+n!                     =SIZE16
+i                      int
+i!                     int
+I                      unsigned int
+I!                     unsigned int
+j                      =IVSIZE
+J                      =UVSIZE
+l!                     long
+l                      =SIZE32
+L!                     unsigned long
+V                      =SIZE32
+N                      =SIZE32
+V!                     =SIZE32
+N!                     =SIZE32
+L                      =SIZE32
+p      *       *       char *
+w              *       char
+q                      Quad_t
+Q                      Uquad_t
+f                      float
+d                      double
+F                      =NVSIZE
+D                      =LONG_DOUBLESIZE
index 6903415..8b50c70 100644 (file)
--- a/pp_pack.c
+++ b/pp_pack.c
@@ -239,6 +239,163 @@ S_mul128(pTHX_ SV *sv, U8 m)
 # define DO_BO_PACK_N(var, type)       BO_CANT_DOIT(pack, type)
 #endif
 
+#define PACK_SIZE_CANNOT_CSUM          0x80
+#define PACK_SIZE_CANNOT_ONLY_ONE      0x40
+#define PACK_SIZE_MASK                 0x3F
+
+
+struct packsize_t {
+    const char *array;
+    int first;
+    int size;
+};
+
+#define PACK_SIZE_NORMAL 0
+#define PACK_SIZE_SHRIEKING 1
+
+/* These tables are regenerated by genpacksizetables.pl (and then hand pasted
+   in).  You're unlikely ever to need to regenerate them.  */
+#if 'J'-'I' == 1
+/* ASCII */
+unsigned char size_normal[53] = {
+  /* C */ sizeof(unsigned char),
+  /* D */ LONG_DOUBLESIZE,
+  0,
+  /* F */ NVSIZE,
+  0, 0,
+  /* I */ sizeof(unsigned int),
+  /* J */ UVSIZE,
+  0,
+  /* L */ SIZE32,
+  0,
+  /* N */ SIZE32,
+  0, 0,
+  /* Q */ sizeof(Uquad_t),
+  0,
+  /* S */ SIZE16,
+  0,
+  /* U */ sizeof(char),
+  /* V */ SIZE32,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* c */ sizeof(char),
+  /* d */ sizeof(double),
+  0,
+  /* f */ sizeof(float),
+  0, 0,
+  /* i */ sizeof(int),
+  /* j */ IVSIZE,
+  0,
+  /* l */ SIZE32,
+  0,
+  /* n */ SIZE16,
+  0,
+  /* p */ sizeof(char *) | PACK_SIZE_CANNOT_ONLY_ONE | PACK_SIZE_CANNOT_CSUM,
+  /* q */ sizeof(Quad_t),
+  0,
+  /* s */ SIZE16,
+  0, 0,
+  /* v */ SIZE16,
+  /* w */ sizeof(char) | PACK_SIZE_CANNOT_CSUM
+};
+unsigned char size_shrieking[46] = {
+  /* I */ sizeof(unsigned int),
+  0, 0,
+  /* L */ sizeof(unsigned long),
+  0,
+  /* N */ SIZE32,
+  0, 0, 0, 0,
+  /* S */ sizeof(unsigned short),
+  0, 0,
+  /* V */ SIZE32,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* i */ sizeof(int),
+  0, 0,
+  /* l */ sizeof(long),
+  0,
+  /* n */ SIZE16,
+  0, 0, 0, 0,
+  /* s */ sizeof(short),
+  0, 0,
+  /* v */ SIZE16
+};
+struct packsize_t packsize[2] = {
+  {size_normal, 67, 53},
+  {size_shrieking, 73, 46}
+};
+#else
+/* EBCDIC (or bust) */
+unsigned char size_normal[99] = {
+  /* c */ sizeof(char),
+  /* d */ sizeof(double),
+  0,
+  /* f */ sizeof(float),
+  0, 0,
+  /* i */ sizeof(int),
+  0, 0, 0, 0, 0, 0, 0,
+  /* j */ IVSIZE,
+  0,
+  /* l */ SIZE32,
+  0,
+  /* n */ SIZE16,
+  0,
+  /* p */ sizeof(char *) | PACK_SIZE_CANNOT_ONLY_ONE | PACK_SIZE_CANNOT_CSUM,
+  /* q */ sizeof(Quad_t),
+  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* s */ SIZE16,
+  0, 0,
+  /* v */ SIZE16,
+  /* w */ sizeof(char) | PACK_SIZE_CANNOT_CSUM,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0,
+  /* C */ sizeof(unsigned char),
+  /* D */ LONG_DOUBLESIZE,
+  0,
+  /* F */ NVSIZE,
+  0, 0,
+  /* I */ sizeof(unsigned int),
+  0, 0, 0, 0, 0, 0, 0,
+  /* J */ UVSIZE,
+  0,
+  /* L */ SIZE32,
+  0,
+  /* N */ SIZE32,
+  0, 0,
+  /* Q */ sizeof(Uquad_t),
+  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* S */ SIZE16,
+  0,
+  /* U */ sizeof(char),
+  /* V */ SIZE32
+};
+unsigned char size_shrieking[93] = {
+  /* i */ sizeof(int),
+  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* l */ sizeof(long),
+  0,
+  /* n */ SIZE16,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* s */ sizeof(short),
+  0, 0,
+  /* v */ SIZE16,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* I */ sizeof(unsigned int),
+  0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* L */ sizeof(unsigned long),
+  0,
+  /* N */ SIZE32,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  /* S */ sizeof(unsigned short),
+  0, 0,
+  /* V */ SIZE32
+};
+struct packsize_t packsize[2] = {
+  {size_normal, 131, 99},
+  {size_shrieking, 137, 93}
+};
+#endif
+
+
 /* Returns the sizeof() struct described by pat */
 STATIC I32
 S_measure_struct(pTHX_ register tempsym_t* symptr)
@@ -331,96 +488,58 @@ S_measure_struct(pTHX_ register tempsym_t* symptr)
            len = (len + 1)/2;
            size = 1;
            break;
-       case 's' | TYPE_IS_SHRIEKING:
-#if SHORTSIZE != SIZE16
-           size = sizeof(short);
-           break;
-#else
-            /* FALL THROUGH */
-#endif
-       case 's':
-           size = SIZE16;
+
+
+       case 'P':
+           len = 1;
+           /* FALL THROUGH */
+       case 'p':
+           size = sizeof(char*);
            break;
+
+       case 's' | TYPE_IS_SHRIEKING:
        case 'S' | TYPE_IS_SHRIEKING:
-#if SHORTSIZE != SIZE16
-           size = sizeof(unsigned short);
-           break;
-#else
-            /* FALL THROUGH */
-#endif
        case 'v' | TYPE_IS_SHRIEKING:
        case 'n' | TYPE_IS_SHRIEKING:
-       case 'v':
-       case 'n':
-       case 'S':
-           size = SIZE16;
-           break;
        case 'i' | TYPE_IS_SHRIEKING:
-       case 'i':
-           size = sizeof(int);
-           break;
        case 'I' | TYPE_IS_SHRIEKING:
-       case 'I':
-           size = sizeof(unsigned int);
-           break;
-       case 'j':
-           size = IVSIZE;
-           break;
-       case 'J':
-           size = UVSIZE;
-           break;
        case 'l' | TYPE_IS_SHRIEKING:
-#if LONGSIZE != SIZE32
-           size = sizeof(long);
-            break;
-#else
-            /* FALL THROUGH */
-#endif
-       case 'l':
-           size = SIZE32;
-           break;
        case 'L' | TYPE_IS_SHRIEKING:
-#if LONGSIZE != SIZE32
-           size = sizeof(unsigned long);
-           break;
-#else
-            /* FALL THROUGH */
-#endif
        case 'V' | TYPE_IS_SHRIEKING:
        case 'N' | TYPE_IS_SHRIEKING:
+       case 'i':
+       case 'I':
+       case 'j':
+       case 'J':
+       case 'l':
+       case 's':
+       case 'v':
+       case 'n':
+       case 'S':
        case 'V':
        case 'N':
        case 'L':
-           size = SIZE32;
-           break;
-       case 'P':
-           len = 1;
-           /* FALL THROUGH */
-       case 'p':
-           size = sizeof(char*);
-           break;
 #ifdef HAS_QUAD
        case 'q':
-           size = sizeof(Quad_t);
-           break;
        case 'Q':
-           size = sizeof(Uquad_t);
-           break;
 #endif
        case 'f':
-           size = sizeof(float);
-           break;
        case 'd':
-           size = sizeof(double);
-           break;
        case 'F':
-           size = NVSIZE;
-           break;
 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
        case 'D':
-           size = LONG_DOUBLESIZE;
-           break;
 #endif
+           {
+               int which = (symptr->code & TYPE_IS_SHRIEKING)
+                   ? PACK_SIZE_SHRIEKING : PACK_SIZE_NORMAL;
+               int offset
+                   = TYPE_NO_MODIFIERS(symptr->code) - packsize[which].first;
+               assert (offset >= 0);
+               assert (offset < packsize[which].size);
+               size = packsize[which].array[offset] & PACK_SIZE_MASK;
+               assert(size);
+               break;
+           }
        }
        total += len * size;
     }
@@ -758,6 +877,32 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
 
       redo_switch:
         beyond = s >= strend;
+       {
+           int which = (symptr->code & TYPE_IS_SHRIEKING)
+               ? PACK_SIZE_SHRIEKING : PACK_SIZE_NORMAL;
+           int offset = TYPE_NO_MODIFIERS(datumtype) - packsize[which].first;
+
+           if (offset >= 0 && offset < packsize[which].size) {
+               /* Data about this template letter  */
+               unsigned char data = packsize[which].array[offset];
+
+               if (data) {
+                   /* data nonzero means we can process this letter.  */
+                   long size = data & PACK_SIZE_MASK;
+                   long howmany = (strend - s) / size;
+                   if (len > howmany)
+                       len = howmany;
+
+                   if (!checksum || (data & PACK_SIZE_CANNOT_CSUM)) {
+                       if (len && unpack_only_one &&
+                           !(data & PACK_SIZE_CANNOT_ONLY_ONE))
+                           len = 1;
+                       EXTEND(SP, len);
+                       EXTEND_MORTAL(len);
+                   }
+               }
+           }
+       }
        switch(TYPE_NO_ENDIANNESS(datumtype)) {
        default:
            Perl_croak(aTHX_ "Invalid type '%c' in unpack", (int)TYPE_NO_MODIFIERS(datumtype) );
@@ -951,14 +1096,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            XPUSHs(sv_2mortal(sv));
            break;
        case 'c':
-           if (len > strend - s)
-               len = strend - s;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                aint = *s++;
                if (aint >= 128)        /* fake up signed chars */
@@ -978,8 +1115,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
                 symptr->flags &= ~FLAG_UNPACK_DO_UTF8;
                break;
            }
-           if (len > strend - s)
-               len = strend - s;
            if (checksum) {
              uchar_checksum:
                while (len-- > 0) {
@@ -988,10 +1123,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
                }
            }
            else {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
                while (len-- > 0) {
                    auint = *s++ & 255;
                    PUSHs(sv_2mortal(newSViv((IV)auint)));
@@ -1005,14 +1136,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            if ((symptr->flags & FLAG_UNPACK_DO_UTF8) == 0)
                 goto unpack_C;
-           if (len > strend - s)
-               len = strend - s;
-           if (!checksum) {
-               if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0 && s < strend) {
                STRLEN alen;
                auint = NATIVE_TO_UNI(utf8n_to_uvchr((U8*)s, strend - s, &alen, ckWARN(WARN_UTF8) ? 0 : UTF8_ALLOW_ANYUV));
@@ -1029,15 +1152,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 's' | TYPE_IS_SHRIEKING:
 #if SHORTSIZE != SIZE16
-           along = (strend - s) / sizeof(short);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPYNN(s, &ashort, sizeof(short));
                DO_BO_UNPACK(ashort, s);
@@ -1055,15 +1169,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            /* Fallthrough! */
 #endif
        case 's':
-           along = (strend - s) / SIZE16;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY16(s, &ai16);
                DO_BO_UNPACK(ai16, 16);
@@ -1083,15 +1188,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'S' | TYPE_IS_SHRIEKING:
 #if SHORTSIZE != SIZE16
-           along = (strend - s) / sizeof(unsigned short);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-               if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPYNN(s, &aushort, sizeof(unsigned short));
                DO_BO_UNPACK(aushort, s);
@@ -1111,15 +1207,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
        case 'v':
        case 'n':
        case 'S':
-           along = (strend - s) / SIZE16;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY16(s, &au16);
                DO_BO_UNPACK(au16, 16);
@@ -1143,15 +1230,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'v' | TYPE_IS_SHRIEKING:
        case 'n' | TYPE_IS_SHRIEKING:
-           along = (strend - s) / SIZE16;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY16(s, &ai16);
                s += SIZE16;
@@ -1174,15 +1252,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'i':
        case 'i' | TYPE_IS_SHRIEKING:
-           along = (strend - s) / sizeof(int);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &aint, 1, int);
                DO_BO_UNPACK(aint, i);
@@ -1198,15 +1267,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'I':
        case 'I' | TYPE_IS_SHRIEKING:
-           along = (strend - s) / sizeof(unsigned int);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &auint, 1, unsigned int);
                DO_BO_UNPACK(auint, i);
@@ -1221,15 +1281,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'j':
-           along = (strend - s) / IVSIZE;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &aiv, 1, IV);
 #if IVSIZE == INTSIZE
@@ -1250,15 +1301,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'J':
-           along = (strend - s) / UVSIZE;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &auv, 1, UV);
 #if UVSIZE == INTSIZE
@@ -1280,15 +1322,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'l' | TYPE_IS_SHRIEKING:
 #if LONGSIZE != SIZE32
-           along = (strend - s) / sizeof(long);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPYNN(s, &along, sizeof(long));
                DO_BO_UNPACK(along, l);
@@ -1306,15 +1339,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            /* Fallthrough! */
 #endif
        case 'l':
-           along = (strend - s) / SIZE32;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY32(s, &ai32);
                DO_BO_UNPACK(ai32, 32);
@@ -1334,15 +1358,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'L' | TYPE_IS_SHRIEKING:
 #if LONGSIZE != SIZE32
-           along = (strend - s) / sizeof(unsigned long);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPYNN(s, &aulong, sizeof(unsigned long));
                DO_BO_UNPACK(aulong, l);
@@ -1362,15 +1377,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
        case 'V':
        case 'N':
        case 'L':
-           along = (strend - s) / SIZE32;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY32(s, &au32);
                DO_BO_UNPACK(au32, 32);
@@ -1394,15 +1400,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
        case 'V' | TYPE_IS_SHRIEKING:
        case 'N' | TYPE_IS_SHRIEKING:
-           along = (strend - s) / SIZE32;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                COPY32(s, &ai32);
                s += SIZE32;
@@ -1424,11 +1421,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'p':
-           along = (strend - s) / sizeof(char*);
-           if (len > along)
-               len = along;
-           EXTEND(SP, len);
-           EXTEND_MORTAL(len);
            while (len-- > 0) {
                if (sizeof(char*) > strend - s)
                    break;
@@ -1442,10 +1434,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'w':
-            if (len && unpack_only_one)
-                len = 1;
-           EXTEND(SP, len);
-           EXTEND_MORTAL(len);
            {
                UV auv = 0;
                U32 bytes = 0;
@@ -1500,15 +1488,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
 #ifdef HAS_QUAD
        case 'q':
-           along = (strend - s) / sizeof(Quad_t);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-                EXTEND(SP, len);
-                EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                assert (s + sizeof(Quad_t) <= strend);
                Copy(s, &aquad, 1, Quad_t);
@@ -1525,15 +1504,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'Q':
-           along = (strend - s) / sizeof(Uquad_t);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-                EXTEND(SP, len);
-                EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                assert (s + sizeof(Uquad_t) <= strend);
                Copy(s, &auquad, 1, Uquad_t);
@@ -1552,15 +1522,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
 #endif
        /* float and double added gnb@melba.bby.oz.au 22/11/89 */
        case 'f':
-           along = (strend - s) / sizeof(float);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &afloat, 1, float);
                DO_BO_UNPACK_N(afloat, float);
@@ -1574,15 +1535,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'd':
-           along = (strend - s) / sizeof(double);
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &adouble, 1, double);
                DO_BO_UNPACK_N(adouble, double);
@@ -1596,15 +1548,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            }
            break;
        case 'F':
-           along = (strend - s) / NVSIZE;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &anv, 1, NV);
                DO_BO_UNPACK_N(anv, NV);
@@ -1619,15 +1562,6 @@ S_unpack_rec(pTHX_ register tempsym_t* symptr, register char *s, char *strbeg, c
            break;
 #if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
        case 'D':
-           along = (strend - s) / LONG_DOUBLESIZE;
-           if (len > along)
-               len = along;
-           if (!checksum) {
-                if (len && unpack_only_one)
-                    len = 1;
-               EXTEND(SP, len);
-               EXTEND_MORTAL(len);
-           }
            while (len-- > 0) {
                Copy(s, &aldouble, 1, long double);
                DO_BO_UNPACK_N(aldouble, long double);