B, Deparse fixups for tr///c
authorDavid Mitchell <davem@iabyn.com>
Fri, 12 Jan 2018 14:35:03 +0000 (14:35 +0000)
committerDavid Mitchell <davem@iabyn.com>
Fri, 19 Jan 2018 13:45:20 +0000 (13:45 +0000)
Recent commits slightly changed the layout of the extended map table: it
now always stores a repeat count, and there are now two structs defined,
rather than treating certain slots, like tbl[0x101], specially.

Update B and Deparse to reflect this.

ext/B/B.xs
lib/B/Deparse.pm
lib/B/Deparse.t

index 6211225..b7d80e4 100644 (file)
@@ -1022,20 +1022,23 @@ next(o)
                ret = make_sv_object(aTHX_ NULL);
                break;
            case 41: /* B::PVOP::pv */
-               /* OP_TRANS uses op_pv to point to a table of 256 or >=258
-                * shorts whereas other PVOPs point to a null terminated
-                * string.  */
-               if (    (cPVOPo->op_type == OP_TRANS
-                       || cPVOPo->op_type == OP_TRANSR) &&
-                       (cPVOPo->op_private & OPpTRANS_COMPLEMENT) &&
-                       !(cPVOPo->op_private & OPpTRANS_DELETE))
-               {
-                   const short* const tbl = (short*)cPVOPo->op_pv;
-                   const short entries = 257 + tbl[256];
-                   ret = newSVpvn_flags(cPVOPo->op_pv, entries * sizeof(short), SVs_TEMP);
-               }
-               else if (cPVOPo->op_type == OP_TRANS || cPVOPo->op_type == OP_TRANSR) {
-                   ret = newSVpvn_flags(cPVOPo->op_pv, 256 * sizeof(short), SVs_TEMP);
+               /* OP_TRANS uses op_pv to point to a OPtrans_map or
+                 * OPtrans_map_ex struct, whereas other PVOPs point to a
+                 * null terminated string. For trans, for now just return the
+                 * whole struct as a string and let the caller unpack() it */
+               if (   cPVOPo->op_type == OP_TRANS
+                    || cPVOPo->op_type == OP_TRANSR)
+                {
+                    const OPtrans_map_ex * const extbl =
+                                                (OPtrans_map_ex*)cPVOPo->op_pv;
+                    char *end = (char*)(&(extbl->map[256]));
+                    if (cPVOPo->op_private & OPpTRANS_COMPLEMENT) {
+                        short excess_len = extbl->excess_len;
+                        end = (char*)(&(extbl->map_ex[excess_len]));
+                    }
+                   ret = newSVpvn_flags(cPVOPo->op_pv,
+                                            end - (char*)extbl,
+                                            SVs_TEMP);
                }
                else
                    ret = newSVpvn_flags(cPVOPo->op_pv, strlen(cPVOPo->op_pv), SVs_TEMP);
index 86f262a..5fc3d02 100644 (file)
@@ -5607,8 +5607,9 @@ sub collapse {
 
 sub tr_decode_byte {
     my($table, $flags) = @_;
-    my(@table) = unpack("s*", $table);
-    splice @table, 0x100, 1;   # Number of subsequent elements
+    my (@table) = unpack("s256sss*", $table);
+    my ($excess_len, $repeat_char) = splice(@table, 256, 2);
+
     my($c, $tr, @from, @to, @delfrom, $delhyphen);
     if ($table[ord "-"] != -1 and
        $table[ord("-") - 1] == -1 || $table[ord("-") + 1] == -1)
index 00fbb01..cbee542 100644 (file)
@@ -1444,6 +1444,20 @@ tr/X//d;
 tr/X//s;
 tr/X//r;
 ####
+# tr with extended table (/c)
+tr/\000-\375/AB/c;
+tr/\000-\375/A-C/c;
+tr/\000-\375/A-D/c;
+tr/\000-\375/A-Z/c;
+tr/\000-\375/AB/cd;
+tr/\000-\375/A-C/cd;
+tr/\000-\375/A-D/cd;
+tr/\000-\375/A-Z/cd;
+tr/\000-\375/AB/cds;
+tr/\000-\375/A-C/cds;
+tr/\000-\375/A-D/cds;
+tr/\000-\375/A-Z/cds;
+####
 # [perl #119807] s//\(3)/ge should not warn when deparsed (\3 warns)
 s/foo/\(3);/eg;
 ####