File Coverage

blib/lib/Devel/Chitin/OpTree/PVOP.pm
Criterion Covered Total %
statement 59 153 38.5
branch 16 78 20.5
condition 7 30 23.3
subroutine 12 16 75.0
pod 0 12 0.0
total 94 289 32.5


line stmt bran cond sub pod time code
1             package Devel::Chitin::OpTree::PVOP;
2 35     35   183 use base 'Devel::Chitin::OpTree';
  35         53  
  35         3620  
3              
4             our $VERSION = '0.16';
5              
6 35     35   188 use strict;
  35         54  
  35         699  
7 35     35   150 use warnings;
  35         53  
  35         956  
8              
9 35     35   165 use Config;
  35         53  
  35         53856  
10              
11             sub pp_dump {
12 1     1 0 15 'dump ' . shift->op->pv;
13             }
14              
15             sub pp_goto {
16 1     1 0 5 'goto ' . shift->op->pv;
17             }
18              
19             sub pp_next {
20 0     0 0 0 'next ' . shift->op->pv;
21             }
22              
23             sub pp_last {
24 1     1 0 6 'last ' . shift->op->pv;
25             }
26              
27             sub pp_redo {
28 0     0 0 0 'redo ' . shift->op->pv;
29             }
30              
31             sub pp_trans {
32 2     2 0 5 my $self = shift;
33              
34 2         6 my $priv_flags = $self->op->private;
35 2         6 my($from, $to) = tr_decode_byte($self->op->pv, $priv_flags);
36              
37 2 50       19 my $flags = join('', map { $priv_flags & $_->[0] ? $_->[1] : () }
  6         31  
38             ([ B::OPpTRANS_COMPLEMENT, 'c' ],
39             [ B::OPpTRANS_DELETE, 'd' ],
40             [ B::OPpTRANS_SQUASH, 's' ]));
41              
42 2         18 "tr/${from}/${to}/$flags";
43             }
44              
45             sub pp_transr {
46 1     1 0 5 shift->pp_trans . 'r';
47             }
48              
49             # These are from B::Deparse
50              
51             # Only used by tr///, so backslashes hyphens
52             sub pchr { # ASCII
53 12     12 0 16 my($n) = @_;
54 12 50 33     41 if ($n == ord '\\') {
    50 0        
    50          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
55 0         0 return '\\\\';
56             } elsif ($n == ord "-") {
57 0         0 return "\\-";
58             } elsif ($n >= ord(' ') and $n <= ord('~')) {
59 12         25 return chr($n);
60             } elsif ($n == ord "\a") {
61 0         0 return '\\a';
62             } elsif ($n == ord "\b") {
63 0         0 return '\\b';
64             } elsif ($n == ord "\t") {
65 0         0 return '\\t';
66             } elsif ($n == ord "\n") {
67 0         0 return '\\n';
68             } elsif ($n == ord "\e") {
69 0         0 return '\\e';
70             } elsif ($n == ord "\f") {
71 0         0 return '\\f';
72             } elsif ($n == ord "\r") {
73 0         0 return '\\r';
74             } elsif ($n >= ord("\cA") and $n <= ord("\cZ")) {
75 0         0 return '\\c' . chr(ord("@") + $n);
76             } else {
77 0         0 return '\\' . sprintf("%03o", $n);
78             }
79             }
80              
81             sub collapse {
82 4     4 0 12 my(@chars) = @_;
83 4         9 my($str, $c, $tr) = ("");
84 4         14 for ($c = 0; $c < @chars; $c++) {
85 12         16 $tr = $chars[$c];
86 12         21 $str .= pchr($tr);
87 12 50 66     42 if ($c <= $#chars - 2
      33        
88             and $chars[$c + 1] == $tr + 1
89             and $chars[$c + 2] == $tr + 2
90             ) {
91 0   0     0 for (; $c <= $#chars-1 and $chars[$c + 1] == $chars[$c] + 1; $c++)
92             {}
93 0         0 $str .= "-";
94 0         0 $str .= pchr($chars[$c]);
95             }
96             }
97 4         11 return $str;
98             }
99              
100             sub tr_decode_byte {
101 2     2 0 6 my($table, $flags) = @_;
102              
103 2         3 my @table;
104 2 50       21 if ($^V lt v5.27.8) {
105 2         60 @table = unpack("s*", $table);
106 2         8 splice @table, 0x100, 1; # Number of subsequent elements
107              
108             } else {
109 0 0       0 my $ssize_t = $Config{ptrsize} == 8 ? 'q' : 'l';
110 0         0 (undef, @table) = unpack("${ssize_t}s*", $table);
111 0         0 pop @table; # remove the wildcard final entry
112             }
113              
114 2         10 my($c, $tr, @from, @to, @delfrom, $delhyphen);
115 2 50 33     24 if ($table[ord "-"] != -1
      33        
116             and
117             $table[ord("-") - 1] == -1
118             ||
119             $table[ord("-") + 1] == -1
120             ) {
121 0         0 $tr = $table[ord "-"];
122 0         0 $table[ord "-"] = -1;
123 0 0       0 if ($tr >= 0) {
124 0         0 @from = ord("-");
125 0         0 @to = $tr;
126             } else { # -2 ==> delete
127 0         0 $delhyphen = 1;
128             }
129             }
130 2         9 for ($c = 0; $c < @table; $c++) {
131 512         513 $tr = $table[$c];
132 512 100       745 if ($tr >= 0) {
    100          
133 8         11 push @from, $c; push @to, $tr;
  8         17  
134             } elsif ($tr == -2) {
135 500         774 push @delfrom, $c;
136             }
137             }
138 2         54 @from = (@from, @delfrom);
139 2 50       13 if ($flags & B::OPpTRANS_COMPLEMENT) {
140 2         7 my @newfrom = ();
141 2         4 my %from;
142 2         387 @from{@from} = (1) x @from;
143 2         13 for ($c = 0; $c < 256; $c++) {
144 512 100       817 push @newfrom, $c unless $from{$c};
145             }
146 2         67 @from = @newfrom;
147             }
148 2 50 33     11 unless ($flags & B::OPpTRANS_DELETE || !@to) {
149 0   0     0 pop @to while $#to and $to[$#to] == $to[$#to -1];
150             }
151 2         5 my($from, $to);
152 2         11 $from = collapse(@from);
153 2         13 $to = collapse(@to);
154 2 50       6 $from .= "-" if $delhyphen;
155 2         34 return ($from, $to);
156             }
157              
158             sub tr_chr {
159 0     0 0   my $x = shift;
160 0 0         if ($x == ord "-") {
    0          
161 0           return "\\-";
162             } elsif ($x == ord "\\") {
163 0           return "\\\\";
164             } else {
165 0           return chr $x;
166             }
167             }
168              
169             # XXX This doesn't yet handle all cases correctly either
170              
171             sub tr_decode_utf8 {
172 0     0 0   my($swash_hv, $flags) = @_;
173 0           my %swash = $swash_hv->ARRAY;
174 0           my $final = undef;
175 0 0         $final = $swash{'FINAL'}->IV if exists $swash{'FINAL'};
176 0           my $none = $swash{"NONE"}->IV;
177 0           my $extra = $none + 1;
178 0           my(@from, @delfrom, @to);
179 0           my $line;
180 0           foreach $line (split /\n/, $swash{'LIST'}->PV) {
181 0           my($min, $max, $result) = split(/\t/, $line);
182 0           $min = hex $min;
183 0 0         if (length $max) {
184 0           $max = hex $max;
185             } else {
186 0           $max = $min;
187             }
188 0           $result = hex $result;
189 0 0         if ($result == $extra) {
190 0           push @delfrom, [$min, $max];
191             } else {
192 0           push @from, [$min, $max];
193 0           push @to, [$result, $result + $max - $min];
194             }
195             }
196 0           for my $i (0 .. $#from) {
197 0 0         if ($from[$i][0] == ord '-') {
    0          
198 0           unshift @from, splice(@from, $i, 1);
199 0           unshift @to, splice(@to, $i, 1);
200 0           last;
201             } elsif ($from[$i][1] == ord '-') {
202 0           $from[$i][1]--;
203 0           $to[$i][1]--;
204 0           unshift @from, ord '-';
205 0           unshift @to, ord '-';
206 0           last;
207             }
208             }
209 0           for my $i (0 .. $#delfrom) {
210 0 0         if ($delfrom[$i][0] == ord '-') {
    0          
211 0           push @delfrom, splice(@delfrom, $i, 1);
212 0           last;
213             } elsif ($delfrom[$i][1] == ord '-') {
214 0           $delfrom[$i][1]--;
215 0           push @delfrom, ord '-';
216 0           last;
217             }
218             }
219 0 0 0       if (defined $final and $to[$#to][1] != $final) {
220 0           push @to, [$final, $final];
221             }
222 0           push @from, @delfrom;
223 0 0         if ($flags & B::OPpTRANS_COMPLEMENT) {
224 0           my @newfrom;
225 0           my $next = 0;
226 0           for my $i (0 .. $#from) {
227 0           push @newfrom, [$next, $from[$i][0] - 1];
228 0           $next = $from[$i][1] + 1;
229             }
230 0           @from = ();
231 0           for my $range (@newfrom) {
232 0 0         if ($range->[0] <= $range->[1]) {
233 0           push @from, $range;
234             }
235             }
236             }
237 0           my($from, $to, $diff);
238 0           for my $chunk (@from) {
239 0           $diff = $chunk->[1] - $chunk->[0];
240 0 0         if ($diff > 1) {
    0          
241 0           $from .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
242             } elsif ($diff == 1) {
243 0           $from .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
244             } else {
245 0           $from .= tr_chr($chunk->[0]);
246             }
247             }
248 0           for my $chunk (@to) {
249 0           $diff = $chunk->[1] - $chunk->[0];
250 0 0         if ($diff > 1) {
    0          
251 0           $to .= tr_chr($chunk->[0]) . "-" . tr_chr($chunk->[1]);
252             } elsif ($diff == 1) {
253 0           $to .= tr_chr($chunk->[0]) . tr_chr($chunk->[1]);
254             } else {
255 0           $to .= tr_chr($chunk->[0]);
256             }
257             }
258             #$final = sprintf("%04x", $final) if defined $final;
259             #$none = sprintf("%04x", $none) if defined $none;
260             #$extra = sprintf("%04x", $extra) if defined $extra;
261             #print STDERR "final: $final\n none: $none\nextra: $extra\n";
262             #print STDERR $swash{'LIST'}->PV;
263 0           return (escape_str($from), escape_str($to));
264             }
265              
266             1;
267              
268             __END__