File Coverage

blib/lib/Devel/Chitin/OpTree/PVOP.pm
Criterion Covered Total %
statement 54 145 37.2
branch 15 74 20.2
condition 7 30 23.3
subroutine 11 15 73.3
pod 0 12 0.0
total 87 276 31.5


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