File Coverage

blib/lib/ExtUtils/Typemaps/OutputMap.pm
Criterion Covered Total %
statement 55 56 98.2
branch 16 18 88.8
condition 3 6 50.0
subroutine 11 11 100.0
pod 6 6 100.0
total 91 97 93.8


line stmt bran cond sub pod time code
1             package ExtUtils::Typemaps::OutputMap;
2 16     16   288 use 5.006001;
  16         78  
3 16     16   125 use strict;
  16         35  
  16         641  
4 16     16   137 use warnings;
  16         43  
  16         15531  
5             our $VERSION = '3.61';
6              
7             =head1 NAME
8              
9             ExtUtils::Typemaps::OutputMap - Entry in the OUTPUT section of a typemap
10              
11             =head1 SYNOPSIS
12              
13             use ExtUtils::Typemaps;
14             ...
15             my $output = $typemap->get_output_map('T_NV');
16             my $code = $output->code();
17             $output->code("...");
18              
19             =head1 DESCRIPTION
20              
21             Refer to L for details.
22              
23             =head1 METHODS
24              
25             =cut
26              
27             =head2 new
28              
29             Requires C and C parameters.
30              
31             =cut
32              
33             sub new {
34 82547     82547 1 330628 my $prot = shift;
35 82547   66     208114 my $class = ref($prot)||$prot;
36 82547         180027 my %args = @_;
37              
38 82547 100       162109 if (!ref($prot)) {
39 27554 50 33     93700 if (not defined $args{xstype} or not defined $args{code}) {
40 0         0 die("Need xstype and code parameters");
41             }
42             }
43              
44 82547 100       345297 my $self = bless(
45             (ref($prot) ? {%$prot} : {})
46             => $class
47             );
48              
49 82547 100       216832 $self->{xstype} = $args{xstype} if defined $args{xstype};
50 82547 100       183345 $self->{code} = $args{code} if defined $args{code};
51 82547         255042 $self->{code} =~ s/^(?=\S)/\t/mg;
52              
53 82547         246248 return $self;
54             }
55              
56             =head2 code
57              
58             Returns or sets the OUTPUT mapping code for this entry.
59              
60             =cut
61              
62             sub code {
63 582 50   582 1 1733 $_[0]->{code} = $_[1] if @_ > 1;
64 582         1837 return $_[0]->{code};
65             }
66              
67             =head2 xstype
68              
69             Returns the name of the XS type of the OUTPUT map.
70              
71             =cut
72              
73             sub xstype {
74 110030     110030 1 334087 return $_[0]->{xstype};
75             }
76              
77             =head2 cleaned_code
78              
79             Returns a cleaned-up copy of the code to which certain transformations
80             have been applied to make it more ANSI compliant.
81              
82             =cut
83              
84             sub cleaned_code {
85 253     253 1 480 my $self = shift;
86 253         871 my $code = $self->code;
87              
88             # Move C pre-processor instructions to column 1 to be strictly ANSI
89             # conformant. Some pre-processors are fussy about this.
90 253         741 $code =~ s/^\s+#/#/mg;
91 253         3350 $code =~ s/\s*\z/\n/;
92              
93 253         814 return $code;
94             }
95              
96             =head2 targetable_legacy
97              
98             Do not use for new code.
99              
100             This is the original version of the targetable() method, whose behaviour
101             has been frozen for backwards compatibility. It is used to determine
102             whether to emit an early C, which will be in scope for most of
103             the XSUB. More recent XSUB code generation emits a C in a tighter
104             scope if one has not already been emitted. Some XS code assumes that
105             C has been declared, so continue to declare it under the same
106             conditions as before. The newer C method may be true under
107             additional circumstances.
108              
109             If the optimization can not be applied, this returns undef. If it can be
110             applied, this method returns a hash reference containing the following
111             information:
112              
113             type: Any of the characters i, u, n, p
114             with_size: Bool indicating whether this is the sv_setpvn variant
115             what: The code that actually evaluates to the output scalar
116             what_size: If "with_size", this has the string length (as code,
117             not constant, including leading comma)
118              
119              
120             =cut
121              
122             sub targetable_legacy {
123 247     247 1 616 my $self = shift;
124 247 100       1076 return $self->{targetable_legacy} if exists $self->{targetable_legacy};
125              
126 208         517 our $bal; # ()-balanced
127             $bal = qr[
128             (?:
129             (?>[^()]+)
130             |
131             \( (??{ $bal }) \)
132             )*
133 208         5663 ]x;
134             my $bal_no_comma = qr[
135             (?:
136             (?>[^(),]+)
137             |
138             \( (??{ $bal }) \)
139             )+
140 208         1445 ]x;
141              
142             # matches variations on (SV*)
143 208         692 my $sv_cast = qr[
144             (?:
145             \( \s* SV \s* \* \s* \) \s*
146             )?
147             ]x;
148              
149             my $size = qr[ # Third arg (to setpvn)
150             , \s* (??{ $bal })
151 208         2830 ]xo;
152              
153 208         769 my $code = $self->code;
154              
155             # We can still bootstrap compile 're', because in code re.pm is
156             # available to miniperl, and does not attempt to load the XS code.
157 16     16   153 use re 'eval';
  16         40  
  16         10392  
158              
159 208         4654 my ($type, $with_size, $arg, $sarg) =
160             ($code =~
161             m[^
162             \s+
163             sv_set([iunp])v(n)? # Type, is_setpvn
164             \s*
165             \( \s*
166             $sv_cast \$arg \s* , \s*
167             ( $bal_no_comma ) # Set from
168             ( $size )? # Possible sizeof set-from
169             \s* \) \s* ; \s* $
170             ]xo
171             );
172              
173 208         609 my $rv = undef;
174 208 100       615 if ($type) {
175 164         1835 $rv = {
176             type => $type,
177             with_size => $with_size,
178             what => $arg,
179             what_size => $sarg,
180             };
181             }
182 208         666 $self->{targetable_legacy} = $rv;
183 208         2102 return $rv;
184             }
185              
186             =head2 targetable
187              
188             Class method.
189              
190             Return a boolean indicating whether the supplied code snippet is suitable
191             for using TARG as the destination SV rather than an new mortal.
192              
193             In principle most things are, except expressions which would set the SV
194             to a ref value. That can cause the referred value to never be freed, as
195             targs aren't freed (at least for the lifetime of their CV). So in
196             practice, we restrict it to an approved list of sv_setfoo() forms, and
197             only where there is no extra code following the sv_setfoo() (so we have to
198             match the closing bracket, allowing for nested brackets etc within).
199              
200             =cut
201              
202             my %targetable_cache;
203              
204             sub targetable {
205 238     238 1 27534 my ($class, $code) = @_;
206              
207 238 100       2605 return $targetable_cache{$code} if exists $targetable_cache{$code};
208              
209             # Match a string with zero or more balanced/nested parentheses
210             # within it, e.g.
211             #
212             # "aa,bb(cc,dd)ee(ff,gg(hh,ii)jj,kk)ll"
213              
214 67         91 our $bal;
215             $bal = qr[
216             (?:
217             (?>[^()]+)
218             |
219             " ([^"] | \\")* "
220             |
221             \( (??{ $bal }) \)
222             )*
223 67         784 ]x;
224              
225             # Like $bal, but doesn't allow commas at the *top* level; e.g.
226             #
227             # "aabb(cc,dd)ee(ff,gg(hh,ii)jj,kk)ll"
228             #
229             # Something like "aa,bb(cc,dd)" will just match/consume the "aa"
230             # part of the string.
231              
232             my $bal_no_comma = qr[
233             (?:
234             (?>[^(),]+)
235             |
236             " ([^"] | \\")* "
237             |
238             \( (??{ $bal }) \)
239             )+
240 67         821 ]x;
241              
242             # the SV whose value is to be set (typically arg 1)
243             # Note that currently ParseXS will always call with $arg expanded
244             # to 'RETVALSV', but also match other possibilities too for future
245             # use.
246              
247 67         183 my $target = qr[
248             (?:
249             \( \s* SV \s* \* \s* \) \s* # optional SV* cast
250             )?
251             (?:
252             \$arg
253             |
254             RETVAL
255             |
256             RETVALSV
257             |
258             ST\(\d+\)
259             )
260             \s*
261             ]x;
262              
263             # We can still bootstrap compile 're', because in code re.pm is
264             # available to miniperl, and does not attempt to load the XS code.
265 16     16   143 use re 'eval';
  16         73  
  16         3155  
