line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package ExtUtils::XSpp::Typemap; |
2
|
21
|
|
|
21
|
|
1806267
|
use strict; |
|
21
|
|
|
|
|
43
|
|
|
21
|
|
|
|
|
773
|
|
3
|
21
|
|
|
21
|
|
124
|
use warnings; |
|
21
|
|
|
|
|
45
|
|
|
21
|
|
|
|
|
706
|
|
4
|
|
|
|
|
|
|
|
5
|
21
|
|
|
21
|
|
23907
|
use ExtUtils::Typemaps; |
|
21
|
|
|
|
|
1096995
|
|
|
21
|
|
|
|
|
32744
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require ExtUtils::XSpp::Node::Type; |
8
|
|
|
|
|
|
|
require ExtUtils::XSpp::Typemap::parsed; |
9
|
|
|
|
|
|
|
require ExtUtils::XSpp::Typemap::simple; |
10
|
|
|
|
|
|
|
require ExtUtils::XSpp::Typemap::reference; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
my %TypemapsByName; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=head1 NAME |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
ExtUtils::XSpp::Typemap - map types |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=cut |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub new { |
21
|
3131
|
|
|
3131
|
0
|
4239
|
my $class = shift; |
22
|
3131
|
|
|
|
|
8063
|
my $this = bless {}, $class; |
23
|
|
|
|
|
|
|
|
24
|
3131
|
|
|
|
|
9196
|
$this->init( @_ ); |
25
|
|
|
|
|
|
|
|
26
|
3131
|
|
|
|
|
7583
|
return $this; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub create { |
30
|
28
|
|
|
28
|
0
|
80
|
my( $name, @args ) = @_; |
31
|
|
|
|
|
|
|
|
32
|
28
|
50
|
|
|
|
92
|
if( my $template = $TypemapsByName{$name} ) { |
33
|
0
|
|
|
|
|
0
|
my $package = ref $template; |
34
|
|
|
|
|
|
|
|
35
|
0
|
|
|
|
|
0
|
return $package->new( base => $template, @args ); |
36
|
|
|
|
|
|
|
} else { |
37
|
28
|
|
|
|
|
79
|
my $package = "ExtUtils::XSpp::Typemap::" . $name; |
38
|
|
|
|
|
|
|
|
39
|
28
|
|
|
|
|
234
|
return $package->new( @args ); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head1 METHODS |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::type |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
Returns the ExtUtils::XSpp::Node::Type that is used for this typemap. |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
50
|
|
|
|
|
|
|
|
51
|
122
|
|
|
122
|
1
|
494
|
sub type { $_[0]->{TYPE} } |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::xs_type() |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
(Optional) XS typemap identifier (e.g. T_IV) for this C++ type. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::xs_input_code() |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
(Optional) XS input code for the associated XS typemap. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::xs_output_code() |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
(Optional) XS output code for the associated XS typemap. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::cpp_type() |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
Returns the C++ type to be used for the local variable declaration. |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::input_code( perl_argument_name, cpp_var_name1, ... ) |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Code to put the contents of the perl_argument (typically ST(x)) into |
72
|
|
|
|
|
|
|
the C++ variable(s). |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::output_code( perl_variable, c_variable ) |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::cleanup_code( perl_variable, c_variable ) |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::call_parameter_code( parameter_name ) |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
=head2 ExtUtils::XSpp::Typemap::call_function_code( function_call_code, return_variable ) |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
Allows modifying the code used in the function/method call. The first |
83
|
|
|
|
|
|
|
parameter has the form Cmethod( )>, the second |
84
|
|
|
|
|
|
|
parameter is a variable to hold the return value. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut |
87
|
|
|
|
|
|
|
|
88
|
0
|
|
|
0
|
0
|
0
|
sub init { } |
89
|
|
|
|
|
|
|
|
90
|
1609
|
|
|
1609
|
1
|
5473
|
sub xs_type { $_[0]->{XS_TYPE} } |
91
|
13
|
|
|
13
|
1
|
53
|
sub xs_input_code { $_[0]->{XS_INPUT_CODE} } |
92
|
13
|
|
|
13
|
1
|
52
|
sub xs_output_code { $_[0]->{XS_OUTPUT_CODE} } |
93
|
3333
|
|
|
3333
|
0
|
12190
|
sub name { $_[0]->{NAME} } |
94
|
0
|
|
|
0
|
1
|
0
|
sub cpp_type { die; } |
95
|
0
|
|
|
0
|
1
|
0
|
sub input_code { die; } |
96
|
111
|
|
|
111
|
0
|
264
|
sub precall_code { undef } |
97
|
0
|
|
|
0
|
1
|
0
|
sub output_code { undef } |
98
|
71
|
|
|
71
|
1
|
318
|
sub cleanup_code { undef } |
99
|
0
|
|
|
0
|
1
|
0
|
sub call_parameter_code { undef } |
100
|
0
|
|
|
0
|
1
|
0
|
sub call_function_code { undef } |
101
|
140
|
|
|
140
|
0
|
2597
|
sub output_list { undef } |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
my @Typemaps; |
104
|
|
|
|
|
|
|
my $Default_output_code = 'sv_setref_pv( $arg, xsp_constructor_class("${my $ntt = $type; $ntt =~ s{^const\s+|[ \t*]+$}{}g; \\$ntt}"), (void*)$var );'; |
105
|
|
|
|
|
|
|
my $Default_input_code = <<'INPUTCODE'; |
106
|
|
|
|
|
|
|
if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) |
107
|
|
|
|
|
|
|
$var = ($type)SvIV((SV*)SvRV( $arg )); |
108
|
|
|
|
|
|
|
else{ |
109
|
|
|
|
|
|
|
warn( \"${Package}::$func_name() -- $var is not a blessed SV reference\" ); |
110
|
|
|
|
|
|
|
XSRETURN_UNDEF; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
INPUTCODE |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# add typemaps for basic C types |
116
|
|
|
|
|
|
|
add_default_typemaps(); |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub add_typemap_for_type { |
119
|
3021
|
|
|
3021
|
0
|
4731
|
my( $type, $typemap ) = @_; |
120
|
|
|
|
|
|
|
|
121
|
3021
|
|
|
|
|
6260
|
unshift @Typemaps, [ $type, $typemap ]; |
122
|
3021
|
100
|
|
|
|
6488
|
$TypemapsByName{$typemap->name} = $typemap if $typemap->name; |
123
|
|
|
|
|
|
|
} |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub reset_typemaps { |
126
|
166
|
|
|
166
|
0
|
242547
|
@Typemaps = (); |
127
|
166
|
|
|
|
|
592
|
add_default_typemaps(); |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# a weak typemap does not override an already existing typemap for the |
131
|
|
|
|
|
|
|
# same type |
132
|
|
|
|
|
|
|
sub add_weak_typemap_for_type { |
133
|
108
|
|
|
108
|
0
|
174
|
my( $type, $typemap ) = @_; |
134
|
108
|
|
|
|
|
278
|
push @Typemaps, [ $type, $typemap ]; |
135
|
108
|
50
|
0
|
|
|
413
|
$TypemapsByName{$typemap->name} ||= $typemap if $typemap->name; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub get_typemap_for_type { |
139
|
227
|
|
|
227
|
0
|
384
|
my $type = shift; |
140
|
|
|
|
|
|
|
|
141
|
227
|
|
|
|
|
433
|
foreach my $t ( @Typemaps ) { |
142
|
2407
|
100
|
|
|
|
6707
|
return ${$t}[1] if $t->[0]->equals( $type ); |
|
227
|
|
|
|
|
1370
|
|
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# construct verbose error message: |
146
|
0
|
|
|
|
|
0
|
my $errmsg = "No typemap for type " . $type->print |
147
|
|
|
|
|
|
|
. "\nThere are typemaps for the following types:\n"; |
148
|
0
|
|
|
|
|
0
|
my @types; |
149
|
0
|
|
|
|
|
0
|
foreach my $t (@Typemaps) { |
150
|
0
|
|
|
|
|
0
|
push @types, " - " . $t->[0]->print . "\n"; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
0
|
0
|
|
|
|
0
|
if (@types) { |
154
|
0
|
|
|
|
|
0
|
$errmsg .= join('', @types); |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
else { |
157
|
0
|
|
|
|
|
0
|
$errmsg .= " (none)\n"; |
158
|
|
|
|
|
|
|
} |
159
|
0
|
|
|
|
|
0
|
$errmsg .= "Did you forget to declare your type in an XS++ typemap?"; |
160
|
|
|
|
|
|
|
|
161
|
0
|
|
|
|
|
0
|
Carp::confess( $errmsg ); |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub get_xs_typemap_code_for_all_typemaps { |
165
|
87
|
|
|
87
|
0
|
940
|
my $typemaps = ExtUtils::Typemaps->new; |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# process typemaps in reverse order, so newer ones take precedence |
168
|
87
|
|
|
|
|
2988
|
my @xs_typemaps = grep $_->[1]->xs_type, reverse @Typemaps; |
169
|
87
|
100
|
|
|
|
818
|
return unless @xs_typemaps; |
170
|
|
|
|
|
|
|
|
171
|
4
|
|
|
|
|
7
|
my %xs_types; |
172
|
4
|
|
100
|
|
|
23
|
foreach my $typemap (grep $_->[1]->cpp_type && $_->[1]->cpp_type ne '_', @xs_typemaps) { |
173
|
7
|
|
|
|
|
479
|
my $xstype = $typemap->[1]->xs_type; |
174
|
|
|
|
|
|
|
|
175
|
7
|
|
|
|
|
25
|
$xs_types{$typemap->[1]->cpp_type} = $xstype; |
176
|
7
|
|
|
|
|
27
|
$typemaps->add_typemap( |
177
|
|
|
|
|
|
|
ctype => $typemap->[1]->cpp_type, |
178
|
|
|
|
|
|
|
xstype => $xstype, |
179
|
|
|
|
|
|
|
replace => 1, |
180
|
|
|
|
|
|
|
); |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# avoid adding INPUT/OUTPUT sections for unused mappings |
184
|
4
|
|
|
|
|
481
|
%xs_types = reverse %xs_types; |
185
|
4
|
|
50
|
|
|
18
|
foreach my $typemap (grep $xs_types{$_->[1]->xs_type || ''}, @xs_typemaps) { |
186
|
9
|
|
|
|
|
256
|
my $xstype = $typemap->[1]->xs_type; |
187
|
|
|
|
|
|
|
|
188
|
9
|
100
|
|
|
|
41
|
$typemaps->add_inputmap( |
189
|
|
|
|
|
|
|
xstype => $xstype, |
190
|
|
|
|
|
|
|
code => $typemap->[1]->xs_input_code, |
191
|
|
|
|
|
|
|
replace => 1, |
192
|
|
|
|
|
|
|
) if $typemap->[1]->xs_input_code; |
193
|
|
|
|
|
|
|
|
194
|
9
|
100
|
|
|
|
397
|
$typemaps->add_outputmap( |
195
|
|
|
|
|
|
|
xstype => $xstype, |
196
|
|
|
|
|
|
|
code => $typemap->[1]->xs_output_code, |
197
|
|
|
|
|
|
|
replace => 1, |
198
|
|
|
|
|
|
|
) if $typemap->[1]->xs_output_code; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
|
201
|
4
|
50
|
|
|
|
350
|
return '' if $typemaps->is_empty; |
202
|
4
|
|
|
|
|
41
|
my $code = $typemaps->as_string; |
203
|
4
|
|
|
|
|
224
|
my $end_marker = 'END'; |
204
|
4
|
|
|
|
|
65
|
while ($code =~ /^\Q$end_marker\E\s*$/m) { |
205
|
0
|
|
|
|
|
0
|
$end_marker .= '_'; |
206
|
|
|
|
|
|
|
} |
207
|
4
|
|
|
|
|
61
|
return "TYPEMAP: <<$end_marker\n$code\n$end_marker\n"; |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# adds default typemaps for C* and C& |
211
|
|
|
|
|
|
|
sub add_class_default_typemaps { |
212
|
54
|
|
|
54
|
0
|
151
|
my( $name ) = @_; |
213
|
|
|
|
|
|
|
|
214
|
54
|
|
|
|
|
278
|
my $ptr = ExtUtils::XSpp::Node::Type->new |
215
|
|
|
|
|
|
|
( base => $name, |
216
|
|
|
|
|
|
|
pointer => 1, |
217
|
|
|
|
|
|
|
); |
218
|
54
|
|
|
|
|
240
|
my $ref = ExtUtils::XSpp::Node::Type->new |
219
|
|
|
|
|
|
|
( base => $name, |
220
|
|
|
|
|
|
|
reference => 1, |
221
|
|
|
|
|
|
|
); |
222
|
|
|
|
|
|
|
|
223
|
54
|
|
|
|
|
397
|
my $xs_type = $TypemapsByName{object}->xs_type; |
224
|
|
|
|
|
|
|
|
225
|
54
|
|
|
|
|
569
|
add_weak_typemap_for_type |
226
|
|
|
|
|
|
|
( $ptr, ExtUtils::XSpp::Typemap::simple->new( type => $ptr, xs_type => $xs_type ) ); |
227
|
54
|
|
|
|
|
455
|
add_weak_typemap_for_type |
228
|
|
|
|
|
|
|
( $ref, ExtUtils::XSpp::Typemap::reference->new( type => $ref, xs_type => $xs_type ) ); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub add_default_typemaps { |
232
|
|
|
|
|
|
|
# void, integral and floating point types |
233
|
187
|
|
|
187
|
0
|
617
|
foreach my $t ( 'char', 'short', 'int', 'long', 'bool', |
234
|
|
|
|
|
|
|
'unsigned char', 'unsigned short', 'unsigned int', |
235
|
|
|
|
|
|
|
'unsigned long', 'void', |
236
|
|
|
|
|
|
|
'float', 'double', 'long double' ) { |
237
|
2431
|
|
|
|
|
7383
|
my $type = ExtUtils::XSpp::Node::Type->new( base => $t ); |
238
|
|
|
|
|
|
|
|
239
|
2431
|
|
|
|
|
7117
|
ExtUtils::XSpp::Typemap::add_typemap_for_type |
240
|
|
|
|
|
|
|
( $type, ExtUtils::XSpp::Typemap::simple->new( type => $type ) ); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
# char*, const char* |
244
|
187
|
|
|
|
|
780
|
my $char_p = ExtUtils::XSpp::Node::Type->new |
245
|
|
|
|
|
|
|
( base => 'char', |
246
|
|
|
|
|
|
|
pointer => 1, |
247
|
|
|
|
|
|
|
); |
248
|
|
|
|
|
|
|
|
249
|
187
|
|
|
|
|
595
|
ExtUtils::XSpp::Typemap::add_typemap_for_type |
250
|
|
|
|
|
|
|
( $char_p, ExtUtils::XSpp::Typemap::simple->new( type => $char_p ) ); |
251
|
|
|
|
|
|
|
|
252
|
187
|
|
|
|
|
718
|
my $const_char_p = ExtUtils::XSpp::Node::Type->new |
253
|
|
|
|
|
|
|
( base => 'char', |
254
|
|
|
|
|
|
|
pointer => 1, |
255
|
|
|
|
|
|
|
const => 1, |
256
|
|
|
|
|
|
|
); |
257
|
|
|
|
|
|
|
|
258
|
187
|
|
|
|
|
554
|
ExtUtils::XSpp::Typemap::add_typemap_for_type |
259
|
|
|
|
|
|
|
( $const_char_p, ExtUtils::XSpp::Typemap::simple->new( type => $const_char_p ) ); |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
# objects |
262
|
187
|
|
|
|
|
681
|
my $dummy_type = ExtUtils::XSpp::Node::Type->new( base => '' ); |
263
|
187
|
|
|
|
|
1349
|
my $obj_typemap = ExtUtils::XSpp::Typemap::parsed->new( |
264
|
|
|
|
|
|
|
name => 'object', |
265
|
|
|
|
|
|
|
type => $dummy_type, |
266
|
|
|
|
|
|
|
xs_input_code => $Default_input_code, |
267
|
|
|
|
|
|
|
xs_output_code => $Default_output_code, |
268
|
|
|
|
|
|
|
); |
269
|
|
|
|
|
|
|
|
270
|
187
|
|
|
|
|
440
|
ExtUtils::XSpp::Typemap::add_typemap_for_type( $dummy_type, $obj_typemap ) |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub _enable_default_xs_typemaps { |
274
|
1
|
|
|
1
|
|
4
|
foreach my $t ( reverse @Typemaps ) { |
275
|
16
|
100
|
100
|
|
|
41
|
if( ($t->[1]->name || '') eq 'object' ) { |
276
|
1
|
|
50
|
|
|
8
|
$t->[1]{XS_TYPE} ||= 'O_OBJECT'; |
277
|
1
|
|
|
|
|
4
|
last; |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
} |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
1; |