266              
267 67         3025 my $match =
268             ($code =~
269             m[^
270             \s*
271             (?:
272             # 1-arg functions
273             sv_set_(?:undef|true|false)
274             \s*
275             \( \s*
276             $target # arg 1: SV to set
277             |
278             # 2-arg functions
279             sv_set(?:iv|iv_mg|uv|uv_mg|nv|nv_mg|pv|pv_mg|_bool)
280             \s*
281             \( \s*
282             $target # arg 1: SV to set
283             , \s*
284             $bal_no_comma # arg 2: value to use
285             |
286             # 3-arg functions
287             sv_set(?:pvn|pvn_mg)
288             \s*
289             \( \s*
290             $target # arg 1: SV to set
291             , \s*
292             $bal_no_comma # arg 2: value to use
293             , \s*
294             $bal_no_comma # arg 3: length
295             )
296             \s* \)
297             \s* ; \s*
298             $
299             ]xo
300             );
301              
302 67         267 $targetable_cache{$code} = $match;
303 67         626 return $match;
304             }
305              
306             =head1 SEE ALSO
307              
308             L
309              
310             =head1 AUTHOR
311              
312             Steffen Mueller C<>
313              
314             =head1 COPYRIGHT & LICENSE
315              
316             Copyright 2009, 2010, 2011, 2012 Steffen Mueller
317              
318             This program is free software; you can redistribute it and/or
319             modify it under the same terms as Perl itself.
320              
321             =cut
322              
323             1;
324