| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node; |
|
2
|
19
|
|
|
19
|
|
123
|
use strict; |
|
|
19
|
|
|
|
|
53
|
|
|
|
19
|
|
|
|
|
690
|
|
|
3
|
19
|
|
|
19
|
|
81
|
use warnings; |
|
|
19
|
|
|
|
|
45
|
|
|
|
19
|
|
|
|
|
934
|
|
|
4
|
19
|
|
|
19
|
|
94
|
use Symbol; |
|
|
19
|
|
|
|
|
35
|
|
|
|
19
|
|
|
|
|
7996
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '3.61'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 NAME |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
ExtUtils::ParseXS::Node - Classes for nodes of an Abstract Syntax Tree |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# Create a node to represent the Foo part of an XS file; then |
|
15
|
|
|
|
|
|
|
# top-down parse it into a subtree; then top-down emit the |
|
16
|
|
|
|
|
|
|
# contents of the subtree as C code. |
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
my $foo = ExtUtils::ParseXS::Node::Foo->new(); |
|
19
|
|
|
|
|
|
|
$foo->parse(...) |
|
20
|
|
|
|
|
|
|
or die; |
|
21
|
|
|
|
|
|
|
$foo->as_code(...); |
|
22
|
|
|
|
|
|
|
print STDERR $foo->as_concise(1); # for debugging |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
This API is currently private and subject to change. |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
The C class, and its various subclasses, hold the |
|
29
|
|
|
|
|
|
|
state for the nodes of an Abstract Syntax Tree (AST), which represents the |
|
30
|
|
|
|
|
|
|
parsed state of an XS file. |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Each node is a hash of fields. Which field names are legal varies by the |
|
33
|
|
|
|
|
|
|
node type. The hash keys and values can be accessed directly: there are no |
|
34
|
|
|
|
|
|
|
getter/setter methods. |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
Each node may have a C field which points to an array of all the |
|
37
|
|
|
|
|
|
|
children of that node: this is what provides the tree structure. In |
|
38
|
|
|
|
|
|
|
addition, some of those kids may also have direct links from fields for |
|
39
|
|
|
|
|
|
|
quick access. For example, the C child object of an C |
|
40
|
|
|
|
|
|
|
object can be accessed in either of these ways: |
|
41
|
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
$xsub_object->{kids}[0] |
|
43
|
|
|
|
|
|
|
$xsub_object->{decl} |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Most object-valued node fields within a tree point only to their direct |
|
46
|
|
|
|
|
|
|
children; however, both C and C have an |
|
47
|
|
|
|
|
|
|
C field which points to the C object associated with |
|
48
|
|
|
|
|
|
|
this line, which is located elsewhere in the tree. |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
The various C nodes divide the parsing of the main body of an |
|
51
|
|
|
|
|
|
|
XSUB into sections where different sets of keywords are allowable, and |
|
52
|
|
|
|
|
|
|
where various bits of code can be conveniently emitted. |
|
53
|
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=head2 Methods |
|
55
|
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
There are two main methods in addition to C, which are present in |
|
57
|
|
|
|
|
|
|
all subclasses. First, C consumes lines from the source to |
|
58
|
|
|
|
|
|
|
satisfy the construct being parsed. It may itself create objects of |
|
59
|
|
|
|
|
|
|
lower-level constructs and call parse on them. For example, |
|
60
|
|
|
|
|
|
|
C may create a C node and call |
|
61
|
|
|
|
|
|
|
C on it, which will create C or C |
|
62
|
|
|
|
|
|
|
nodes as appropriate, and so on. |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Secondly, C descends its sub-tree, outputting the tree as C |
|
65
|
|
|
|
|
|
|
code. |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
The C method returns a line-per-node string representation |
|
68
|
|
|
|
|
|
|
of the node and any children. Most node classes just inherit this method |
|
69
|
|
|
|
|
|
|
from the base C class. It is intended mainly for debugging. |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Some nodes also have an C method for adding any code to |
|
72
|
|
|
|
|
|
|
the boot XSUB. This returns two array refs, one containing a list of code |
|
73
|
|
|
|
|
|
|
lines to be inserted early into the boot XSUB, and a second for later |
|
74
|
|
|
|
|
|
|
lines. |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Finally, in the IO_Param subclass, C is replaced with |
|
77
|
|
|
|
|
|
|
C and C, since that node may need to |
|
78
|
|
|
|
|
|
|
generate I sets of C code; one to assign a Perl argument to a C |
|
79
|
|
|
|
|
|
|
variable, and the other to return the value of a variable to Perl. |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Note that parsing and code-generation are done as two separate phases; |
|
82
|
|
|
|
|
|
|
C should only build a tree and never emit code. |
|
83
|
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
In addition to C<$self>, methods may commonly have some of these |
|
85
|
|
|
|
|
|
|
parameters: |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=over |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
=item C<$pxs> |
|
90
|
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
An C object which contains the overall processing |
|
92
|
|
|
|
|
|
|
state. In particular, it has warning and croaking methods, and holds the |
|
93
|
|
|
|
|
|
|
lines read in from the source file for the current paragraph. |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=item C<$xsub> |
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
For nodes related to parsing an XSUB, the current |
|
98
|
|
|
|
|
|
|
C node being processed. |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=item C<$xbody> |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
For nodes related to parsing an XSUB, the current |
|
103
|
|
|
|
|
|
|
C node being processed. Note that in the |
|
104
|
|
|
|
|
|
|
presence of a C keyword, an XSUB can have multiple bodies. |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=back |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
The C and C methods for some subclasses may have |
|
109
|
|
|
|
|
|
|
parameters in addition to those. |
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Some subclasses may also have additional helper methods. |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=head2 Class Hierachy |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
C and its sub-classes form the following inheritance hierarchy. |
|
116
|
|
|
|
|
|
|
Various abstract classes are used by concrete subclasses where the |
|
117
|
|
|
|
|
|
|
processing and/or fields are similar: for example, C, C etc |
|
118
|
|
|
|
|
|
|
all consume a block of uninterpreted lines from the source file until the |
|
119
|
|
|
|
|
|
|
next keyword, and emit that code, possibly wrapped in C<#line> directives. |
|
120
|
|
|
|
|
|
|
This common behaviour is provided by the C class. |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Node |
|
123
|
|
|
|
|
|
|
XS_file |
|
124
|
|
|
|
|
|
|
preamble |
|
125
|
|
|
|
|
|
|
C_part |
|
126
|
|
|
|
|
|
|
C_part_POD |
|
127
|
|
|
|
|
|
|
C_part_code |
|
128
|
|
|
|
|
|
|
C_part_postamble |
|
129
|
|
|
|
|
|
|
cpp_scope |
|
130
|
|
|
|
|
|
|
global_cpp_line |
|
131
|
|
|
|
|
|
|
BOOT |
|
132
|
|
|
|
|
|
|
TYPEMAP |
|
133
|
|
|
|
|
|
|
pre_boot |
|
134
|
|
|
|
|
|
|
boot_xsub |
|
135
|
|
|
|
|
|
|
xsub |
|
136
|
|
|
|
|
|
|
xsub_decl |
|
137
|
|
|
|
|
|
|
ReturnType |
|
138
|
|
|
|
|
|
|
Param |
|
139
|
|
|
|
|
|
|
IO_Param |
|
140
|
|
|
|
|
|
|
Params |
|
141
|
|
|
|
|
|
|
xbody |
|
142
|
|
|
|
|
|
|
input_part |
|
143
|
|
|
|
|
|
|
init_part |
|
144
|
|
|
|
|
|
|
code_part |
|
145
|
|
|
|
|
|
|
output_part |
|
146
|
|
|
|
|
|
|
cleanup_part |
|
147
|
|
|
|
|
|
|
autocall |
|
148
|
|
|
|
|
|
|
oneline |
|
149
|
|
|
|
|
|
|
MODULE |
|
150
|
|
|
|
|
|
|
REQUIRE |
|
151
|
|
|
|
|
|
|
FALLBACK |
|
152
|
|
|
|
|
|
|
include |
|
153
|
|
|
|
|
|
|
INCLUDE |
|
154
|
|
|
|
|
|
|
INCLUDE_COMMAND |
|
155
|
|
|
|
|
|
|
NOT_IMPLEMENTED_YET |
|
156
|
|
|
|
|
|
|
CASE |
|
157
|
|
|
|
|
|
|
enable |
|
158
|
|
|
|
|
|
|
EXPORT_XSUB_SYMBOLS |
|
159
|
|
|
|
|
|
|
PROTOTYPES |
|
160
|
|
|
|
|
|
|
SCOPE |
|
161
|
|
|
|
|
|
|
VERSIONCHECK |
|
162
|
|
|
|
|
|
|
multiline |
|
163
|
|
|
|
|
|
|
multiline_merged |
|
164
|
|
|
|
|
|
|
C_ARGS |
|
165
|
|
|
|
|
|
|
INTERFACE |
|
166
|
|
|
|
|
|
|
INTERFACE_MACRO |
|
167
|
|
|
|
|
|
|
OVERLOAD |
|
168
|
|
|
|
|
|
|
ATTRS |
|
169
|
|
|
|
|
|
|
PROTOTYPE |
|
170
|
|
|
|
|
|
|
codeblock |
|
171
|
|
|
|
|
|
|
CODE |
|
172
|
|
|
|
|
|
|
CLEANUP |
|
173
|
|
|
|
|
|
|
INIT |
|
174
|
|
|
|
|
|
|
POSTCALL |
|
175
|
|
|
|
|
|
|
PPCODE |
|
176
|
|
|
|
|
|
|
PREINIT |
|
177
|
|
|
|
|
|
|
keylines |
|
178
|
|
|
|
|
|
|
ALIAS |
|
179
|
|
|
|
|
|
|
INPUT |
|
180
|
|
|
|
|
|
|
OUTPUT |
|
181
|
|
|
|
|
|
|
keyline |
|
182
|
|
|
|
|
|
|
ALIAS_line |
|
183
|
|
|
|
|
|
|
INPUT_line |
|
184
|
|
|
|
|
|
|
OUTPUT_line |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=head2 Abstract Syntax Tree structure |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
A typical XS file might compile to a tree with a node structure similar to |
|
190
|
|
|
|
|
|
|
the following. Note that this is unrelated to the inheritance hierarchy |
|
191
|
|
|
|
|
|
|
shown above. In this example, the XS file includes another file, and has a |
|
192
|
|
|
|
|
|
|
couple of XSUBs within a C<#if/#else/#endif>. Note that a C |
|
193
|
|
|
|
|
|
|
node is the parent of all the nodes within the same branch of an C<#if>, |
|
194
|
|
|
|
|
|
|
or in the absence of C<#if>, within the same file. |
|
195
|
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
XS_file |
|
197
|
|
|
|
|
|
|
preamble |
|
198
|
|
|
|
|
|
|
C_part |
|
199
|
|
|
|
|
|
|
C_part_POD |
|
200
|
|
|
|
|
|
|
C_part_code |
|
201
|
|
|
|
|
|
|
C_part_postamble |
|
202
|
|
|
|
|
|
|
cpp_scope: type="main" |
|
203
|
|
|
|
|
|
|
MODULE |
|
204
|
|
|
|
|
|
|
PROTOTYPES |
|
205
|
|
|
|
|
|
|
BOOT |
|
206
|
|
|
|
|
|
|
TYPEMAP |
|
207
|
|
|
|
|
|
|
INCLUDE |
|
208
|
|
|
|
|
|
|
cpp_scope: type="include" |
|
209
|
|
|
|
|
|
|
xsub |
|
210
|
|
|
|
|
|
|
... |
|
211
|
|
|
|
|
|
|
global_cpp_line: directive="ifdef" |
|
212
|
|
|
|
|
|
|
cpp_scope: type="if" |
|
213
|
|
|
|
|
|
|
xsub |
|
214
|
|
|
|
|
|
|
... |
|
215
|
|
|
|
|
|
|
global_cpp_line: directive="else" |
|
216
|
|
|
|
|
|
|
cpp_scope: type="if" |
|
217
|
|
|
|
|
|
|
xsub |
|
218
|
|
|
|
|
|
|
... |
|
219
|
|
|
|
|
|
|
global_cpp_line: directive="endif" |
|
220
|
|
|
|
|
|
|
xsub |
|
221
|
|
|
|
|
|
|
... |
|
222
|
|
|
|
|
|
|
pre_boot |
|
223
|
|
|
|
|
|
|
boot_xsub |
|
224
|
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
A typical XSUB might compile to a tree with a structure similar to the |
|
226
|
|
|
|
|
|
|
following. |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
xsub |
|
229
|
|
|
|
|
|
|
xsub_decl |
|
230
|
|
|
|
|
|
|
ReturnType |
|
231
|
|
|
|
|
|
|
Params |
|
232
|
|
|
|
|
|
|
Param |
|
233
|
|
|
|
|
|
|
Param |
|
234
|
|
|
|
|
|
|
... |
|
235
|
|
|
|
|
|
|
CASE # for when a CASE keyword being present implies multiple |
|
236
|
|
|
|
|
|
|
# bodies; otherwise, just a bare xbody node. |
|
237
|
|
|
|
|
|
|
xbody |
|
238
|
|
|
|
|
|
|
# per-body copy of declaration Params, augmented by |
|
239
|
|
|
|
|
|
|
# data from INPUT and OUTPUT sections |
|
240
|
|
|
|
|
|
|
Params |
|
241
|
|
|
|
|
|
|
IO_Param |
|
242
|
|
|
|
|
|
|
IO_Param |
|
243
|
|
|
|
|
|
|
... |
|
244
|
|
|
|
|
|
|
input_part |
|
245
|
|
|
|
|
|
|
INPUT |
|
246
|
|
|
|
|
|
|
INPUT_line |
|
247
|
|
|
|
|
|
|
INPUT_line |
|
248
|
|
|
|
|
|
|
... |
|
249
|
|
|
|
|
|
|
PREINIT |
|
250
|
|
|
|
|
|
|
init_part |
|
251
|
|
|
|
|
|
|
INIT |
|
252
|
|
|
|
|
|
|
code_part |
|
253
|
|
|
|
|
|
|
CODE |
|
254
|
|
|
|
|
|
|
output_part |
|
255
|
|
|
|
|
|
|
OUTPUT |
|
256
|
|
|
|
|
|
|
OUTPUT_line |
|
257
|
|
|
|
|
|
|
OUTPUT_line |
|
258
|
|
|
|
|
|
|
... |
|
259
|
|
|
|
|
|
|
POSTCALL |
|
260
|
|
|
|
|
|
|
cleanup_part |
|
261
|
|
|
|
|
|
|
CLEANUP |
|
262
|
|
|
|
|
|
|
CASE |
|
263
|
|
|
|
|
|
|
xbody |
|
264
|
|
|
|
|
|
|
... |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
=cut |
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
# store these in variables to hide them from brace-matching text editors |
|
269
|
|
|
|
|
|
|
my $open_brace = '{'; |
|
270
|
|
|
|
|
|
|
my $close_brace = '}'; |
|
271
|
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# values for parse_keywords() flags |
|
273
|
|
|
|
|
|
|
# (Can't assume 'constant.pm' is present yet) |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
my $keywords_flag_MODULE = 1; |
|
276
|
|
|
|
|
|
|
my $keywords_flag_NOT_IMPLEMENTED_YET = 2; |
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
# Utility sub to handle all the boilerplate of declaring a Node subclass, |
|
279
|
|
|
|
|
|
|
# including setting up @INC and @FIELDS. Intended to be called from within |
|
280
|
|
|
|
|
|
|
# BEGIN. (Created as a lexical sub ref to make it easily accessible to |
|
281
|
|
|
|
|
|
|
# all subclasses in this file.) |
|
282
|
|
|
|
|
|
|
# |
|
283
|
|
|
|
|
|
|
# The first two args can optionally be ('-parent', 'Foo'), in which case |
|
284
|
|
|
|
|
|
|
# the parent of this subclass will be ExtUtils::ParseXS::Node::Foo. |
|
285
|
|
|
|
|
|
|
# If not specified, the parent will be ExtUtils::ParseXS::Node. |
|
286
|
|
|
|
|
|
|
# |
|
287
|
|
|
|
|
|
|
# Any remaining args are the names of fields. It also inherits the fields |
|
288
|
|
|
|
|
|
|
# of its parent. |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
my $USING_FIELDS; |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
my $build_subclass; |
|
293
|
|
|
|
|
|
|
BEGIN { |
|
294
|
|
|
|
|
|
|
$build_subclass = sub { |
|
295
|
1178
|
|
|
|
|
4429
|
my (@fields) = @_; |
|
296
|
|
|
|
|
|
|
|
|
297
|
1178
|
|
|
|
|
2065
|
my $parent = 'ExtUtils::ParseXS::Node'; |
|
298
|
1178
|
100
|
100
|
|
|
6216
|
if (@fields and $fields[0] eq '-parent') { |
|
299
|
646
|
|
|
|
|
1182
|
shift @fields; |
|
300
|
646
|
|
|
|
|
3808
|
my $p = shift @fields; |
|
301
|
646
|
|
|
|
|
2013
|
$parent .= "::$p"; |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
|
|
304
|
1178
|
|
|
|
|
6565
|
my @bad = grep !/^\w+$/, @fields; |
|
305
|
1178
|
50
|
|
|
|
2385
|
die "Internal error: bad field name(s) in build_subclass: (@bad)\n" |
|
306
|
|
|
|
|
|
|
if @bad; |
|
307
|
|
|
|
|
|
|
|
|
308
|
19
|
|
|
19
|
|
162
|
no strict 'refs'; |
|
|
19
|
|
|
|
|
51
|
|
|
|
19
|
|
|
|
|
2881
|
|
|
309
|
|
|
|
|
|
|
|
|
310
|
1178
|
|
|
|
|
2845
|
my $class = caller(0); |
|
311
|
1178
|
|
|
|
|
1744
|
@fields = (@{"${parent}::FIELDS"}, @fields); |
|
|
1178
|
|
|
|
|
7388
|
|
|
312
|
1178
|
|
|
|
|
1922
|
@{"${class}::ISA"} = $parent; |
|
|
1178
|
|
|
|
|
22528
|
|
|
313
|
1178
|
|
|
|
|
2575
|
@{"${class}::FIELDS"} = @fields; |
|
|
1178
|
|
|
|
|
6909
|
|
|
314
|
|
|
|
|
|
|
|
|
315
|
1178
|
50
|
|
|
|
2851
|
if ($USING_FIELDS) { |
|
316
|
1178
|
50
|
|
|
|
105632
|
eval qq{package $class; fields->import(\@fields); 1;} |
|
317
|
|
|
|
|
|
|
or die $@; |
|
318
|
|
|
|
|
|
|
} |
|
319
|
19
|
|
|
19
|
|
1953
|
}; |
|
320
|
|
|
|
|
|
|
}; |
|
321
|
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# ====================================================================== |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node; |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Base class for all the other node types. |
|
328
|
|
|
|
|
|
|
# |
|
329
|
|
|
|
|
|
|
# The 'use fields' enables compile-time or run-time errors if code |
|
330
|
|
|
|
|
|
|
# attempts to use a key which isn't listed here. |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
BEGIN { |
|
333
|
19
|
|
|
19
|
|
88
|
our @FIELDS = ( |
|
334
|
|
|
|
|
|
|
'line_no', # line number and ... |
|
335
|
|
|
|
|
|
|
'file', # ... filename where this node appeared in src |
|
336
|
|
|
|
|
|
|
'kids', # child nodes, if any |
|
337
|
|
|
|
|
|
|
); |
|
338
|
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
# do 'use fields', except: fields needs Hash::Util which is XS, which |
|
340
|
|
|
|
|
|
|
# needs us. So only 'use fields' on systems where Hash::Util has already |
|
341
|
|
|
|
|
|
|
# been built. |
|
342
|
19
|
50
|
|
|
|
1515
|
if (eval 'require Hash::Util; 1;') { |
|
343
|
19
|
|
|
|
|
9034
|
require fields; |
|
344
|
19
|
|
|
|
|
31505
|
$USING_FIELDS = 1; |
|
345
|
19
|
|
|
|
|
91
|
fields->import(@FIELDS); |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
} |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
# new(): takes one optional arg, $args, which is a hash ref of key/value |
|
351
|
|
|
|
|
|
|
# pairs to initialise the object with. |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
sub new { |
|
354
|
9795
|
|
|
9795
|
0
|
23966
|
my ($class, $args) = @_; |
|
355
|
9795
|
100
|
|
|
|
30784
|
$args = {} unless defined $args; |
|
356
|
|
|
|
|
|
|
|
|
357
|
9795
|
|
|
|
|
16125
|
my __PACKAGE__ $self = shift; |
|
358
|
|
|
|
|
|
|
|
|
359
|
9795
|
50
|
|
|
|
21735
|
if ($USING_FIELDS) { |
|
360
|
9795
|
|
|
|
|
29820
|
$self = fields::new($class); |
|
361
|
9795
|
|
|
|
|
1378050
|
%$self = %$args; |
|
362
|
|
|
|
|
|
|
} |
|
363
|
|
|
|
|
|
|
else { |
|
364
|
0
|
|
|
|
|
0
|
$self = bless { %$args } => $class; |
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
} |
|
367
|
9795
|
|
|
|
|
31491
|
return $self; |
|
368
|
|
|
|
|
|
|
} |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# A very generic parse method that just notes the current file/line no. |
|
372
|
|
|
|
|
|
|
# Typically called first as a SUPER by the parse() method of real nodes. |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub parse { |
|
375
|
7205
|
|
|
7205
|
0
|
11602
|
my __PACKAGE__ $self = shift; |
|
376
|
7205
|
|
|
|
|
10724
|
my ExtUtils::ParseXS $pxs = shift; |
|
377
|
|
|
|
|
|
|
|
|
378
|
7205
|
|
|
|
|
20129
|
$self->{file} = $pxs->{in_pathname}; |
|
379
|
|
|
|
|
|
|
# account for the line array getting shifted |
|
380
|
|
|
|
|
|
|
# as input lines are consumed, while line_no |
|
381
|
|
|
|
|
|
|
# array isn't ever shifted |
|
382
|
|
|
|
|
|
|
$self->{line_no} = $pxs->{line_no}->[ |
|
383
|
7205
|
|
|
|
|
19090
|
@{$pxs->{line_no}} - @{$pxs->{line}} |
|
|
7205
|
|
|
|
|
13486
|
|
|
|
7205
|
|
|
|
|
19823
|
|
|
384
|
|
|
|
|
|
|
]; |
|
385
|
7205
|
|
|
|
|
13469
|
1; |
|
386
|
|
|
|
|
|
|
} |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
# Repeatedly look for keywords matching the pattern. For each found |
|
390
|
|
|
|
|
|
|
# keyword, parse the text following them, and add any resultant nodes |
|
391
|
|
|
|
|
|
|
# as kids to the current node. Returns a list of the successfully parsed |
|
392
|
|
|
|
|
|
|
# and added kids. |
|
393
|
|
|
|
|
|
|
# If $max is defined, it specifies the maximum number of keywords to |
|
394
|
|
|
|
|
|
|
# process. This value is typically passed as undef (unlimited) or 1 |
|
395
|
|
|
|
|
|
|
# (just grab the next keyword). |
|
396
|
|
|
|
|
|
|
# $flags can contain $keywords_flag_MODULE or |
|
397
|
|
|
|
|
|
|
# keywords_flag_NOT_IMPLEMENTED_YET to indicate to match one of those |
|
398
|
|
|
|
|
|
|
# keywords too (whose syntax is slightly different from 'KEY:' and |
|
399
|
|
|
|
|
|
|
# so need special handling |
|
400
|
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub parse_keywords { |
|
402
|
3804
|
|
|
3804
|
0
|
6853
|
my __PACKAGE__ $self = shift; |
|
403
|
3804
|
|
|
|
|
5674
|
my ExtUtils::ParseXS $pxs = shift; |
|
404
|
3804
|
|
|
|
|
5562
|
my $xsub = shift; |
|
405
|
3804
|
|
|
|
|
6225
|
my $xbody = shift; |
|
406
|
3804
|
|
|
|
|
5887
|
my $max = shift; # max number of keywords to process |
|
407
|
3804
|
|
|
|
|
7863
|
my $pat = shift; |
|
408
|
3804
|
|
|
|
|
6312
|
my $flags = shift; |
|
409
|
|
|
|
|
|
|
|
|
410
|
3804
|
100
|
|
|
|
9961
|
$flags = 0 unless defined $flags; |
|
411
|
|
|
|
|
|
|
|
|
412
|
3804
|
|
|
|
|
5840
|
my $n = 0; |
|
413
|
3804
|
|
|
|
|
5768
|
my @kids; |
|
414
|
3804
|
|
|
|
|
6230
|
while (@{$pxs->{line}}) { |
|
|
4735
|
|
|
|
|
13647
|
|
|
415
|
2070
|
|
|
|
|
3349
|
my $line = shift @{$pxs->{line}}; |
|
|
2070
|
|
|
|
|
4782
|
|
|
416
|
2070
|
100
|
|
|
|
9599
|
next unless $line =~ /\S/; |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# extract/delete recognised keyword and any following text |
|
419
|
2069
|
|
|
|
|
3386
|
my $keyword; |
|
420
|
|
|
|
|
|
|
|
|
421
|
2069
|
100
|
100
|
|
|
103613
|
if ( ($flags & $keywords_flag_MODULE) |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
422
|
|
|
|
|
|
|
&& ExtUtils::ParseXS::Utilities::looks_like_MODULE_line($line) |
|
423
|
|
|
|
|
|
|
) |
|
424
|
|
|
|
|
|
|
{ |
|
425
|
323
|
|
|
|
|
935
|
$keyword = 'MODULE'; |
|
426
|
|
|
|
|
|
|
} |
|
427
|
|
|
|
|
|
|
elsif ( $line =~ s/^(\s*)($pat)\s*:\s*(?:#.*)?/$1/s |
|
428
|
|
|
|
|
|
|
or ( ($flags & $keywords_flag_NOT_IMPLEMENTED_YET) |
|
429
|
|
|
|
|
|
|
&& $line =~ s/^(\s*)(NOT_IMPLEMENTED_YET)/$1/ |
|
430
|
|
|
|
|
|
|
) |
|
431
|
|
|
|
|
|
|
) |
|
432
|
|
|
|
|
|
|
{ |
|
433
|
790
|
|
|
|
|
4755
|
$keyword = $2 |
|
434
|
|
|
|
|
|
|
} |
|
435
|
|
|
|
|
|
|
else { |
|
436
|
|
|
|
|
|
|
# stop at unrecognised line |
|
437
|
956
|
|
|
|
|
2425
|
unshift @{$pxs->{line}}, $line; |
|
|
956
|
|
|
|
|
3043
|
|
|
438
|
956
|
|
|
|
|
2492
|
last; |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
|
|
441
|
1113
|
|
|
|
|
2945
|
unshift @{$pxs->{line}}, $line; |
|
|
1113
|
|
|
|
|
3938
|
|
|
442
|
|
|
|
|
|
|
# create a node for the keyword and parse any lines associated |
|
443
|
|
|
|
|
|
|
# with it. |
|
444
|
1113
|
|
|
|
|
3018
|
my $class = "ExtUtils::ParseXS::Node::$keyword"; |
|
445
|
1113
|
|
|
|
|
16617
|
my $node = $class->new(); |
|
446
|
1113
|
50
|
|
|
|
11948
|
if ($node->parse($pxs, $xsub, $xbody)) { |
|
447
|
1090
|
|
|
|
|
1734
|
push @{$self->{kids}}, $node; |
|
|
1090
|
|
|
|
|
3880
|
|
|
448
|
1090
|
|
|
|
|
2384
|
push @kids, $node; |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
1090
|
|
|
|
|
2052
|
$n++; |
|
452
|
1090
|
100
|
66
|
|
|
5580
|
last if defined $max and $max >= $n; |
|
453
|
|
|
|
|
|
|
} |
|
454
|
|
|
|
|
|
|
|
|
455
|
3781
|
|
|
|
|
12156
|
return @kids; |
|
456
|
|
|
|
|
|
|
} |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
1167
|
0
|
|
sub as_code { } |
|
459
|
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
# Most node types inherit this: just continue walking the tree |
|
461
|
|
|
|
|
|
|
# looking for any nodes which provide some boot code. |
|
462
|
|
|
|
|
|
|
# It returns two array refs; one for lines of code to be injected early |
|
463
|
|
|
|
|
|
|
# into the boot XSUB, the second for later code. |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub as_boot_code { |
|
466
|
2490
|
|
|
2490
|
0
|
3820
|
my __PACKAGE__ $self = shift; |
|
467
|
2490
|
|
|
|
|
3524
|
my ExtUtils::ParseXS $pxs = shift; |
|
468
|
|
|
|
|
|
|
|
|
469
|
2490
|
|
|
|
|
5120
|
my ($early, $later) = ([], []); |
|
470
|
2490
|
|
|
|
|
5574
|
my $kids = $self->{kids}; |
|
471
|
2490
|
100
|
|
|
|
5320
|
if ($kids) { |
|
472
|
876
|
|
|
|
|
1965
|
for (@$kids) { |
|
473
|
2843
|
|
|
|
|
11053
|
my ($e, $l) = $_->as_boot_code($pxs); |
|
474
|
2843
|
|
|
|
|
5825
|
push @$early, @$e; |
|
475
|
2843
|
|
|
|
|
5723
|
push @$later, @$l; |
|
476
|
|
|
|
|
|
|
} |
|
477
|
|
|
|
|
|
|
} |
|
478
|
2490
|
|
|
|
|
5511
|
return $early, $later; |
|
479
|
|
|
|
|
|
|
} |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
# as_concise(): for debugging: |
|
483
|
|
|
|
|
|
|
# |
|
484
|
|
|
|
|
|
|
# Return a string representing a concise line-per-node representation |
|
485
|
|
|
|
|
|
|
# of the node and any children, in the spirit of 'perl -MO=Concise'. |
|
486
|
|
|
|
|
|
|
# Intended to be human- rather than machine-readable. |
|
487
|
|
|
|
|
|
|
# |
|
488
|
|
|
|
|
|
|
# The single optional parameter, depth, is for indentation purposes |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
sub as_concise { |
|
491
|
0
|
|
|
0
|
0
|
0
|
my __PACKAGE__ $self = shift; |
|
492
|
0
|
|
|
|
|
0
|
my $depth = shift; |
|
493
|
0
|
0
|
|
|
|
0
|
$depth = 0 unless defined $depth; |
|
494
|
|
|
|
|
|
|
|
|
495
|
0
|
|
|
|
|
0
|
my $f = $self->{file}; |
|
496
|
0
|
0
|
|
|
|
0
|
$f = '??' unless defined $f; |
|
497
|
0
|
|
|
|
|
0
|
$f =~ s{^.*/}{}; |
|
498
|
0
|
0
|
|
|
|
0
|
substr($f,0,10) = '' if length($f) > 10; |
|
499
|
|
|
|
|
|
|
|
|
500
|
0
|
|
|
|
|
0
|
my $l = $self->{line_no}; |
|
501
|
0
|
0
|
|
|
|
0
|
$l = defined $l ? sprintf("%-3d", $l) : '?? '; |
|
502
|
|
|
|
|
|
|
|
|
503
|
0
|
|
|
|
|
0
|
my $s = sprintf "%-15s", "$f:$l"; |
|
504
|
0
|
|
|
|
|
0
|
$s .= (' ' x $depth); |
|
505
|
|
|
|
|
|
|
|
|
506
|
0
|
|
|
|
|
0
|
my $class = ref $self; |
|
507
|
0
|
|
|
|
|
0
|
$class =~ s/^.*:://g; |
|
508
|
0
|
|
|
|
|
0
|
$s .= "${class}: "; |
|
509
|
|
|
|
|
|
|
|
|
510
|
0
|
|
|
|
|
0
|
my @kv; |
|
511
|
|
|
|
|
|
|
|
|
512
|
0
|
|
|
|
|
0
|
for my $key (sort grep !/^(file|line_no|kids)$/, keys %$self) { |
|
513
|
0
|
|
|
|
|
0
|
my $v = $self->{$key}; |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
# some basic pretty-printing |
|
516
|
|
|
|
|
|
|
|
|
517
|
0
|
0
|
|
|
|
0
|
if (!defined $v) { |
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
518
|
0
|
|
|
|
|
0
|
$v = '-'; |
|
519
|
|
|
|
|
|
|
} |
|
520
|
|
|
|
|
|
|
elsif (ref $v) { |
|
521
|
0
|
|
|
|
|
0
|
$v = "[ref]"; |
|
522
|
|
|
|
|
|
|
} |
|
523
|
|
|
|
|
|
|
elsif ($v =~ /^-?\d+(\.\d+)?$/) { |
|
524
|
|
|
|
|
|
|
# leave as-is |
|
525
|
|
|
|
|
|
|
} |
|
526
|
|
|
|
|
|
|
else { |
|
527
|
0
|
|
|
|
|
0
|
$v = "$v"; |
|
528
|
0
|
|
|
|
|
0
|
$v =~ s/"/\\"/g; |
|
529
|
0
|
|
|
|
|
0
|
my $max = 20; |
|
530
|
0
|
0
|
|
|
|
0
|
substr($v, $max) = '...' if length($v) > $max; |
|
531
|
0
|
|
|
|
|
0
|
$v = qq("$v"); |
|
532
|
|
|
|
|
|
|
} |
|
533
|
|
|
|
|
|
|
|
|
534
|
0
|
|
|
|
|
0
|
push @kv, "$key=$v"; |
|
535
|
|
|
|
|
|
|
} |
|
536
|
|
|
|
|
|
|
|
|
537
|
0
|
|
|
|
|
0
|
$s .= join '; ', @kv; |
|
538
|
0
|
|
|
|
|
0
|
$s .= "\n"; |
|
539
|
|
|
|
|
|
|
|
|
540
|
0
|
0
|
|
|
|
0
|
if ($self->{kids}) { |
|
541
|
0
|
|
|
|
|
0
|
$s .= $_->as_concise($depth+1) for @{$self->{kids}}; |
|
|
0
|
|
|
|
|
0
|
|
|
542
|
|
|
|
|
|
|
} |
|
543
|
|
|
|
|
|
|
|
|
544
|
0
|
|
|
|
|
0
|
$s; |
|
545
|
|
|
|
|
|
|
} |
|
546
|
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
# Simple method wrapper for ExtUtils::ParseXS::Q |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
sub Q { |
|
551
|
2918
|
|
|
2918
|
0
|
4803
|
my __PACKAGE__ $self = shift; |
|
552
|
2918
|
|
|
|
|
6236
|
my $text = shift; |
|
553
|
2918
|
|
|
|
|
8592
|
return ExtUtils::ParseXS::Q($text); |
|
554
|
|
|
|
|
|
|
} |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# ====================================================================== |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::XS_file; |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
# Top-level AST node representing an entire XS file |
|
562
|
|
|
|
|
|
|
|
|
563
|
19
|
|
|
19
|
|
28821
|
BEGIN { $build_subclass->( |
|
564
|
|
|
|
|
|
|
'preamble', # Node::preamble object which emits preamble C code |
|
565
|
|
|
|
|
|
|
'C_part', # the C part of the XS file, before the first MODULE |
|
566
|
|
|
|
|
|
|
'C_part_postamble',# Node::C_part_postamble object which emits |
|
567
|
|
|
|
|
|
|
# boilerplate code following the C code |
|
568
|
|
|
|
|
|
|
'cpp_scope', # node holding all the XS part of the main file |
|
569
|
|
|
|
|
|
|
'pre_boot', # node holding code after user XSUBs but before boot XSUB |
|
570
|
|
|
|
|
|
|
'boot_xsub', # node holding code which generates the boot XSUB |
|
571
|
|
|
|
|
|
|
)}; |
|
572
|
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
sub parse { |
|
574
|
316
|
|
|
316
|
|
1376
|
my __PACKAGE__ $self = shift; |
|
575
|
316
|
|
|
|
|
810
|
my ExtUtils::ParseXS $pxs = shift; |
|
576
|
|
|
|
|
|
|
|
|
577
|
316
|
|
|
|
|
918
|
$self->{line_no} = 1; |
|
578
|
316
|
|
|
|
|
1414
|
$self->{file} = $pxs->{in_pathname}; |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
# Hash of package name => package C name |
|
581
|
316
|
|
|
|
|
1087
|
$pxs->{map_overloaded_package_to_C_package} = {}; |
|
582
|
|
|
|
|
|
|
|
|
583
|
|
|
|
|
|
|
# Hashref of package name => fallback setting |
|
584
|
316
|
|
|
|
|
1522
|
$pxs->{map_package_to_fallback_string} = {}; |
|
585
|
|
|
|
|
|
|
|
|
586
|
316
|
|
|
|
|
997
|
$pxs->{error_count} = 0; |
|
587
|
|
|
|
|
|
|
|
|
588
|
|
|
|
|
|
|
# Initialise the sequence of guard defines used by cpp_scope |
|
589
|
316
|
|
|
|
|
1668
|
$pxs->{cpp_next_tmp_define} = 'XSubPPtmpAAAA'; |
|
590
|
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
# "Parse" the start of the file. Doesn't actually consume any lines: |
|
592
|
|
|
|
|
|
|
# just a placeholder for emitting preamble later |
|
593
|
|
|
|
|
|
|
|
|
594
|
316
|
|
|
|
|
3344
|
my $preamble = ExtUtils::ParseXS::Node::preamble->new(); |
|
595
|
316
|
|
|
|
|
1064
|
$self->{preamble} = $preamble; |
|
596
|
316
|
50
|
|
|
|
3384
|
$preamble->parse($pxs, $self) |
|
597
|
|
|
|
|
|
|
or return; |
|
598
|
316
|
|
|
|
|
695
|
push @{$self->{kids}}, $preamble; |
|
|
316
|
|
|
|
|
1483
|
|
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
# Process the first (C language) half of the XS file, up until the first |
|
602
|
|
|
|
|
|
|
# MODULE: line |
|
603
|
|
|
|
|
|
|
|
|
604
|
316
|
|
|
|
|
3036
|
my $C_part = ExtUtils::ParseXS::Node::C_part->new(); |
|
605
|
316
|
|
|
|
|
1120
|
$self->{C_part} = $C_part; |
|
606
|
316
|
50
|
|
|
|
2922
|
$C_part->parse($pxs, $self) |
|
607
|
|
|
|
|
|
|
or return; |
|
608
|
316
|
|
|
|
|
544
|
push @{$self->{kids}}, $C_part; |
|
|
316
|
|
|
|
|
1054
|
|
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
# "Parse" the bit following any C code. Doesn't actually consume any |
|
611
|
|
|
|
|
|
|
# lines: just a placeholder for emitting postamble code. |
|
612
|
|
|
|
|
|
|
|
|
613
|
316
|
|
|
|
|
4317
|
my $C_part_postamble = ExtUtils::ParseXS::Node::C_part_postamble->new(); |
|
614
|
316
|
|
|
|
|
1041
|
$self->{C_part_postamble} = $C_part_postamble; |
|
615
|
316
|
50
|
|
|
|
2709
|
$C_part_postamble->parse($pxs, $self) |
|
616
|
|
|
|
|
|
|
or return; |
|
617
|
316
|
|
|
|
|
626
|
push @{$self->{kids}}, $C_part_postamble; |
|
|
316
|
|
|
|
|
917
|
|
|
618
|
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
# Parse the XS half of the file |
|
620
|
|
|
|
|
|
|
|
|
621
|
316
|
|
|
|
|
5270
|
my $cpp_scope = ExtUtils::ParseXS::Node::cpp_scope->new({type => 'main'}); |
|
622
|
316
|
|
|
|
|
1200
|
$self->{cpp_scope} = $cpp_scope; |
|
623
|
316
|
50
|
|
|
|
3570
|
$cpp_scope->parse($pxs) |
|
624
|
|
|
|
|
|
|
or return; |
|
625
|
285
|
|
|
|
|
1944
|
push @{$self->{kids}}, $cpp_scope; |
|
|
285
|
|
|
|
|
1681
|
|
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
# Now at EOF: all paragraphs (and thus XSUBs) have now been read in |
|
628
|
|
|
|
|
|
|
# and processed. Do any final post-processing. |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
# "Parse" the bit following any C code. Doesn't actually consume any |
|
631
|
|
|
|
|
|
|
# lines: just a placeholder for emitting any code which should follow |
|
632
|
|
|
|
|
|
|
# user XSUBs but which comes before the boot XSUB |
|
633
|
|
|
|
|
|
|
|
|
634
|
285
|
|
|
|
|
2767
|
my $pre_boot = ExtUtils::ParseXS::Node::pre_boot->new(); |
|
635
|
285
|
|
|
|
|
877
|
$self->{pre_boot} = $pre_boot; |
|
636
|
285
|
|
|
|
|
585
|
push @{$self->{kids}}, $pre_boot; |
|
|
285
|
|
|
|
|
905
|
|
|
637
|
285
|
50
|
|
|
|
1336
|
$pre_boot->parse($pxs) |
|
638
|
|
|
|
|
|
|
or return; |
|
639
|
|
|
|
|
|
|
|
|
640
|
|
|
|
|
|
|
# Emit the boot XSUB initialization routine |
|
641
|
|
|
|
|
|
|
|
|
642
|
285
|
|
|
|
|
2452
|
my $boot_xsub = ExtUtils::ParseXS::Node::boot_xsub->new(); |
|
643
|
285
|
|
|
|
|
1018
|
$self->{boot_xsub} = $boot_xsub; |
|
644
|
285
|
|
|
|
|
592
|
push @{$self->{kids}}, $boot_xsub; |
|
|
285
|
|
|
|
|
1126
|
|
|
645
|
285
|
50
|
|
|
|
2734
|
$boot_xsub->parse($pxs) |
|
646
|
|
|
|
|
|
|
or return; |
|
647
|
|
|
|
|
|
|
|
|
648
|
|
|
|
|
|
|
warn( "Please specify prototyping behavior for " |
|
649
|
|
|
|
|
|
|
. "$pxs->{in_filename} (see perlxs manual)\n") |
|
650
|
285
|
50
|
|
|
|
1059
|
unless $pxs->{proto_behaviour_specified}; |
|
651
|
|
|
|
|
|
|
|
|
652
|
285
|
|
|
|
|
1343
|
1; |
|
653
|
|
|
|
|
|
|
} |
|
654
|
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
sub as_code { |
|
657
|
285
|
|
|
285
|
|
666
|
my __PACKAGE__ $self = shift; |
|
658
|
285
|
|
|
|
|
542
|
my ExtUtils::ParseXS $pxs = shift; |
|
659
|
|
|
|
|
|
|
|
|
660
|
285
|
|
|
|
|
508
|
$_->as_code($pxs, $self) for @{$self->{kids}}; |
|
|
285
|
|
|
|
|
7638
|
|
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
} |
|
663
|
|
|
|
|
|
|
# ====================================================================== |
|
664
|
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::preamble; |
|
666
|
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
# AST node representing the boilerplate C code preamble at the start of |
|
668
|
|
|
|
|
|
|
# the file. Parsing doesn't actually consume any lines; it exists just for |
|
669
|
|
|
|
|
|
|
# its as_code() method which emits the preamble into the C file. |
|
670
|
|
|
|
|
|
|
|
|
671
|
19
|
|
|
19
|
|
146
|
BEGIN { $build_subclass->( |
|
672
|
|
|
|
|
|
|
)}; |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
sub parse { |
|
675
|
316
|
|
|
316
|
|
891
|
my __PACKAGE__ $self = shift; |
|
676
|
316
|
|
|
|
|
613
|
my ExtUtils::ParseXS $pxs = shift; |
|
677
|
|
|
|
|
|
|
|
|
678
|
316
|
|
|
|
|
941
|
$self->{line_no} = 1; |
|
679
|
316
|
|
|
|
|
1010
|
$self->{file} = $pxs->{in_pathname}; |
|
680
|
316
|
|
|
|
|
1170
|
1; |
|
681
|
|
|
|
|
|
|
} |
|
682
|
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
sub as_code { |
|
684
|
285
|
|
|
285
|
|
729
|
my __PACKAGE__ $self = shift; |
|
685
|
285
|
|
|
|
|
1694
|
my ExtUtils::ParseXS $pxs = shift; |
|
686
|
|
|
|
|
|
|
|
|
687
|
|
|
|
|
|
|
# Emit preamble at start of C file, including the |
|
688
|
|
|
|
|
|
|
# version it was generated by. |
|
689
|
|
|
|
|
|
|
|
|
690
|
285
|
|
|
|
|
3513
|
print $self->Q(<<"EOM"); |
|
691
|
|
|
|
|
|
|
|/* |
|
692
|
|
|
|
|
|
|
| * This file was generated automatically by ExtUtils::ParseXS version $ExtUtils::ParseXS::VERSION from the |
|
693
|
|
|
|
|
|
|
| * contents of $pxs->{in_filename}. Do not edit this file, edit $pxs->{in_filename} instead. |
|
694
|
|
|
|
|
|
|
| * |
|
695
|
|
|
|
|
|
|
| * ANY CHANGES MADE HERE WILL BE LOST! |
|
696
|
|
|
|
|
|
|
| * |
|
697
|
|
|
|
|
|
|
| */ |
|
698
|
|
|
|
|
|
|
| |
|
699
|
|
|
|
|
|
|
EOM |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
print("#line 1 \"" . |
|
702
|
|
|
|
|
|
|
ExtUtils::ParseXS::Utilities::escape_file_for_line_directive( |
|
703
|
|
|
|
|
|
|
$self->{file}) . "\"\n") |
|
704
|
285
|
100
|
|
|
|
4157
|
if $pxs->{config_WantLineNumbers}; |
|
705
|
|
|
|
|
|
|
} |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
|
|
708
|
|
|
|
|
|
|
# ====================================================================== |
|
709
|
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::C_part; |
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
# A node representing the C part of the XS file - i.e. everything |
|
713
|
|
|
|
|
|
|
# before the first MODULE line |
|
714
|
|
|
|
|
|
|
|
|
715
|
19
|
|
|
19
|
|
84
|
BEGIN { $build_subclass->( |
|
716
|
|
|
|
|
|
|
)}; |
|
717
|
|
|
|
|
|
|
|
|
718
|
|
|
|
|
|
|
sub parse { |
|
719
|
316
|
|
|
316
|
|
788
|
my __PACKAGE__ $self = shift; |
|
720
|
316
|
|
|
|
|
675
|
my ExtUtils::ParseXS $pxs = shift; |
|
721
|
|
|
|
|
|
|
|
|
722
|
316
|
|
|
|
|
871
|
$self->{line_no} = 1; |
|
723
|
316
|
|
|
|
|
1062
|
$self->{file} = $pxs->{in_pathname}; |
|
724
|
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
# Read in lines until the first MODULE line, creating a list of |
|
726
|
|
|
|
|
|
|
# Node::C_part_code and Node::C_part_POD nodes as children. |
|
727
|
|
|
|
|
|
|
# Returns with $pxs->{lastline} holding the next line (i.e. the MODULE |
|
728
|
|
|
|
|
|
|
# line) or errors out if not found |
|
729
|
|
|
|
|
|
|
|
|
730
|
316
|
|
|
|
|
3747
|
$pxs->{lastline} = readline($pxs->{in_fh}); |
|
731
|
316
|
|
|
|
|
3404
|
$pxs->{lastline_no} = $.; |
|
732
|
|
|
|
|
|
|
|
|
733
|
316
|
|
|
|
|
1351
|
while (defined $pxs->{lastline}) { |
|
734
|
327
|
100
|
|
|
|
15609
|
if (ExtUtils::ParseXS::Utilities::looks_like_MODULE_line( |
|
735
|
|
|
|
|
|
|
$pxs->{lastline})) |
|
736
|
|
|
|
|
|
|
{ |
|
737
|
|
|
|
|
|
|
# the fetch_para() regime in place in the XS part of the file |
|
738
|
|
|
|
|
|
|
# expects this to have been chomped |
|
739
|
316
|
|
|
|
|
1161
|
chomp $pxs->{lastline}; |
|
740
|
316
|
|
|
|
|
1577
|
return 1; |
|
741
|
|
|
|
|
|
|
} |
|
742
|
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
my $node = |
|
744
|
11
|
100
|
|
|
|
188
|
$pxs->{lastline} =~ /^=/ |
|
745
|
|
|
|
|
|
|
? ExtUtils::ParseXS::Node::C_part_POD->new() |
|
746
|
|
|
|
|
|
|
: ExtUtils::ParseXS::Node::C_part_code->new(); |
|
747
|
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
# Read in next block of code or POD lines |
|
749
|
11
|
50
|
|
|
|
84
|
$node->parse($pxs) |
|
750
|
|
|
|
|
|
|
or return; |
|
751
|
11
|
|
|
|
|
25
|
push @{$self->{kids}}, $node; |
|
|
11
|
|
|
|
|
43
|
|
|
752
|
|
|
|
|
|
|
} |
|
753
|
|
|
|
|
|
|
|
|
754
|
0
|
|
|
|
|
0
|
warn "Didn't find a 'MODULE ... PACKAGE ... PREFIX' line\n"; |
|
755
|
0
|
|
|
|
|
0
|
exit 0; # Not a fatal error for the caller process |
|
756
|
|
|
|
|
|
|
} |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
|
|
759
|
|
|
|
|
|
|
sub as_code { |
|
760
|
285
|
|
|
285
|
|
4475
|
my __PACKAGE__ $self = shift; |
|
761
|
285
|
|
|
|
|
715
|
my ExtUtils::ParseXS $pxs = shift; |
|
762
|
|
|
|
|
|
|
|
|
763
|
285
|
|
|
|
|
621
|
$_->as_code($pxs, $self) for @{$self->{kids}}; |
|
|
285
|
|
|
|
|
1428
|
|
|
764
|
|
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" |
|
766
|
285
|
100
|
|
|
|
4163
|
if $pxs->{config_WantLineNumbers}; |
|
767
|
|
|
|
|
|
|
} |
|
768
|
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
|
|
770
|
|
|
|
|
|
|
# ====================================================================== |
|
771
|
|
|
|
|
|
|
|
|
772
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::C_part_POD; |
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
# A node representing a section of POD within the C part of the XS file |
|
775
|
|
|
|
|
|
|
|
|
776
|
19
|
|
|
19
|
|
98
|
BEGIN { $build_subclass->( |
|
777
|
|
|
|
|
|
|
'pod_lines', # array of lines containing pod, including start and end |
|
778
|
|
|
|
|
|
|
# '=foo' lines |
|
779
|
|
|
|
|
|
|
)}; |
|
780
|
|
|
|
|
|
|
|
|
781
|
|
|
|
|
|
|
sub parse { |
|
782
|
1
|
|
|
1
|
|
3
|
my __PACKAGE__ $self = shift; |
|
783
|
1
|
|
|
|
|
3
|
my ExtUtils::ParseXS $pxs = shift; |
|
784
|
|
|
|
|
|
|
|
|
785
|
1
|
|
|
|
|
3
|
$self->{line_no} = $pxs->{lastline_no}; |
|
786
|
1
|
|
|
|
|
3
|
$self->{file} = $pxs->{in_pathname}; |
|
787
|
|
|
|
|
|
|
|
|
788
|
|
|
|
|
|
|
# This method is called with $pxs->{lastline} holding the first line |
|
789
|
|
|
|
|
|
|
# of POD and returns with $pxs->{lastline} holding the (unprocessed) |
|
790
|
|
|
|
|
|
|
# next line following the =cut line |
|
791
|
|
|
|
|
|
|
|
|
792
|
1
|
|
|
|
|
2
|
my $cut; |
|
793
|
1
|
|
|
|
|
2
|
while (1) { |
|
794
|
5
|
|
|
|
|
11
|
push @{$self->{pod_lines}}, $pxs->{lastline}; |
|
|
5
|
|
|
|
|
13
|
|
|
795
|
5
|
|
|
|
|
41
|
$pxs->{lastline} = readline($pxs->{in_fh}); |
|
796
|
5
|
|
|
|
|
13
|
$pxs->{lastline_no} = $.; |
|
797
|
5
|
100
|
|
|
|
15
|
return 1 if $cut; |
|
798
|
4
|
50
|
|
|
|
10
|
last unless defined $pxs->{lastline}; |
|
799
|
4
|
|
|
|
|
19
|
$cut = $pxs->{lastline} =~ /^=cut\s*$/; |
|
800
|
|
|
|
|
|
|
} |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
# At this point $. is at end of file so die won't state the start |
|
803
|
|
|
|
|
|
|
# of the problem, and as we haven't yet read any lines &death won't |
|
804
|
|
|
|
|
|
|
# show the correct line in the message either. |
|
805
|
0
|
|
|
|
|
0
|
die ( "Error: Unterminated pod in $pxs->{in_filename}, " |
|
806
|
|
|
|
|
|
|
. "line $self->{line_no}\n"); |
|
807
|
|
|
|
|
|
|
} |
|
808
|
|
|
|
|
|
|
|
|
809
|
|
|
|
|
|
|
|
|
810
|
|
|
|
|
|
|
sub as_code { |
|
811
|
1
|
|
|
1
|
|
3
|
my __PACKAGE__ $self = shift; |
|
812
|
1
|
|
|
|
|
2
|
my ExtUtils::ParseXS $pxs = shift; |
|
813
|
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
# Emit something in the C file to indicate that a section of POD has |
|
815
|
|
|
|
|
|
|
# been elided, while maintaining the correct lines numbers using |
|
816
|
|
|
|
|
|
|
# #line. |
|
817
|
|
|
|
|
|
|
# |
|
818
|
|
|
|
|
|
|
# We can't just write out a /* */ comment, as our embedded POD might |
|
819
|
|
|
|
|
|
|
# itself be in a comment. We can't put a /**/ comment inside #if 0, as |
|
820
|
|
|
|
|
|
|
# the C standard says that the source file is decomposed into |
|
821
|
|
|
|
|
|
|
# preprocessing characters in the stage before preprocessing commands |
|
822
|
|
|
|
|
|
|
# are executed. |
|
823
|
|
|
|
|
|
|
# |
|
824
|
|
|
|
|
|
|
# I don't want to leave the text as barewords, because the spec isn't |
|
825
|
|
|
|
|
|
|
# clear whether macros are expanded before or after preprocessing |
|
826
|
|
|
|
|
|
|
# commands are executed, and someone pathological may just have |
|
827
|
|
|
|
|
|
|
# defined one of the 3 words as a macro that does something strange. |
|
828
|
|
|
|
|
|
|
# Multiline strings are illegal in C, so the "" we write must be a |
|
829
|
|
|
|
|
|
|
# string literal. And they aren't concatenated until 2 steps later, so |
|
830
|
|
|
|
|
|
|
# we are safe. |
|
831
|
|
|
|
|
|
|
# - Nicholas Clark |
|
832
|
|
|
|
|
|
|
|
|
833
|
1
|
|
|
|
|
8
|
print $self->Q(<<"EOF"); |
|
834
|
|
|
|
|
|
|
|#if 0 |
|
835
|
|
|
|
|
|
|
| "Skipped embedded POD." |
|
836
|
|
|
|
|
|
|
|#endif |
|
837
|
|
|
|
|
|
|
EOF |
|
838
|
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
printf("#line %d \"%s\"\n", |
|
840
|
1
|
|
|
|
|
4
|
$self->{line_no} + @{$self->{pod_lines}}, |
|
841
|
|
|
|
|
|
|
ExtUtils::ParseXS::Utilities::escape_file_for_line_directive( |
|
842
|
|
|
|
|
|
|
$pxs->{in_pathname})) |
|
843
|
1
|
50
|
|
|
|
5
|
if $pxs->{config_WantLineNumbers}; |
|
844
|
|
|
|
|
|
|
} |
|
845
|
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
|
|
847
|
|
|
|
|
|
|
# ====================================================================== |
|
848
|
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::C_part_code; |
|
850
|
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
# A node representing a section of C code within the C part of the XS file |
|
852
|
|
|
|
|
|
|
|
|
853
|
19
|
|
|
19
|
|
94
|
BEGIN { $build_subclass->( |
|
854
|
|
|
|
|
|
|
'code_lines', # array of lines containing C code |
|
855
|
|
|
|
|
|
|
)}; |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
sub parse { |
|
858
|
10
|
|
|
10
|
|
24
|
my __PACKAGE__ $self = shift; |
|
859
|
10
|
|
|
|
|
44
|
my ExtUtils::ParseXS $pxs = shift; |
|
860
|
|
|
|
|
|
|
|
|
861
|
10
|
|
|
|
|
37
|
$self->{line_no} = $pxs->{lastline_no}; |
|
862
|
10
|
|
|
|
|
21
|
$self->{file} = $pxs->{in_pathname}; |
|
863
|
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
# This method is called with $pxs->{lastline} holding the first line |
|
865
|
|
|
|
|
|
|
# of (possibly) C code and returns with $pxs->{lastline} holding the |
|
866
|
|
|
|
|
|
|
# first (unprocessed) line which isn't C code (i.e. its the start of |
|
867
|
|
|
|
|
|
|
# POD or a MODULE line) |
|
868
|
|
|
|
|
|
|
|
|
869
|
10
|
|
|
|
|
19
|
my $cut; |
|
870
|
10
|
|
|
|
|
18
|
while (1) { |
|
871
|
|
|
|
|
|
|
return 1 if ExtUtils::ParseXS::Utilities::looks_like_MODULE_line( |
|
872
|
201
|
100
|
|
|
|
366
|
$pxs->{lastline}); |
|
873
|
192
|
100
|
|
|
|
1205
|
return 1 if $pxs->{lastline} =~ /^=/; |
|
874
|
191
|
|
|
|
|
236
|
push @{$self->{code_lines}}, $pxs->{lastline}; |
|
|
191
|
|
|
|
|
417
|
|
|
875
|
191
|
|
|
|
|
369
|
$pxs->{lastline} = readline($pxs->{in_fh}); |
|
876
|
191
|
|
|
|
|
312
|
$pxs->{lastline_no} = $.; |
|
877
|
191
|
50
|
|
|
|
403
|
last unless defined $pxs->{lastline}; |
|
878
|
|
|
|
|
|
|
} |
|
879
|
|
|
|
|
|
|
|
|
880
|
0
|
|
|
|
|
0
|
1; |
|
881
|
|
|
|
|
|
|
} |
|
882
|
|
|
|
|
|
|
|
|
883
|
|
|
|
|
|
|
sub as_code { |
|
884
|
9
|
|
|
9
|
|
40
|
my __PACKAGE__ $self = shift; |
|
885
|
9
|
|
|
|
|
17
|
my ExtUtils::ParseXS $pxs = shift; |
|
886
|
|
|
|
|
|
|
|
|
887
|
9
|
|
|
|
|
14
|
print @{$self->{code_lines}}; |
|
|
9
|
|
|
|
|
43
|
|
|
888
|
|
|
|
|
|
|
} |
|
889
|
|
|
|
|
|
|
|
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
# ====================================================================== |
|
893
|
|
|
|
|
|
|
|
|
894
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::C_part_postamble; |
|
895
|
|
|
|
|
|
|
|
|
896
|
|
|
|
|
|
|
# AST node representing the boilerplate C code postamble following any |
|
897
|
|
|
|
|
|
|
# initial C code contained within the C part of the XS file. |
|
898
|
|
|
|
|
|
|
# This node's parse() method doesn't actually consume any lines; the node |
|
899
|
|
|
|
|
|
|
# exists just for its as_code() method to emit the postamble into the C |
|
900
|
|
|
|
|
|
|
# file. |
|
901
|
|
|
|
|
|
|
|
|
902
|
19
|
|
|
19
|
|
116
|
BEGIN { $build_subclass->( |
|
903
|
|
|
|
|
|
|
)}; |
|
904
|
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
sub parse { |
|
906
|
316
|
|
|
316
|
|
1516
|
my __PACKAGE__ $self = shift; |
|
907
|
316
|
|
|
|
|
742
|
my ExtUtils::ParseXS $pxs = shift; |
|
908
|
|
|
|
|
|
|
|
|
909
|
316
|
|
|
|
|
1205
|
$self->{line_no} = $pxs->{lastline_no}; |
|
910
|
316
|
|
|
|
|
888
|
$self->{file} = $pxs->{in_pathname}; |
|
911
|
316
|
|
|
|
|
1333
|
1; |
|
912
|
|
|
|
|
|
|
} |
|
913
|
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
sub as_code { |
|
915
|
285
|
|
|
285
|
|
3084
|
my __PACKAGE__ $self = shift; |
|
916
|
285
|
|
|
|
|
559
|
my ExtUtils::ParseXS $pxs = shift; |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
# Emit boilerplate postamble following any code passed through from |
|
919
|
|
|
|
|
|
|
# the 'C' part of the XS file |
|
920
|
|
|
|
|
|
|
|
|
921
|
285
|
|
|
|
|
1083
|
print $self->Q(<<'EOF'); |
|
922
|
|
|
|
|
|
|
|#ifndef PERL_UNUSED_VAR |
|
923
|
|
|
|
|
|
|
|# define PERL_UNUSED_VAR(var) if (0) var = var |
|
924
|
|
|
|
|
|
|
|#endif |
|
925
|
|
|
|
|
|
|
| |
|
926
|
|
|
|
|
|
|
|#ifndef dVAR |
|
927
|
|
|
|
|
|
|
|# define dVAR dNOOP |
|
928
|
|
|
|
|
|
|
|#endif |
|
929
|
|
|
|
|
|
|
| |
|
930
|
|
|
|
|
|
|
| |
|
931
|
|
|
|
|
|
|
|/* This stuff is not part of the API! You have been warned. */ |
|
932
|
|
|
|
|
|
|
|#ifndef PERL_VERSION_DECIMAL |
|
933
|
|
|
|
|
|
|
|# define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s) |
|
934
|
|
|
|
|
|
|
|#endif |
|
935
|
|
|
|
|
|
|
|#ifndef PERL_DECIMAL_VERSION |
|
936
|
|
|
|
|
|
|
|# define PERL_DECIMAL_VERSION \ |
|
937
|
|
|
|
|
|
|
| PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION) |
|
938
|
|
|
|
|
|
|
|#endif |
|
939
|
|
|
|
|
|
|
|#ifndef PERL_VERSION_GE |
|
940
|
|
|
|
|
|
|
|# define PERL_VERSION_GE(r,v,s) \ |
|
941
|
|
|
|
|
|
|
| (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s)) |
|
942
|
|
|
|
|
|
|
|#endif |
|
943
|
|
|
|
|
|
|
|#ifndef PERL_VERSION_LE |
|
944
|
|
|
|
|
|
|
|# define PERL_VERSION_LE(r,v,s) \ |
|
945
|
|
|
|
|
|
|
| (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s)) |
|
946
|
|
|
|
|
|
|
|#endif |
|
947
|
|
|
|
|
|
|
| |
|
948
|
|
|
|
|
|
|
|/* XS_INTERNAL is the explicit static-linkage variant of the default |
|
949
|
|
|
|
|
|
|
| * XS macro. |
|
950
|
|
|
|
|
|
|
| * |
|
951
|
|
|
|
|
|
|
| * XS_EXTERNAL is the same as XS_INTERNAL except it does not include |
|
952
|
|
|
|
|
|
|
| * "STATIC", ie. it exports XSUB symbols. You probably don't want that |
|
953
|
|
|
|
|
|
|
| * for anything but the BOOT XSUB. |
|
954
|
|
|
|
|
|
|
| * |
|
955
|
|
|
|
|
|
|
| * See XSUB.h in core! |
|
956
|
|
|
|
|
|
|
| */ |
|
957
|
|
|
|
|
|
|
| |
|
958
|
|
|
|
|
|
|
| |
|
959
|
|
|
|
|
|
|
|/* TODO: This might be compatible further back than 5.10.0. */ |
|
960
|
|
|
|
|
|
|
|#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1) |
|
961
|
|
|
|
|
|
|
|# undef XS_EXTERNAL |
|
962
|
|
|
|
|
|
|
|# undef XS_INTERNAL |
|
963
|
|
|
|
|
|
|
|# if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING) |
|
964
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name) |
|
965
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) STATIC XSPROTO(name) |
|
966
|
|
|
|
|
|
|
|# endif |
|
967
|
|
|
|
|
|
|
|# if defined(__SYMBIAN32__) |
|
968
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) EXPORT_C XSPROTO(name) |
|
969
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name) |
|
970
|
|
|
|
|
|
|
|# endif |
|
971
|
|
|
|
|
|
|
|# ifndef XS_EXTERNAL |
|
972
|
|
|
|
|
|
|
|# if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus) |
|
973
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__) |
|
974
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__) |
|
975
|
|
|
|
|
|
|
|# else |
|
976
|
|
|
|
|
|
|
|# ifdef __cplusplus |
|
977
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) extern "C" XSPROTO(name) |
|
978
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) static XSPROTO(name) |
|
979
|
|
|
|
|
|
|
|# else |
|
980
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) XSPROTO(name) |
|
981
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) STATIC XSPROTO(name) |
|
982
|
|
|
|
|
|
|
|# endif |
|
983
|
|
|
|
|
|
|
|# endif |
|
984
|
|
|
|
|
|
|
|# endif |
|
985
|
|
|
|
|
|
|
|#endif |
|
986
|
|
|
|
|
|
|
| |
|
987
|
|
|
|
|
|
|
|/* perl >= 5.10.0 && perl <= 5.15.1 */ |
|
988
|
|
|
|
|
|
|
| |
|
989
|
|
|
|
|
|
|
| |
|
990
|
|
|
|
|
|
|
|/* The XS_EXTERNAL macro is used for functions that must not be static |
|
991
|
|
|
|
|
|
|
| * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL |
|
992
|
|
|
|
|
|
|
| * macro defined, the best we can do is assume XS is the same. |
|
993
|
|
|
|
|
|
|
| * Dito for XS_INTERNAL. |
|
994
|
|
|
|
|
|
|
| */ |
|
995
|
|
|
|
|
|
|
|#ifndef XS_EXTERNAL |
|
996
|
|
|
|
|
|
|
|# define XS_EXTERNAL(name) XS(name) |
|
997
|
|
|
|
|
|
|
|#endif |
|
998
|
|
|
|
|
|
|
|#ifndef XS_INTERNAL |
|
999
|
|
|
|
|
|
|
|# define XS_INTERNAL(name) XS(name) |
|
1000
|
|
|
|
|
|
|
|#endif |
|
1001
|
|
|
|
|
|
|
| |
|
1002
|
|
|
|
|
|
|
|/* Now, finally, after all this mess, we want an ExtUtils::ParseXS |
|
1003
|
|
|
|
|
|
|
| * internal macro that we're free to redefine for varying linkage due |
|
1004
|
|
|
|
|
|
|
| * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use |
|
1005
|
|
|
|
|
|
|
| * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to! |
|
1006
|
|
|
|
|
|
|
| */ |
|
1007
|
|
|
|
|
|
|
| |
|
1008
|
|
|
|
|
|
|
|#undef XS_EUPXS |
|
1009
|
|
|
|
|
|
|
|#if defined(PERL_EUPXS_ALWAYS_EXPORT) |
|
1010
|
|
|
|
|
|
|
|# define XS_EUPXS(name) XS_EXTERNAL(name) |
|
1011
|
|
|
|
|
|
|
|#else |
|
1012
|
|
|
|
|
|
|
| /* default to internal */ |
|
1013
|
|
|
|
|
|
|
|# define XS_EUPXS(name) XS_INTERNAL(name) |
|
1014
|
|
|
|
|
|
|
|#endif |
|
1015
|
|
|
|
|
|
|
| |
|
1016
|
|
|
|
|
|
|
|#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE |
|
1017
|
|
|
|
|
|
|
|#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params) |
|
1018
|
|
|
|
|
|
|
| |
|
1019
|
|
|
|
|
|
|
|/* prototype to pass -Wmissing-prototypes */ |
|
1020
|
|
|
|
|
|
|
|STATIC void |
|
1021
|
|
|
|
|
|
|
|S_croak_xs_usage(const CV *const cv, const char *const params); |
|
1022
|
|
|
|
|
|
|
| |
|
1023
|
|
|
|
|
|
|
|STATIC void |
|
1024
|
|
|
|
|
|
|
|S_croak_xs_usage(const CV *const cv, const char *const params) |
|
1025
|
|
|
|
|
|
|
|{ |
|
1026
|
|
|
|
|
|
|
| const GV *const gv = CvGV(cv); |
|
1027
|
|
|
|
|
|
|
| |
|
1028
|
|
|
|
|
|
|
| PERL_ARGS_ASSERT_CROAK_XS_USAGE; |
|
1029
|
|
|
|
|
|
|
| |
|
1030
|
|
|
|
|
|
|
| if (gv) { |
|
1031
|
|
|
|
|
|
|
| const char *const gvname = GvNAME(gv); |
|
1032
|
|
|
|
|
|
|
| const HV *const stash = GvSTASH(gv); |
|
1033
|
|
|
|
|
|
|
| const char *const hvname = stash ? HvNAME(stash) : NULL; |
|
1034
|
|
|
|
|
|
|
| |
|
1035
|
|
|
|
|
|
|
| if (hvname) |
|
1036
|
|
|
|
|
|
|
| Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params); |
|
1037
|
|
|
|
|
|
|
| else |
|
1038
|
|
|
|
|
|
|
| Perl_croak_nocontext("Usage: %s(%s)", gvname, params); |
|
1039
|
|
|
|
|
|
|
| } else { |
|
1040
|
|
|
|
|
|
|
| /* Pants. I don't think that it should be possible to get here. */ |
|
1041
|
|
|
|
|
|
|
| Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params); |
|
1042
|
|
|
|
|
|
|
| } |
|
1043
|
|
|
|
|
|
|
|} |
|
1044
|
|
|
|
|
|
|
|#undef PERL_ARGS_ASSERT_CROAK_XS_USAGE |
|
1045
|
|
|
|
|
|
|
| |
|
1046
|
|
|
|
|
|
|
|#define croak_xs_usage S_croak_xs_usage |
|
1047
|
|
|
|
|
|
|
| |
|
1048
|
|
|
|
|
|
|
|#endif |
|
1049
|
|
|
|
|
|
|
| |
|
1050
|
|
|
|
|
|
|
|/* NOTE: the prototype of newXSproto() is different in versions of perls, |
|
1051
|
|
|
|
|
|
|
| * so we define a portable version of newXSproto() |
|
1052
|
|
|
|
|
|
|
| */ |
|
1053
|
|
|
|
|
|
|
|#ifdef newXS_flags |
|
1054
|
|
|
|
|
|
|
|#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0) |
|
1055
|
|
|
|
|
|
|
|#else |
|
1056
|
|
|
|
|
|
|
|#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv) |
|
1057
|
|
|
|
|
|
|
|#endif /* !defined(newXS_flags) */ |
|
1058
|
|
|
|
|
|
|
| |
|
1059
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 21, 5) |
|
1060
|
|
|
|
|
|
|
|# define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file) |
|
1061
|
|
|
|
|
|
|
|#else |
|
1062
|
|
|
|
|
|
|
|# define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b) |
|
1063
|
|
|
|
|
|
|
|#endif |
|
1064
|
|
|
|
|
|
|
| |
|
1065
|
|
|
|
|
|
|
|/* simple backcompat versions of the TARGx() macros with no optimisation */ |
|
1066
|
|
|
|
|
|
|
|#ifndef TARGi |
|
1067
|
|
|
|
|
|
|
|# define TARGi(iv, do_taint) sv_setiv_mg(TARG, iv) |
|
1068
|
|
|
|
|
|
|
|# define TARGu(uv, do_taint) sv_setuv_mg(TARG, uv) |
|
1069
|
|
|
|
|
|
|
|# define TARGn(nv, do_taint) sv_setnv_mg(TARG, nv) |
|
1070
|
|
|
|
|
|
|
|#endif |
|
1071
|
|
|
|
|
|
|
| |
|
1072
|
|
|
|
|
|
|
EOF |
|
1073
|
|
|
|
|
|
|
|
|
1074
|
|
|
|
|
|
|
# Fix up line number reckoning |
|
1075
|
|
|
|
|
|
|
|
|
1076
|
|
|
|
|
|
|
print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" |
|
1077
|
285
|
100
|
|
|
|
3914
|
if $pxs->{config_WantLineNumbers}; |
|
1078
|
|
|
|
|
|
|
} |
|
1079
|
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
# ====================================================================== |
|
1082
|
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::cpp_scope; |
|
1084
|
|
|
|
|
|
|
|
|
1085
|
|
|
|
|
|
|
# Node representing a part of an XS file which is all in the same C |
|
1086
|
|
|
|
|
|
|
# preprocessor scope as regards C preprocessor (CPP) conditionals, i.e. |
|
1087
|
|
|
|
|
|
|
# #if/#elsif/#else/#endif etc. |
|
1088
|
|
|
|
|
|
|
# |
|
1089
|
|
|
|
|
|
|
# Note that this only considers file-scoped C preprocessor directives; |
|
1090
|
|
|
|
|
|
|
# ones within a code block such as CODE or BOOT don't contribute to the |
|
1091
|
|
|
|
|
|
|
# state maintained here. |
|
1092
|
|
|
|
|
|
|
# |
|
1093
|
|
|
|
|
|
|
# Initially the whole XS part of the main XS file is considered a single |
|
1094
|
|
|
|
|
|
|
# scope, so the single main cpp_scope node would have, as children, all |
|
1095
|
|
|
|
|
|
|
# the file-scoped nodes such as Node::PROTOTYPES and any Node::xsub's. |
|
1096
|
|
|
|
|
|
|
# |
|
1097
|
|
|
|
|
|
|
# After an INCLUDE, the new XS file is considered as being in a separate |
|
1098
|
|
|
|
|
|
|
# scope, and gets its own child cpp_scope node. |
|
1099
|
|
|
|
|
|
|
# |
|
1100
|
|
|
|
|
|
|
# Once an XS file starts having file-scope CPP conditionals, then each |
|
1101
|
|
|
|
|
|
|
# branch of the conditional is considered a separate scope and gets its |
|
1102
|
|
|
|
|
|
|
# own cpp_scope node. Nested conditionals cause nested cpp_scope objects |
|
1103
|
|
|
|
|
|
|
# in the AST. |
|
1104
|
|
|
|
|
|
|
# |
|
1105
|
|
|
|
|
|
|
# The main reason for this node type is to separate out the AST into |
|
1106
|
|
|
|
|
|
|
# separate sections which can each have the same named XSUB without a |
|
1107
|
|
|
|
|
|
|
# 'duplicate XSUB' warning, and where newXS()-type calls can be added to |
|
1108
|
|
|
|
|
|
|
# to the boot code for *both* XSUBs, guarded by suitable #ifdef's. |
|
1109
|
|
|
|
|
|
|
# |
|
1110
|
|
|
|
|
|
|
# This node is the main high-level node where file-scoped parsing takes |
|
1111
|
|
|
|
|
|
|
# place: its parse() method contains a fetch_para() loop which does all |
|
1112
|
|
|
|
|
|
|
# the looking for file-scoped keywords, CPP directives, and XSUB |
|
1113
|
|
|
|
|
|
|
# declarations. It implements a recursive-decent parser by creating child |
|
1114
|
|
|
|
|
|
|
# cpp_scope nodes and recursing into that child's parse() method (which |
|
1115
|
|
|
|
|
|
|
# does its own fetch_para() calls). |
|
1116
|
|
|
|
|
|
|
|
|
1117
|
19
|
|
|
19
|
|
90
|
BEGIN { $build_subclass->( |
|
1118
|
|
|
|
|
|
|
'type', # Str: what sort of scope: 'main', 'include' or 'if' |
|
1119
|
|
|
|
|
|
|
'is_cmd', # Bool: for include type, it's INCLUDE_COMMAND |
|
1120
|
|
|
|
|
|
|
'guard_name', # Str: the name of the XSubPPtmpAAAA guard define |
|
1121
|
|
|
|
|
|
|
'seen_xsubs', # Hash: the names of any XSUBs seen in this scope |
|
1122
|
|
|
|
|
|
|
)}; |
|
1123
|
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
sub parse { |
|
1125
|
342
|
|
|
342
|
|
1145
|
my __PACKAGE__ $self = shift; |
|
1126
|
342
|
|
|
|
|
835
|
my ExtUtils::ParseXS $pxs = shift; |
|
1127
|
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
# Main loop: for each iteration, parse the next 'thing' in the current |
|
1129
|
|
|
|
|
|
|
# paragraph, such as a C preprocessor directive, a contiguous block of |
|
1130
|
|
|
|
|
|
|
# file-scoped keywords, or an XSUB. When the current paragraph runs |
|
1131
|
|
|
|
|
|
|
# out, read in another one. XSUBs, TYPEMAP and BOOT will consume |
|
1132
|
|
|
|
|
|
|
# all lines until the end of the current paragraph. |
|
1133
|
|
|
|
|
|
|
# |
|
1134
|
|
|
|
|
|
|
# C preprocessor conditionals such as #if may trigger recursive |
|
1135
|
|
|
|
|
|
|
# calls to process each branch until the matching #endif. These may |
|
1136
|
|
|
|
|
|
|
# cross paragraph boundaries. |
|
1137
|
|
|
|
|
|
|
|
|
1138
|
342
|
|
100
|
|
|
6349
|
while ( ($pxs->{line} && @{$pxs->{line}}) || $pxs->fetch_para()) |
|
|
1264
|
|
100
|
|
|
8625
|
|
|
1139
|
|
|
|
|
|
|
{ |
|
1140
|
1287
|
100
|
|
|
|
2262
|
next unless @{$pxs->{line}}; # fetch_para() can return zero lines |
|
|
1287
|
|
|
|
|
3563
|
|
|
1141
|
|
|
|
|
|
|
|
|
1142
|
1209
|
100
|
66
|
|
|
7299
|
if ( !defined($self->{line_no}) |
|
1143
|
|
|
|
|
|
|
&& defined $pxs->{line_no}[0] |
|
1144
|
|
|
|
|
|
|
) { |
|
1145
|
|
|
|
|
|
|
# set file/line_no after line number info is available: |
|
1146
|
|
|
|
|
|
|
# typically after the first call to fetch_para() |
|
1147
|
342
|
|
|
|
|
1905
|
$self->SUPER::parse($pxs); |
|
1148
|
|
|
|
|
|
|
} |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
# skip blank line |
|
1151
|
1209
|
50
|
|
|
|
7227
|
shift @{$pxs->{line}}, next if $pxs->{line}[0] !~ /\S/; |
|
|
0
|
|
|
|
|
0
|
|
|
1152
|
|
|
|
|
|
|
|
|
1153
|
|
|
|
|
|
|
# Process a C-preprocessor line. Note that any non-CPP lines |
|
1154
|
|
|
|
|
|
|
# starting with '#' will already have been filtered out by |
|
1155
|
|
|
|
|
|
|
# fetch_para(). |
|
1156
|
|
|
|
|
|
|
# |
|
1157
|
|
|
|
|
|
|
# If its a #if or similar, then recursively process each branch |
|
1158
|
|
|
|
|
|
|
# as a separate cpp_scope object until the matching #endif is |
|
1159
|
|
|
|
|
|
|
# reached. |
|
1160
|
|
|
|
|
|
|
|
|
1161
|
1209
|
100
|
|
|
|
4933
|
if ($pxs->{line}[0] =~ /^#/) { |
|
1162
|
48
|
|
|
|
|
387
|
my $node = ExtUtils::ParseXS::Node::global_cpp_line->new(); |
|
1163
|
48
|
50
|
|
|
|
340
|
$node->parse($pxs) |
|
1164
|
|
|
|
|
|
|
or next; |
|
1165
|
48
|
|
|
|
|
151
|
push @{$self->{kids}}, $node; |
|
|
48
|
|
|
|
|
158
|
|
|
1166
|
|
|
|
|
|
|
|
|
1167
|
48
|
100
|
|
|
|
198
|
next unless $node->{is_cond}; |
|
1168
|
|
|
|
|
|
|
|
|
1169
|
|
|
|
|
|
|
# Parse branches of a CPP conditionals within a nested scope |
|
1170
|
|
|
|
|
|
|
|
|
1171
|
43
|
100
|
|
|
|
171
|
if (not $node->{is_if}) { |
|
1172
|
|
|
|
|
|
|
$pxs->death("Error: '". $node->{directive} |
|
1173
|
|
|
|
|
|
|
. "' with no matching 'if'") |
|
1174
|
24
|
100
|
|
|
|
116
|
if $self->{type} ne 'if'; |
|
1175
|
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
# we should already be within a nested scope; this |
|
1177
|
|
|
|
|
|
|
# CPP condition keyword just ends that scope. Our |
|
1178
|
|
|
|
|
|
|
# (recursive) caller will handle processing any further |
|
1179
|
|
|
|
|
|
|
# branches if it's an elif/else rather than endif |
|
1180
|
|
|
|
|
|
|
|
|
1181
|
23
|
|
|
|
|
105
|
return 1 |
|
1182
|
|
|
|
|
|
|
} |
|
1183
|
|
|
|
|
|
|
|
|
1184
|
|
|
|
|
|
|
# So it's an 'if'/'ifdef' etc node. Start a new |
|
1185
|
|
|
|
|
|
|
# Node::cpp_scope sub-parse to handle that branch and then any |
|
1186
|
|
|
|
|
|
|
# other branches of the same conditional. |
|
1187
|
|
|
|
|
|
|
|
|
1188
|
19
|
|
|
|
|
95
|
while (1) { |
|
1189
|
|
|
|
|
|
|
# For each iteration, parse the next branch in a new scope |
|
1190
|
24
|
|
|
|
|
250
|
my $scope = ExtUtils::ParseXS::Node::cpp_scope->new( |
|
1191
|
|
|
|
|
|
|
{type => 'if'}); |
|
1192
|
24
|
50
|
|
|
|
294
|
$scope->parse($pxs) |
|
1193
|
|
|
|
|
|
|
or next; |
|
1194
|
|
|
|
|
|
|
|
|
1195
|
|
|
|
|
|
|
# Sub-parsing of that branch should have terminated |
|
1196
|
|
|
|
|
|
|
# at an elif/endif line rather than falling off the |
|
1197
|
|
|
|
|
|
|
# end of the file |
|
1198
|
24
|
|
|
|
|
74
|
my $last = $scope->{kids}[-1]; |
|
1199
|
24
|
50
|
66
|
|
|
543
|
unless ( |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
defined $last |
|
1201
|
|
|
|
|
|
|
&& $last->isa( |
|
1202
|
|
|
|
|
|
|
'ExtUtils::ParseXS::Node::global_cpp_line') |
|
1203
|
|
|
|
|
|
|
&& $last->{is_cond} |
|
1204
|
|
|
|
|
|
|
&& !$last->{is_if} |
|
1205
|
|
|
|
|
|
|
) { |
|
1206
|
1
|
|
|
|
|
46
|
$pxs->death("Error: Unterminated '#if/#ifdef/#ifndef'") |
|
1207
|
|
|
|
|
|
|
} |
|
1208
|
|
|
|
|
|
|
|
|
1209
|
|
|
|
|
|
|
# Move the CPP line which terminated the branch from |
|
1210
|
|
|
|
|
|
|
# the end of the inner scope to the current scope |
|
1211
|
23
|
|
|
|
|
74
|
pop @{$scope->{kids}}; |
|
|
23
|
|
|
|
|
128
|
|
|
1212
|
23
|
|
|
|
|
113
|
push @{$self->{kids}}, $scope, $last; |
|
|
23
|
|
|
|
|
104
|
|
|
1213
|
|
|
|
|
|
|
|
|
1214
|
23
|
100
|
|
|
|
112
|
if (grep { ref($_) !~ /::global_cpp_line$/ } |
|
|
34
|
|
|
|
|
252
|
|
|
1215
|
23
|
|
|
|
|
128
|
@{$scope->{kids}} ) |
|
1216
|
|
|
|
|
|
|
{ |
|
1217
|
|
|
|
|
|
|
# the inner scope has some content, so needs |
|
1218
|
|
|
|
|
|
|
# a '#define XSubPPtmpAAAA 1'-style guard |
|
1219
|
21
|
|
|
|
|
109
|
$scope->{guard_name} = $pxs->{cpp_next_tmp_define}++; |
|
1220
|
|
|
|
|
|
|
} |
|
1221
|
|
|
|
|
|
|
|
|
1222
|
|
|
|
|
|
|
# any more branches to process of current if? |
|
1223
|
23
|
100
|
|
|
|
120
|
last if $last->{is_endif}; |
|
1224
|
|
|
|
|
|
|
} # while 1 |
|
1225
|
|
|
|
|
|
|
|
|
1226
|
18
|
|
|
|
|
73
|
next; |
|
1227
|
|
|
|
|
|
|
} |
|
1228
|
|
|
|
|
|
|
|
|
1229
|
|
|
|
|
|
|
# die if the next line is indented: all file-scoped things (CPP, |
|
1230
|
|
|
|
|
|
|
# keywords, XSUB starts) are supposed to start on column 1 |
|
1231
|
|
|
|
|
|
|
# (although see the comment below about multiple parse_keywords() |
|
1232
|
|
|
|
|
|
|
# iterations sneaking in indented keywords). |
|
1233
|
|
|
|
|
|
|
# |
|
1234
|
|
|
|
|
|
|
# The text of the error message is based around a common reason |
|
1235
|
|
|
|
|
|
|
# for an indented line to appear in file scope: this is due to an |
|
1236
|
|
|
|
|
|
|
# XSUB being prematurely truncated by fetch_para(). For example in |
|
1237
|
|
|
|
|
|
|
# the code below, the coder wants the foo and bar lines to both be |
|
1238
|
|
|
|
|
|
|
# part of the same CODE block. But the XS parser sees the blank |
|
1239
|
|
|
|
|
|
|
# line followed by the '#ifdef' on column 1 as terminating the |
|
1240
|
|
|
|
|
|
|
# current XSUB. So the bar() line is treated as being in file |
|
1241
|
|
|
|
|
|
|
# scope and dies because it is indented. |
|
1242
|
|
|
|
|
|
|
# |
|
1243
|
|
|
|
|
|
|
# |int f() |
|
1244
|
|
|
|
|
|
|
# | CODE: |
|
1245
|
|
|
|
|
|
|
# | foo(); |
|
1246
|
|
|
|
|
|
|
# | |
|
1247
|
|
|
|
|
|
|
# |#ifdef USE_BAR |
|
1248
|
|
|
|
|
|
|
# | bar(); |
|
1249
|
|
|
|
|
|
|
# |#endif |
|
1250
|
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
$pxs->death( |
|
1252
|
|
|
|
|
|
|
"Code is not inside a function" |
|
1253
|
|
|
|
|
|
|
." (maybe last function was ended by a blank line " |
|
1254
|
|
|
|
|
|
|
." followed by a statement on column one?)") |
|
1255
|
1161
|
100
|
|
|
|
5485
|
if $pxs->{line}->[0] =~ /^\s/; |
|
1256
|
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
# The SCOPE keyword can appear both in file scope (just before an |
|
1258
|
|
|
|
|
|
|
# XSUB) and as an XSUB keyword. This field maintains the state of the |
|
1259
|
|
|
|
|
|
|
# former: reset it at the start of processing any file-scoped |
|
1260
|
|
|
|
|
|
|
# keywords just before the XSUB (i.e. without any blank lines, e.g. |
|
1261
|
|
|
|
|
|
|
# SCOPE: ENABLE |
|
1262
|
|
|
|
|
|
|
# int |
|
1263
|
|
|
|
|
|
|
# foo(...) |
|
1264
|
|
|
|
|
|
|
# These semantics may not be particularly sensible, but they maintain |
|
1265
|
|
|
|
|
|
|
# backwards compatibility for now. |
|
1266
|
|
|
|
|
|
|
|
|
1267
|
1159
|
|
|
|
|
2657
|
$pxs->{file_SCOPE_enabled} = 0; |
|
1268
|
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
# Process file-scoped keywords |
|
1270
|
|
|
|
|
|
|
# |
|
1271
|
|
|
|
|
|
|
# This loop repeatedly: skips any blank lines and then calls |
|
1272
|
|
|
|
|
|
|
# the relevant Node::FOO::parse() method if it finds any of the |
|
1273
|
|
|
|
|
|
|
# file-scoped keywords in the passed pattern. |
|
1274
|
|
|
|
|
|
|
# |
|
1275
|
|
|
|
|
|
|
# Note: due to the looping within parse_keywords() rather than |
|
1276
|
|
|
|
|
|
|
# looping here, only the first keyword in a contiguous block |
|
1277
|
|
|
|
|
|
|
# gets the 'start at column 1' check above enforced. |
|
1278
|
|
|
|
|
|
|
# This is a bug, maintained for backwards compatibility: see the |
|
1279
|
|
|
|
|
|
|
# comments below referring to SCOPE for other bits of code needed |
|
1280
|
|
|
|
|
|
|
# to enforce this compatibility. |
|
1281
|
|
|
|
|
|
|
|
|
1282
|
1159
|
|
|
|
|
7604
|
$self->parse_keywords( |
|
1283
|
|
|
|
|
|
|
$pxs, |
|
1284
|
|
|
|
|
|
|
undef, undef, # xsub and xbody: not needed for non XSUB keywords |
|
1285
|
|
|
|
|
|
|
undef, # implies process as many keywords as possible |
|
1286
|
|
|
|
|
|
|
"BOOT|REQUIRE|PROTOTYPES|EXPORT_XSUB_SYMBOLS|FALLBACK" |
|
1287
|
|
|
|
|
|
|
. "|VERSIONCHECK|INCLUDE|INCLUDE_COMMAND|SCOPE|TYPEMAP", |
|
1288
|
|
|
|
|
|
|
$keywords_flag_MODULE, |
|
1289
|
|
|
|
|
|
|
); |
|
1290
|
|
|
|
|
|
|
# XXX we could have an 'or next' here if not for SCOPE backcompat |
|
1291
|
|
|
|
|
|
|
# and also delete the following 'skip blank line' and 'next unless |
|
1292
|
|
|
|
|
|
|
# @line' lines |
|
1293
|
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
# skip blank lines |
|
1295
|
1142
|
|
66
|
|
|
2028
|
shift @{$pxs->{line}} while @{$pxs->{line}} && $pxs->{line}[0] !~ /\S/; |
|
|
1142
|
|
|
|
|
8756
|
|
|
|
0
|
|
|
|
|
0
|
|
|
1296
|
|
|
|
|
|
|
|
|
1297
|
1142
|
100
|
|
|
|
1829
|
next unless @{$pxs->{line}}; |
|
|
1142
|
|
|
|
|
5975
|
|
|
1298
|
|
|
|
|
|
|
|
|
1299
|
|
|
|
|
|
|
# Parse an XSUB |
|
1300
|
|
|
|
|
|
|
|
|
1301
|
366
|
|
|
|
|
3722
|
my $xsub = ExtUtils::ParseXS::Node::xsub->new(); |
|
1302
|
366
|
100
|
|
|
|
4703
|
$xsub->parse($pxs) |
|
1303
|
|
|
|
|
|
|
or next; |
|
1304
|
355
|
|
|
|
|
857
|
push @{$self->{kids}}, $xsub; |
|
|
355
|
|
|
|
|
1307
|
|
|
1305
|
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
# Check for a duplicate function definition in this scope |
|
1307
|
|
|
|
|
|
|
{ |
|
1308
|
355
|
|
|
|
|
625
|
my $name = $xsub->{decl}{full_C_name}; |
|
|
355
|
|
|
|
|
986
|
|
|
1309
|
355
|
100
|
|
|
|
1411
|
if ($self->{seen_xsubs}{$name}) { |
|
1310
|
4
|
|
|
|
|
133
|
(my $short = $name) =~ s/^$pxs->{PACKAGE_C_name}_//; |
|
1311
|
4
|
|
|
|
|
87
|
$pxs->Warn( "Warning: duplicate function definition " |
|
1312
|
|
|
|
|
|
|
. "'$short' detected"); |
|
1313
|
|
|
|
|
|
|
} |
|
1314
|
355
|
|
|
|
|
1710
|
$self->{seen_xsubs}{$name} = 1; |
|
1315
|
|
|
|
|
|
|
} |
|
1316
|
|
|
|
|
|
|
|
|
1317
|
|
|
|
|
|
|
# xsub->parse() should have consumed all the remaining |
|
1318
|
|
|
|
|
|
|
# lines in the current paragraph. |
|
1319
|
|
|
|
|
|
|
die "Internal error: unexpectedly not at EOF\n" |
|
1320
|
355
|
50
|
|
|
|
887
|
if @{$pxs->{line}}; |
|
|
355
|
|
|
|
|
1096
|
|
|
1321
|
|
|
|
|
|
|
|
|
1322
|
355
|
|
|
|
|
1755
|
$pxs->{seen_an_XSUB} = 1; # encountered at least one XSUB |
|
1323
|
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
} # END main 'while' loop |
|
1325
|
|
|
|
|
|
|
|
|
1326
|
288
|
|
|
|
|
1306
|
1; |
|
1327
|
|
|
|
|
|
|
} |
|
1328
|
|
|
|
|
|
|
|
|
1329
|
|
|
|
|
|
|
|
|
1330
|
|
|
|
|
|
|
sub as_code { |
|
1331
|
310
|
|
|
310
|
|
4426
|
my __PACKAGE__ $self = shift; |
|
1332
|
310
|
|
|
|
|
647
|
my ExtUtils::ParseXS $pxs = shift; |
|
1333
|
|
|
|
|
|
|
|
|
1334
|
310
|
|
|
|
|
1477
|
my $g = $self->{guard_name}; |
|
1335
|
310
|
100
|
|
|
|
1051
|
print "#define $g 1\n\n" if defined $g; |
|
1336
|
310
|
|
|
|
|
724
|
$_->as_code($pxs, $self) for @{$self->{kids}}; |
|
|
310
|
|
|
|
|
2235
|
|
|
1337
|
|
|
|
|
|
|
} |
|
1338
|
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
|
|
1340
|
|
|
|
|
|
|
sub as_boot_code { |
|
1341
|
308
|
|
|
308
|
|
629
|
my __PACKAGE__ $self = shift; |
|
1342
|
308
|
|
|
|
|
594
|
my ExtUtils::ParseXS $pxs = shift; |
|
1343
|
|
|
|
|
|
|
|
|
1344
|
|
|
|
|
|
|
# accumulate all the newXS()'s in $early and the BOOT blocks in $later, |
|
1345
|
308
|
|
|
|
|
1157
|
my ($early, $later) = $self->SUPER::as_boot_code($pxs); |
|
1346
|
|
|
|
|
|
|
|
|
1347
|
|
|
|
|
|
|
# then wrap them all within '#if XSubPPtmpAAAA' guards |
|
1348
|
308
|
|
|
|
|
838
|
my $g = $self->{guard_name}; |
|
1349
|
308
|
100
|
|
|
|
1181
|
if (defined $g) { |
|
1350
|
21
|
|
|
|
|
108
|
unshift @$early, "#if $g\n"; |
|
1351
|
21
|
|
|
|
|
90
|
unshift @$later, "#if $g\n"; |
|
1352
|
21
|
|
|
|
|
64
|
push @$early, "#endif\n"; |
|
1353
|
21
|
|
|
|
|
56
|
push @$later, "#endif\n"; |
|
1354
|
|
|
|
|
|
|
} |
|
1355
|
|
|
|
|
|
|
|
|
1356
|
308
|
|
|
|
|
776
|
return $early, $later; |
|
1357
|
|
|
|
|
|
|
} |
|
1358
|
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
|
|
1360
|
|
|
|
|
|
|
# ====================================================================== |
|
1361
|
|
|
|
|
|
|
|
|
1362
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::global_cpp_line; |
|
1363
|
|
|
|
|
|
|
|
|
1364
|
|
|
|
|
|
|
# AST node representing a single C-preprocessor line in file (global) |
|
1365
|
|
|
|
|
|
|
# scope. (A "single" line can actually include embedded "\\\n"'s from line |
|
1366
|
|
|
|
|
|
|
# continuations). |
|
1367
|
|
|
|
|
|
|
|
|
1368
|
19
|
|
|
19
|
|
114
|
BEGIN { $build_subclass->( |
|
1369
|
|
|
|
|
|
|
'cpp_line', # Str: the full text of the "# foo" CPP line |
|
1370
|
|
|
|
|
|
|
'directive', # Str: one of 'define', 'endif' etc |
|
1371
|
|
|
|
|
|
|
'rest', # Str: the rest of the line following the directive |
|
1372
|
|
|
|
|
|
|
'is_cond', # Bool: it's an ifdef/else/endif etc |
|
1373
|
|
|
|
|
|
|
'is_if', # Bool: it's an if/ifdef/ifndef |
|
1374
|
|
|
|
|
|
|
'is_endif' # Bool: it's an endif |
|
1375
|
|
|
|
|
|
|
)}; |
|
1376
|
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
sub parse { |
|
1378
|
48
|
|
|
48
|
|
126
|
my __PACKAGE__ $self = shift; |
|
1379
|
48
|
|
|
|
|
98
|
my ExtUtils::ParseXS $pxs = shift; |
|
1380
|
|
|
|
|
|
|
|
|
1381
|
48
|
|
|
|
|
218
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1382
|
|
|
|
|
|
|
|
|
1383
|
48
|
|
|
|
|
88
|
my $line = shift @{$pxs->{line}}; |
|
|
48
|
|
|
|
|
150
|
|
|
1384
|
|
|
|
|
|
|
|
|
1385
|
48
|
50
|
|
|
|
538
|
my ($directive, $rest) = $line =~ /^ \# \s* (\w+) (?:\s+ (.*) \s* $)?/sx |
|
1386
|
|
|
|
|
|
|
or $pxs->death("Internal error: can't parse CPP line: $line\n"); |
|
1387
|
48
|
100
|
|
|
|
217
|
$rest = '' unless defined $rest; |
|
1388
|
48
|
|
|
|
|
371
|
my $is_cond = $directive =~ /^(if|ifdef|ifndef|elif|else|endif)$/; |
|
1389
|
48
|
|
|
|
|
245
|
my $is_if = $directive =~ /^(if|ifdef|ifndef)$/; |
|
1390
|
48
|
|
|
|
|
285
|
my $is_endif = $directive =~ /^endif$/; |
|
1391
|
48
|
|
|
|
|
325
|
@$self{qw(cpp_line directive rest is_cond is_if is_endif)} |
|
1392
|
|
|
|
|
|
|
= ($line, $directive, $rest, $is_cond, $is_if, $is_endif); |
|
1393
|
|
|
|
|
|
|
|
|
1394
|
48
|
|
|
|
|
286
|
1; |
|
1395
|
|
|
|
|
|
|
} |
|
1396
|
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
sub as_code { |
|
1399
|
45
|
|
|
45
|
|
409
|
my __PACKAGE__ $self = shift; |
|
1400
|
45
|
|
|
|
|
134
|
my ExtUtils::ParseXS $pxs = shift; |
|
1401
|
|
|
|
|
|
|
|
|
1402
|
45
|
|
|
|
|
251
|
print $self->{cpp_line}, "\n"; |
|
1403
|
|
|
|
|
|
|
} |
|
1404
|
|
|
|
|
|
|
|
|
1405
|
|
|
|
|
|
|
|
|
1406
|
|
|
|
|
|
|
# ====================================================================== |
|
1407
|
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::BOOT; |
|
1409
|
|
|
|
|
|
|
|
|
1410
|
|
|
|
|
|
|
# Store the code lines associated with the BOOT keyword |
|
1411
|
|
|
|
|
|
|
# |
|
1412
|
|
|
|
|
|
|
# Note that unlike other codeblock-like Node classes, BOOT consumes |
|
1413
|
|
|
|
|
|
|
# *all* lines remaining in the current paragraph, rather than stopping |
|
1414
|
|
|
|
|
|
|
# at the next keyword, if any. |
|
1415
|
|
|
|
|
|
|
# It's also file-scoped rather than XSUB-scoped. |
|
1416
|
|
|
|
|
|
|
|
|
1417
|
19
|
|
|
19
|
|
2059
|
BEGIN { $build_subclass->( |
|
1418
|
|
|
|
|
|
|
'lines', # Array ref of all code lines making up the BOOT |
|
1419
|
|
|
|
|
|
|
)}; |
|
1420
|
|
|
|
|
|
|
|
|
1421
|
|
|
|
|
|
|
|
|
1422
|
|
|
|
|
|
|
# Consume all the remaining lines and store in @$lines. |
|
1423
|
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
sub parse { |
|
1425
|
1
|
|
|
1
|
|
3
|
my __PACKAGE__ $self = shift; |
|
1426
|
1
|
|
|
|
|
3
|
my ExtUtils::ParseXS $pxs = shift; |
|
1427
|
|
|
|
|
|
|
|
|
1428
|
1
|
|
|
|
|
9
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1429
|
|
|
|
|
|
|
|
|
1430
|
|
|
|
|
|
|
# Check all the @{$pxs->{line}} lines for balance: all the |
|
1431
|
|
|
|
|
|
|
# #if, #else, #endif etc within the BOOT should balance out. |
|
1432
|
1
|
|
|
|
|
6
|
ExtUtils::ParseXS::Utilities::check_conditional_preprocessor_statements(); |
|
1433
|
|
|
|
|
|
|
|
|
1434
|
|
|
|
|
|
|
# Suck in all remaining lines |
|
1435
|
|
|
|
|
|
|
|
|
1436
|
1
|
|
|
|
|
2
|
$self->{lines} = [ @{$pxs->{line}} ]; |
|
|
1
|
|
|
|
|
4
|
|
|
1437
|
1
|
|
|
|
|
3
|
@{$pxs->{line}} = (); |
|
|
1
|
|
|
|
|
4
|
|
|
1438
|
|
|
|
|
|
|
|
|
1439
|
|
|
|
|
|
|
# Ignore any text following the keyword on the same line. |
|
1440
|
|
|
|
|
|
|
# XXX this quietly ignores any such text - really it should |
|
1441
|
|
|
|
|
|
|
# warn, but not yet for backwards compatibility. |
|
1442
|
1
|
|
|
|
|
2
|
shift @{$self->{lines}}; |
|
|
1
|
|
|
|
|
9
|
|
|
1443
|
|
|
|
|
|
|
|
|
1444
|
1
|
|
|
|
|
4
|
1; |
|
1445
|
|
|
|
|
|
|
} |
|
1446
|
|
|
|
|
|
|
|
|
1447
|
|
|
|
|
|
|
|
|
1448
|
|
|
|
|
|
|
sub as_boot_code { |
|
1449
|
1
|
|
|
1
|
|
4
|
my __PACKAGE__ $self = shift; |
|
1450
|
1
|
|
|
|
|
3
|
my ExtUtils::ParseXS $pxs = shift; |
|
1451
|
|
|
|
|
|
|
|
|
1452
|
1
|
|
|
|
|
3
|
my @lines; |
|
1453
|
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
# Prepend a '#line' directive if not already present |
|
1455
|
1
|
50
|
33
|
|
|
7
|
if ( $pxs->{config_WantLineNumbers} |
|
|
|
|
33
|
|
|
|
|
|
1456
|
1
|
|
|
|
|
18
|
&& @{$self->{lines}} |
|
1457
|
|
|
|
|
|
|
&& $self->{lines}[0] !~ /^\s*#\s*line\b/ |
|
1458
|
|
|
|
|
|
|
) |
|
1459
|
|
|
|
|
|
|
{ |
|
1460
|
|
|
|
|
|
|
push @lines, |
|
1461
|
|
|
|
|
|
|
sprintf "#line %d \"%s\"\n", |
|
1462
|
|
|
|
|
|
|
$self->{line_no} + 1, |
|
1463
|
|
|
|
|
|
|
ExtUtils::ParseXS::Utilities::escape_file_for_line_directive( |
|
1464
|
1
|
|
|
|
|
9
|
$self->{file}); |
|
1465
|
|
|
|
|
|
|
} |
|
1466
|
|
|
|
|
|
|
|
|
1467
|
|
|
|
|
|
|
# Save all the BOOT lines (plus trailing empty line) to be emitted |
|
1468
|
|
|
|
|
|
|
# later. |
|
1469
|
1
|
|
|
|
|
4
|
push @lines, "$_\n" for @{$self->{lines}}, ""; |
|
|
1
|
|
|
|
|
6
|
|
|
1470
|
|
|
|
|
|
|
|
|
1471
|
1
|
|
|
|
|
5
|
return [], \@lines; |
|
1472
|
|
|
|
|
|
|
} |
|
1473
|
|
|
|
|
|
|
|
|
1474
|
|
|
|
|
|
|
# ====================================================================== |
|
1475
|
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::TYPEMAP; |
|
1477
|
|
|
|
|
|
|
|
|
1478
|
|
|
|
|
|
|
# Process the lines associated with the TYPEMAP keyword |
|
1479
|
|
|
|
|
|
|
# |
|
1480
|
|
|
|
|
|
|
# fetch_para() will have already processed the <
|
|
1481
|
|
|
|
|
|
|
# and read all the lines up to, but not including, the EOF line. |
|
1482
|
|
|
|
|
|
|
|
|
1483
|
19
|
|
|
19
|
|
4180
|
BEGIN { $build_subclass->( |
|
1484
|
|
|
|
|
|
|
'lines', # Array ref of all lines making up the TYPEMAP section |
|
1485
|
|
|
|
|
|
|
)}; |
|
1486
|
|
|
|
|
|
|
|
|
1487
|
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
# Feed all the lines to ExtUtils::Typemaps. |
|
1489
|
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
sub parse { |
|
1491
|
145
|
|
|
145
|
|
434
|
my __PACKAGE__ $self = shift; |
|
1492
|
145
|
|
|
|
|
361
|
my ExtUtils::ParseXS $pxs = shift; |
|
1493
|
|
|
|
|
|
|
|
|
1494
|
145
|
|
|
|
|
1116
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1495
|
|
|
|
|
|
|
|
|
1496
|
145
|
|
|
|
|
308
|
shift @{$pxs->{line}}; # skip the 'TYPEMAP:' line |
|
|
145
|
|
|
|
|
839
|
|
|
1497
|
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
# Suck in all remaining lines |
|
1499
|
145
|
|
|
|
|
555
|
$self->{lines} = $pxs->{line}; |
|
1500
|
145
|
|
|
|
|
773
|
$pxs->{line} = []; |
|
1501
|
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
my $tmap = ExtUtils::Typemaps->new( |
|
1503
|
145
|
|
|
|
|
3395
|
string => join("", map "$_\n", @{$self->{lines}}), |
|
1504
|
|
|
|
|
|
|
lineno_offset => 1 + ($pxs->current_line_number() || 0), |
|
1505
|
|
|
|
|
|
|
fake_filename => $pxs->{in_filename}, |
|
1506
|
145
|
|
50
|
|
|
425
|
); |
|
1507
|
|
|
|
|
|
|
|
|
1508
|
145
|
|
|
|
|
1911
|
$pxs->{typemaps_object}->merge(typemap => $tmap, replace => 1); |
|
1509
|
|
|
|
|
|
|
|
|
1510
|
145
|
|
|
|
|
1966
|
1; |
|
1511
|
|
|
|
|
|
|
} |
|
1512
|
|
|
|
|
|
|
|
|
1513
|
|
|
|
|
|
|
|
|
1514
|
|
|
|
|
|
|
# ====================================================================== |
|
1515
|
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::pre_boot; |
|
1517
|
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
# AST node representing C code that is emitted after all user-defined |
|
1519
|
|
|
|
|
|
|
# XSUBs but before the boot XSUB. (This currently consists of |
|
1520
|
|
|
|
|
|
|
# 'Foo::Bar::()' XSUBs for any packages which have overloading.) |
|
1521
|
|
|
|
|
|
|
# |
|
1522
|
|
|
|
|
|
|
# This node's parse() method doesn't actually consume any lines; the node |
|
1523
|
|
|
|
|
|
|
# exists just for its as_code() method. |
|
1524
|
|
|
|
|
|
|
|
|
1525
|
19
|
|
|
19
|
|
86
|
BEGIN { $build_subclass->( |
|
1526
|
|
|
|
|
|
|
)}; |
|
1527
|
|
|
|
|
|
|
|
|
1528
|
|
|
|
|
|
|
sub parse { |
|
1529
|
285
|
|
|
285
|
|
677
|
my __PACKAGE__ $self = shift; |
|
1530
|
285
|
|
|
|
|
660
|
my ExtUtils::ParseXS $pxs = shift; |
|
1531
|
|
|
|
|
|
|
|
|
1532
|
285
|
|
|
|
|
1392
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1533
|
285
|
|
|
|
|
1722
|
1; |
|
1534
|
|
|
|
|
|
|
} |
|
1535
|
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
sub as_code { |
|
1537
|
283
|
|
|
283
|
|
3870
|
my __PACKAGE__ $self = shift; |
|
1538
|
283
|
|
|
|
|
1046
|
my ExtUtils::ParseXS $pxs = shift; |
|
1539
|
|
|
|
|
|
|
|
|
1540
|
|
|
|
|
|
|
# For each package FOO which has had at least one overloaded method |
|
1541
|
|
|
|
|
|
|
# specified: |
|
1542
|
|
|
|
|
|
|
# - create a stub XSUB in that package called nil; |
|
1543
|
|
|
|
|
|
|
# - generate code to be added to the boot XSUB which links that XSUB |
|
1544
|
|
|
|
|
|
|
# to the symbol table entry *{"FOO::()"}. This mimics the action in |
|
1545
|
|
|
|
|
|
|
# overload::import() which creates the stub method as a quick way to |
|
1546
|
|
|
|
|
|
|
# check whether an object is overloaded (including via inheritance), |
|
1547
|
|
|
|
|
|
|
# by doing $self->can('()'). |
|
1548
|
|
|
|
|
|
|
# - Further down, we add a ${"FOO:()"} scalar containing the value of |
|
1549
|
|
|
|
|
|
|
# 'fallback' (or undef if not specified). |
|
1550
|
|
|
|
|
|
|
# |
|
1551
|
|
|
|
|
|
|
# XXX In 5.18.0, this arrangement was changed in overload.pm, but hasn't |
|
1552
|
|
|
|
|
|
|
# been updated here. The *() glob was being used for two different |
|
1553
|
|
|
|
|
|
|
# purposes: a sub to do a quick check of overloadability, and a scalar |
|
1554
|
|
|
|
|
|
|
# to indicate what 'fallback' value was specified (even if it wasn't |
|
1555
|
|
|
|
|
|
|
# specified). The commits: |
|
1556
|
|
|
|
|
|
|
# v5.16.0-87-g50853fa94f |
|
1557
|
|
|
|
|
|
|
# v5.16.0-190-g3866ea3be5 |
|
1558
|
|
|
|
|
|
|
# v5.17.1-219-g79c9643d87 |
|
1559
|
|
|
|
|
|
|
# changed this so that overloadability is checked by &((, while fallback |
|
1560
|
|
|
|
|
|
|
# is checked by $() (and not present unless specified by 'fallback' |
|
1561
|
|
|
|
|
|
|
# as opposed to the always being present, but sometimes undef). |
|
1562
|
|
|
|
|
|
|
# Except that, in the presence of fallback, &() is added too for |
|
1563
|
|
|
|
|
|
|
# backcompat reasons (which I don't fully understand - DAPM). |
|
1564
|
|
|
|
|
|
|
# See overload.pm's import() and OVERLOAD() methods for more detail. |
|
1565
|
|
|
|
|
|
|
# |
|
1566
|
|
|
|
|
|
|
# So this code (and the code in as_boot_code) needs updating to match. |
|
1567
|
|
|
|
|
|
|
|
|
1568
|
283
|
|
|
|
|
651
|
for my $package (sort keys %{$pxs->{map_overloaded_package_to_C_package}}) |
|
|
283
|
|
|
|
|
6473
|
|
|
1569
|
|
|
|
|
|
|
{ |
|
1570
|
|
|
|
|
|
|
# make them findable with fetchmethod |
|
1571
|
5
|
|
|
|
|
27
|
my $packid = $pxs->{map_overloaded_package_to_C_package}{$package}; |
|
1572
|
5
|
|
|
|
|
106
|
print $self->Q(<<"EOF"); |
|
1573
|
|
|
|
|
|
|
|XS_EUPXS(XS_${packid}_nil); /* prototype to pass -Wmissing-prototypes */ |
|
1574
|
|
|
|
|
|
|
|XS_EUPXS(XS_${packid}_nil) |
|
1575
|
|
|
|
|
|
|
|{ |
|
1576
|
|
|
|
|
|
|
| dXSARGS; |
|
1577
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(items); |
|
1578
|
|
|
|
|
|
|
| XSRETURN_EMPTY; |
|
1579
|
|
|
|
|
|
|
|} |
|
1580
|
|
|
|
|
|
|
| |
|
1581
|
|
|
|
|
|
|
EOF |
|
1582
|
|
|
|
|
|
|
} |
|
1583
|
|
|
|
|
|
|
} |
|
1584
|
|
|
|
|
|
|
|
|
1585
|
|
|
|
|
|
|
sub as_boot_code { |
|
1586
|
283
|
|
|
283
|
|
599
|
my __PACKAGE__ $self = shift; |
|
1587
|
283
|
|
|
|
|
6620
|
my ExtUtils::ParseXS $pxs = shift; |
|
1588
|
|
|
|
|
|
|
|
|
1589
|
283
|
|
|
|
|
672
|
my @early; |
|
1590
|
283
|
|
|
|
|
639
|
for my $package (sort keys %{$pxs->{map_overloaded_package_to_C_package}}) |
|
|
283
|
|
|
|
|
2129
|
|
|
1591
|
|
|
|
|
|
|
{ |
|
1592
|
5
|
|
|
|
|
25
|
my $packid = $pxs->{map_overloaded_package_to_C_package}{$package}; |
|
1593
|
5
|
|
|
|
|
35
|
push @early, $self->Q(<<"EOF"); |
|
1594
|
|
|
|
|
|
|
| /* Making a sub named "${package}::()" allows the package */ |
|
1595
|
|
|
|
|
|
|
| /* to be findable via fetchmethod(), and causes */ |
|
1596
|
|
|
|
|
|
|
| /* overload::Overloaded("$package") to return true. */ |
|
1597
|
|
|
|
|
|
|
| (void)newXS_deffile("${package}::()", XS_${packid}_nil); |
|
1598
|
|
|
|
|
|
|
EOF |
|
1599
|
|
|
|
|
|
|
} |
|
1600
|
283
|
|
|
|
|
1100
|
return \@early, []; |
|
1601
|
|
|
|
|
|
|
} |
|
1602
|
|
|
|
|
|
|
|
|
1603
|
|
|
|
|
|
|
|
|
1604
|
|
|
|
|
|
|
# ====================================================================== |
|
1605
|
|
|
|
|
|
|
|
|
1606
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::boot_xsub; |
|
1607
|
|
|
|
|
|
|
|
|
1608
|
|
|
|
|
|
|
# AST node representing C code that is emitted to create the boo XSUB. |
|
1609
|
|
|
|
|
|
|
# |
|
1610
|
|
|
|
|
|
|
# This node's parse() method doesn't actually consume any lines; the node |
|
1611
|
|
|
|
|
|
|
# exists just for its as_code() method. |
|
1612
|
|
|
|
|
|
|
|
|
1613
|
19
|
|
|
19
|
|
96
|
BEGIN { $build_subclass->( |
|
1614
|
|
|
|
|
|
|
)}; |
|
1615
|
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
sub parse { |
|
1617
|
285
|
|
|
285
|
|
642
|
my __PACKAGE__ $self = shift; |
|
1618
|
285
|
|
|
|
|
673
|
my ExtUtils::ParseXS $pxs = shift; |
|
1619
|
|
|
|
|
|
|
|
|
1620
|
285
|
|
|
|
|
1076
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1621
|
285
|
|
|
|
|
898
|
1; |
|
1622
|
|
|
|
|
|
|
} |
|
1623
|
|
|
|
|
|
|
|
|
1624
|
|
|
|
|
|
|
sub as_code { |
|
1625
|
283
|
|
|
283
|
|
715
|
my __PACKAGE__ $self = shift; |
|
1626
|
283
|
|
|
|
|
718
|
my ExtUtils::ParseXS $pxs = shift; |
|
1627
|
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
# Walk the AST accumulating any boot code generated by |
|
1629
|
|
|
|
|
|
|
# the various nodes' as_boot_code() methods. |
|
1630
|
283
|
|
|
|
|
1755
|
my ($early, $later) = $pxs->{AST}->as_boot_code($pxs); |
|
1631
|
|
|
|
|
|
|
|
|
1632
|
|
|
|
|
|
|
# Emit the boot_Foo__Bar() C function / XSUB |
|
1633
|
|
|
|
|
|
|
|
|
1634
|
283
|
|
|
|
|
1072
|
print $self->Q(<<"EOF"); |
|
1635
|
|
|
|
|
|
|
|#ifdef __cplusplus |
|
1636
|
|
|
|
|
|
|
|extern "C" $open_brace |
|
1637
|
|
|
|
|
|
|
|#endif |
|
1638
|
|
|
|
|
|
|
|XS_EXTERNAL(boot_$pxs->{MODULE_cname}); /* prototype to pass -Wmissing-prototypes */ |
|
1639
|
|
|
|
|
|
|
|XS_EXTERNAL(boot_$pxs->{MODULE_cname}) |
|
1640
|
|
|
|
|
|
|
|$open_brace |
|
1641
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 21, 5) |
|
1642
|
|
|
|
|
|
|
| dVAR; dXSARGS; |
|
1643
|
|
|
|
|
|
|
|#else |
|
1644
|
283
|
100
|
|
|
|
2625
|
| dVAR; ${\($pxs->{VERSIONCHECK_value} ? 'dXSBOOTARGSXSAPIVERCHK;' : 'dXSBOOTARGSAPIVERCHK;')} |
|
1645
|
|
|
|
|
|
|
|#endif |
|
1646
|
|
|
|
|
|
|
EOF |
|
1647
|
|
|
|
|
|
|
|
|
1648
|
|
|
|
|
|
|
# Declare a 'file' var for passing to newXS() and variants. |
|
1649
|
|
|
|
|
|
|
# |
|
1650
|
|
|
|
|
|
|
# If there is no $pxs->{seen_an_XSUB} then there are no xsubs |
|
1651
|
|
|
|
|
|
|
# in this .xs so 'file' is unused, so silence warnings. |
|
1652
|
|
|
|
|
|
|
# |
|
1653
|
|
|
|
|
|
|
# 'file' can also be unused in other circumstances: in particular, |
|
1654
|
|
|
|
|
|
|
# newXS_deffile() doesn't take a file parameter. So suppress any |
|
1655
|
|
|
|
|
|
|
# 'unused var' warning always. |
|
1656
|
|
|
|
|
|
|
# |
|
1657
|
|
|
|
|
|
|
# Give it the correct 'const'ness: Under 5.8.x and lower, newXS() is |
|
1658
|
|
|
|
|
|
|
# declared in proto.h as expecting a non-const file name argument. If |
|
1659
|
|
|
|
|
|
|
# the wrong qualifier is used, it causes breakage with C++ compilers and |
|
1660
|
|
|
|
|
|
|
# warnings with recent gcc. |
|
1661
|
|
|
|
|
|
|
|
|
1662
|
283
|
100
|
|
|
|
3596
|
print $self->Q(<<"EOF") if $pxs->{seen_an_XSUB}; |
|
1663
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */ |
|
1664
|
|
|
|
|
|
|
| char* file = __FILE__; |
|
1665
|
|
|
|
|
|
|
|#else |
|
1666
|
|
|
|
|
|
|
| const char* file = __FILE__; |
|
1667
|
|
|
|
|
|
|
|#endif |
|
1668
|
|
|
|
|
|
|
| |
|
1669
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(file); |
|
1670
|
|
|
|
|
|
|
EOF |
|
1671
|
|
|
|
|
|
|
|
|
1672
|
|
|
|
|
|
|
# Emit assorted declarations |
|
1673
|
|
|
|
|
|
|
|
|
1674
|
283
|
|
|
|
|
2577
|
print $self->Q(<<"EOF"); |
|
1675
|
|
|
|
|
|
|
| |
|
1676
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(cv); /* -W */ |
|
1677
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(items); /* -W */ |
|
1678
|
|
|
|
|
|
|
EOF |
|
1679
|
|
|
|
|
|
|
|
|
1680
|
283
|
100
|
|
|
|
2561
|
if ($pxs->{VERSIONCHECK_value}) { |
|
1681
|
282
|
|
|
|
|
1743
|
print $self->Q(<<"EOF"); |
|
1682
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 21, 5) |
|
1683
|
|
|
|
|
|
|
| XS_VERSION_BOOTCHECK; |
|
1684
|
|
|
|
|
|
|
|# ifdef XS_APIVERSION_BOOTCHECK |
|
1685
|
|
|
|
|
|
|
| XS_APIVERSION_BOOTCHECK; |
|
1686
|
|
|
|
|
|
|
|# endif |
|
1687
|
|
|
|
|
|
|
|#endif |
|
1688
|
|
|
|
|
|
|
| |
|
1689
|
|
|
|
|
|
|
EOF |
|
1690
|
|
|
|
|
|
|
} |
|
1691
|
|
|
|
|
|
|
else { |
|
1692
|
1
|
|
|
|
|
3
|
print $self->Q(<<"EOF") ; |
|
1693
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 21, 5) && defined(XS_APIVERSION_BOOTCHECK) |
|
1694
|
|
|
|
|
|
|
| XS_APIVERSION_BOOTCHECK; |
|
1695
|
|
|
|
|
|
|
|#endif |
|
1696
|
|
|
|
|
|
|
| |
|
1697
|
|
|
|
|
|
|
EOF |
|
1698
|
|
|
|
|
|
|
} |
|
1699
|
|
|
|
|
|
|
|
|
1700
|
|
|
|
|
|
|
# Declare a 'cv' variable within a scope small enough to be visible |
|
1701
|
|
|
|
|
|
|
# just to newXS() calls which need to do further processing of the cv: |
|
1702
|
|
|
|
|
|
|
# in particular, when emitting one of: |
|
1703
|
|
|
|
|
|
|
# XSANY.any_i32 = $value; |
|
1704
|
|
|
|
|
|
|
# XSINTERFACE_FUNC_SET(cv, $value); |
|
1705
|
|
|
|
|
|
|
|
|
1706
|
283
|
100
|
|
|
|
2983
|
if ($pxs->{need_boot_cv}) { |
|
1707
|
26
|
|
|
|
|
183
|
print $self->Q(<<"EOF"); |
|
1708
|
|
|
|
|
|
|
| $open_brace |
|
1709
|
|
|
|
|
|
|
| CV * cv; |
|
1710
|
|
|
|
|
|
|
| |
|
1711
|
|
|
|
|
|
|
EOF |
|
1712
|
|
|
|
|
|
|
} |
|
1713
|
|
|
|
|
|
|
|
|
1714
|
|
|
|
|
|
|
# More overload stuff |
|
1715
|
|
|
|
|
|
|
|
|
1716
|
283
|
100
|
|
|
|
817
|
if (keys %{ $pxs->{map_overloaded_package_to_C_package} }) { |
|
|
283
|
|
|
|
|
1163
|
|
|
1717
|
|
|
|
|
|
|
# Emit just once if any overloads: |
|
1718
|
|
|
|
|
|
|
# Before 5.10, PL_amagic_generation used to need setting to at |
|
1719
|
|
|
|
|
|
|
# least a non-zero value to tell perl that any overloading was |
|
1720
|
|
|
|
|
|
|
# present. |
|
1721
|
4
|
|
|
|
|
31
|
print $self->Q(<<"EOF"); |
|
1722
|
|
|
|
|
|
|
| /* register the overloading (type 'A') magic */ |
|
1723
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 8, 999) /* PERL_VERSION_LT is 5.33+ */ |
|
1724
|
|
|
|
|
|
|
| PL_amagic_generation++; |
|
1725
|
|
|
|
|
|
|
|#endif |
|
1726
|
|
|
|
|
|
|
EOF |
|
1727
|
|
|
|
|
|
|
|
|
1728
|
4
|
|
|
|
|
33
|
for my $package ( |
|
1729
|
4
|
|
|
|
|
24
|
sort keys %{ $pxs->{map_overloaded_package_to_C_package} }) |
|
1730
|
|
|
|
|
|
|
{ |
|
1731
|
|
|
|
|
|
|
# Emit once for each package with overloads: |
|
1732
|
|
|
|
|
|
|
# Set ${'Foo::()'} to the fallback value for each overloaded |
|
1733
|
|
|
|
|
|
|
# package 'Foo' (or undef if not specified). |
|
1734
|
|
|
|
|
|
|
# But see the 'XXX' comments above about fallback and $(). |
|
1735
|
|
|
|
|
|
|
|
|
1736
|
5
|
|
|
|
|
35
|
my $fallback = $pxs->{map_package_to_fallback_string}{$package}; |
|
1737
|
5
|
100
|
|
|
|
41
|
$fallback = 'UNDEF' unless defined $fallback; |
|
1738
|
5
|
50
|
|
|
|
43
|
$fallback = $fallback eq 'TRUE' ? '&PL_sv_yes' |
|
|
|
100
|
|
|
|
|
|
|
1739
|
|
|
|
|
|
|
: $fallback eq 'FALSE' ? '&PL_sv_no' |
|
1740
|
|
|
|
|
|
|
: '&PL_sv_undef'; |
|
1741
|
|
|
|
|
|
|
|
|
1742
|
5
|
|
|
|
|
53
|
print $self->Q(<<"EOF"); |
|
1743
|
|
|
|
|
|
|
| /* The magic for overload gets a GV* via gv_fetchmeth as */ |
|
1744
|
|
|
|
|
|
|
| /* mentioned above, and looks in the SV* slot of it for */ |
|
1745
|
|
|
|
|
|
|
| /* the "fallback" status. */ |
|
1746
|
|
|
|
|
|
|
| sv_setsv( |
|
1747
|
|
|
|
|
|
|
| get_sv( "${package}::()", TRUE ), |
|
1748
|
|
|
|
|
|
|
| $fallback |
|
1749
|
|
|
|
|
|
|
| ); |
|
1750
|
|
|
|
|
|
|
EOF |
|
1751
|
|
|
|
|
|
|
} |
|
1752
|
|
|
|
|
|
|
} |
|
1753
|
|
|
|
|
|
|
|
|
1754
|
|
|
|
|
|
|
# Emit any boot code associated with newXS(). |
|
1755
|
|
|
|
|
|
|
|
|
1756
|
283
|
|
|
|
|
1051
|
print @$early; |
|
1757
|
|
|
|
|
|
|
|
|
1758
|
|
|
|
|
|
|
# Emit closing scope for the 'CV *cv' declaration |
|
1759
|
|
|
|
|
|
|
|
|
1760
|
283
|
100
|
|
|
|
3703
|
if ($pxs->{need_boot_cv}) { |
|
1761
|
26
|
|
|
|
|
211
|
print $self->Q(<<"EOF"); |
|
1762
|
|
|
|
|
|
|
| $close_brace |
|
1763
|
|
|
|
|
|
|
EOF |
|
1764
|
|
|
|
|
|
|
} |
|
1765
|
|
|
|
|
|
|
|
|
1766
|
|
|
|
|
|
|
# Emit any lines derived from BOOT: sections |
|
1767
|
|
|
|
|
|
|
|
|
1768
|
283
|
100
|
|
|
|
1057
|
if (@$later) { |
|
1769
|
13
|
|
|
|
|
55
|
print $self->Q(<<"EOF"); |
|
1770
|
|
|
|
|
|
|
| |
|
1771
|
|
|
|
|
|
|
| /* Initialisation Section */ |
|
1772
|
|
|
|
|
|
|
| |
|
1773
|
|
|
|
|
|
|
EOF |
|
1774
|
|
|
|
|
|
|
|
|
1775
|
13
|
|
|
|
|
136
|
print @$later; |
|
1776
|
|
|
|
|
|
|
|
|
1777
|
|
|
|
|
|
|
print 'ExtUtils::ParseXS::CountLines'->end_marker, "\n" |
|
1778
|
13
|
50
|
|
|
|
163
|
if $pxs->{config_WantLineNumbers}; |
|
1779
|
|
|
|
|
|
|
|
|
1780
|
13
|
|
|
|
|
125
|
print $self->Q(<<"EOF"); |
|
1781
|
|
|
|
|
|
|
| |
|
1782
|
|
|
|
|
|
|
| /* End of Initialisation Section */ |
|
1783
|
|
|
|
|
|
|
| |
|
1784
|
|
|
|
|
|
|
EOF |
|
1785
|
|
|
|
|
|
|
} |
|
1786
|
|
|
|
|
|
|
|
|
1787
|
|
|
|
|
|
|
# Emit code to call any UNITCHECK blocks and return true. |
|
1788
|
|
|
|
|
|
|
# Since 5.22, this is been put into a separate function. |
|
1789
|
|
|
|
|
|
|
|
|
1790
|
283
|
|
|
|
|
1628
|
print $self->Q(<<"EOF"); |
|
1791
|
|
|
|
|
|
|
|#if PERL_VERSION_LE(5, 21, 5) |
|
1792
|
|
|
|
|
|
|
|# if PERL_VERSION_GE(5, 9, 0) |
|
1793
|
|
|
|
|
|
|
| if (PL_unitcheckav) |
|
1794
|
|
|
|
|
|
|
| call_list(PL_scopestack_ix, PL_unitcheckav); |
|
1795
|
|
|
|
|
|
|
|# endif |
|
1796
|
|
|
|
|
|
|
| XSRETURN_YES; |
|
1797
|
|
|
|
|
|
|
|#else |
|
1798
|
|
|
|
|
|
|
| Perl_xs_boot_epilog(aTHX_ ax); |
|
1799
|
|
|
|
|
|
|
|#endif |
|
1800
|
|
|
|
|
|
|
|$close_brace |
|
1801
|
|
|
|
|
|
|
| |
|
1802
|
|
|
|
|
|
|
|#ifdef __cplusplus |
|
1803
|
|
|
|
|
|
|
|$close_brace |
|
1804
|
|
|
|
|
|
|
|#endif |
|
1805
|
|
|
|
|
|
|
EOF |
|
1806
|
|
|
|
|
|
|
} |
|
1807
|
|
|
|
|
|
|
|
|
1808
|
|
|
|
|
|
|
|
|
1809
|
|
|
|
|
|
|
# ====================================================================== |
|
1810
|
|
|
|
|
|
|
|
|
1811
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::xsub; |
|
1812
|
|
|
|
|
|
|
|
|
1813
|
|
|
|
|
|
|
# Process an entire XSUB definition |
|
1814
|
|
|
|
|
|
|
|
|
1815
|
19
|
|
|
19
|
|
110
|
BEGIN { $build_subclass->( |
|
1816
|
|
|
|
|
|
|
'decl', # Node::xsub_decl object holding this XSUB's declaration |
|
1817
|
|
|
|
|
|
|
|
|
1818
|
|
|
|
|
|
|
# Boolean flags: they indicate that at least one of each specified |
|
1819
|
|
|
|
|
|
|
# keyword has been seen in this XSUB |
|
1820
|
|
|
|
|
|
|
'seen_ALIAS', |
|
1821
|
|
|
|
|
|
|
'seen_INTERFACE', |
|
1822
|
|
|
|
|
|
|
'seen_INTERFACE_MACRO', |
|
1823
|
|
|
|
|
|
|
'seen_PPCODE', |
|
1824
|
|
|
|
|
|
|
'seen_PROTOTYPE', |
|
1825
|
|
|
|
|
|
|
'seen_SCOPE', |
|
1826
|
|
|
|
|
|
|
|
|
1827
|
|
|
|
|
|
|
# These three fields indicate how many SVs are returned to the caller, |
|
1828
|
|
|
|
|
|
|
# and so influence the emitting of 'EXTEND(n)', 'XSRETURN(n)', and |
|
1829
|
|
|
|
|
|
|
# potentially, the value of n in 'ST(n) = ...'. |
|
1830
|
|
|
|
|
|
|
# |
|
1831
|
|
|
|
|
|
|
# XSRETURN_count_basic is 0 or 1 and indicates whether a basic return |
|
1832
|
|
|
|
|
|
|
# value is pushed onto the stack. It is usually directly related to |
|
1833
|
|
|
|
|
|
|
# whether the XSUB is declared void, but NO_RETURN and CODE_sets_ST0 |
|
1834
|
|
|
|
|
|
|
# can alter that. |
|
1835
|
|
|
|
|
|
|
# |
|
1836
|
|
|
|
|
|
|
# XSRETURN_count_extra indicates how many SVs will be returned in |
|
1837
|
|
|
|
|
|
|
# addition the basic 0 or 1. These will be params declared as OUTLIST. |
|
1838
|
|
|
|
|
|
|
# |
|
1839
|
|
|
|
|
|
|
# CODE_sets_ST0 is a flag indicating that something within a CODE |
|
1840
|
|
|
|
|
|
|
# block is doing 'ST(0) = ..' or similar. This is a workaround for |
|
1841
|
|
|
|
|
|
|
# a bug: see the code comments "Horrible 'void' return arg count hack" |
|
1842
|
|
|
|
|
|
|
# in Node::CODE::parse() for more details. |
|
1843
|
|
|
|
|
|
|
'CODE_sets_ST0', # Bool |
|
1844
|
|
|
|
|
|
|
'XSRETURN_count_basic', # Int |
|
1845
|
|
|
|
|
|
|
'XSRETURN_count_extra', # Int |
|
1846
|
|
|
|
|
|
|
|
|
1847
|
|
|
|
|
|
|
# These maintain the alias parsing state across potentially multiple |
|
1848
|
|
|
|
|
|
|
# ALIAS keywords and or lines: |
|
1849
|
|
|
|
|
|
|
|
|
1850
|
|
|
|
|
|
|
'map_alias_name_to_value', # Hash: maps seen alias names to their value |
|
1851
|
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
'map_alias_value_to_name_seen_hash', # Hash of Hash of Bools: |
|
1853
|
|
|
|
|
|
|
# indicates which alias names have been |
|
1854
|
|
|
|
|
|
|
# used for each value. |
|
1855
|
|
|
|
|
|
|
|
|
1856
|
|
|
|
|
|
|
'alias_clash_hinted', # Bool: an ALIAS warn-hint has been emitted. |
|
1857
|
|
|
|
|
|
|
|
|
1858
|
|
|
|
|
|
|
# Maintain the INTERFACE parsing state across potentially multiple |
|
1859
|
|
|
|
|
|
|
# INTERFACE keywords and/or lines: |
|
1860
|
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
'map_interface_name_short_to_original', # Hash: for each INTERFACE |
|
1862
|
|
|
|
|
|
|
# name, map the short (PREFIX removed) name |
|
1863
|
|
|
|
|
|
|
# to the original name. |
|
1864
|
|
|
|
|
|
|
|
|
1865
|
|
|
|
|
|
|
# Maintain the OVERLOAD parsing state across potentially multiple |
|
1866
|
|
|
|
|
|
|
# OVERLOAD keywords and/or lines: |
|
1867
|
|
|
|
|
|
|
|
|
1868
|
|
|
|
|
|
|
'overload_name_seen', # Hash of Bools: indicates overload method |
|
1869
|
|
|
|
|
|
|
# names (such as '<=>') which have been |
|
1870
|
|
|
|
|
|
|
# listed by OVERLOAD (for newXS boot code |
|
1871
|
|
|
|
|
|
|
# emitting). |
|
1872
|
|
|
|
|
|
|
|
|
1873
|
|
|
|
|
|
|
# Maintain the ATTRS parsing state across potentially multiple |
|
1874
|
|
|
|
|
|
|
# ATTRS keywords and or lines: |
|
1875
|
|
|
|
|
|
|
|
|
1876
|
|
|
|
|
|
|
'attributes', # Array of Strs: all ATTRIBUTE keywords |
|
1877
|
|
|
|
|
|
|
# (possibly multiple space-separated |
|
1878
|
|
|
|
|
|
|
# keywords per string). |
|
1879
|
|
|
|
|
|
|
|
|
1880
|
|
|
|
|
|
|
# INTERFACE_MACRO state |
|
1881
|
|
|
|
|
|
|
|
|
1882
|
|
|
|
|
|
|
'interface_macro', # Str: value of interface extraction macro. |
|
1883
|
|
|
|
|
|
|
'interface_macro_set', # Str: value of interface setting macro. |
|
1884
|
|
|
|
|
|
|
|
|
1885
|
|
|
|
|
|
|
# PROTOTYPE value |
|
1886
|
|
|
|
|
|
|
|
|
1887
|
|
|
|
|
|
|
'prototype', # Str: is set to either the global PROTOTYPES |
|
1888
|
|
|
|
|
|
|
# values (0 or 1), or to what's been |
|
1889
|
|
|
|
|
|
|
# overridden for this XSUB with PROTOTYPE |
|
1890
|
|
|
|
|
|
|
# "0": DISABLE |
|
1891
|
|
|
|
|
|
|
# "1": ENABLE |
|
1892
|
|
|
|
|
|
|
# "2": empty prototype |
|
1893
|
|
|
|
|
|
|
# other: a specific prototype. |
|
1894
|
|
|
|
|
|
|
|
|
1895
|
|
|
|
|
|
|
# Misc |
|
1896
|
|
|
|
|
|
|
|
|
1897
|
|
|
|
|
|
|
'SCOPE_enabled', # Bool: "SCOPE: ENABLE" seen, in either the |
|
1898
|
|
|
|
|
|
|
# file or XSUB part of the XS file |
|
1899
|
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
'PACKAGE_name', # value of $pxs->{PACKAGE_name} at parse time |
|
1901
|
|
|
|
|
|
|
'PACKAGE_C_name', # value of $pxs->{PACKAGE_C_name} at parse time |
|
1902
|
|
|
|
|
|
|
|
|
1903
|
|
|
|
|
|
|
)}; |
|
1904
|
|
|
|
|
|
|
|
|
1905
|
|
|
|
|
|
|
|
|
1906
|
|
|
|
|
|
|
sub parse { |
|
1907
|
366
|
|
|
366
|
|
1257
|
my __PACKAGE__ $self = shift; |
|
1908
|
366
|
|
|
|
|
827
|
my ExtUtils::ParseXS $pxs = shift; |
|
1909
|
|
|
|
|
|
|
|
|
1910
|
366
|
|
|
|
|
1579
|
$self->SUPER::parse($pxs); # set file/line_no |
|
1911
|
|
|
|
|
|
|
|
|
1912
|
|
|
|
|
|
|
# record what package we're in |
|
1913
|
366
|
|
|
|
|
1436
|
$self->{PACKAGE_name} = $pxs->{PACKAGE_name}; |
|
1914
|
366
|
|
|
|
|
1206
|
$self->{PACKAGE_C_name} = $pxs->{PACKAGE_C_name}; |
|
1915
|
|
|
|
|
|
|
|
|
1916
|
|
|
|
|
|
|
# Initially inherit the prototype behaviour for the XSUB from the |
|
1917
|
|
|
|
|
|
|
# global PROTOTYPES default |
|
1918
|
366
|
|
|
|
|
1063
|
$self->{prototype} = $pxs->{PROTOTYPES_value}; |
|
1919
|
|
|
|
|
|
|
|
|
1920
|
|
|
|
|
|
|
# inherit any SCOPE: value that immediately preceded the XSUB |
|
1921
|
|
|
|
|
|
|
# declaration |
|
1922
|
366
|
|
|
|
|
896
|
$self->{SCOPE_enabled} = $pxs->{file_SCOPE_enabled}; |
|
1923
|
|
|
|
|
|
|
|
|
1924
|
|
|
|
|
|
|
# Parse the XSUB's declaration (return type, name, parameters) |
|
1925
|
|
|
|
|
|
|
|
|
1926
|
366
|
|
|
|
|
2886
|
my $decl = ExtUtils::ParseXS::Node::xsub_decl->new(); |
|
1927
|
366
|
|
|
|
|
1291
|
$self->{decl} = $decl; |
|
1928
|
366
|
100
|
|
|
|
2305
|
$decl->parse($pxs, $self) |
|
1929
|
|
|
|
|
|
|
or return; |
|
1930
|
363
|
|
|
|
|
905
|
push @{$self->{kids}}, $decl; |
|
|
363
|
|
|
|
|
1446
|
|
|
1931
|
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
# Check all the @{ $pxs->{line}} lines for balance: all the |
|
1933
|
|
|
|
|
|
|
# #if, #else, #endif etc within the XSUB should balance out. |
|
1934
|
363
|
|
|
|
|
2820
|
ExtUtils::ParseXS::Utilities::check_conditional_preprocessor_statements(); |
|
1935
|
|
|
|
|
|
|
|
|
1936
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
1937
|
|
|
|
|
|
|
# Each iteration of this loop will process 1 optional CASE: line, |
|
1938
|
|
|
|
|
|
|
# followed by all the other blocks. In the absence of a CASE: line, |
|
1939
|
|
|
|
|
|
|
# this loop is only iterated once. |
|
1940
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
1941
|
|
|
|
|
|
|
|
|
1942
|
363
|
|
|
|
|
697
|
my $num = 0; # the number of CASE+bodies seen |
|
1943
|
363
|
|
|
|
|
585
|
my $seen_bare_xbody = 0; # seen a previous body without a CASE |
|
1944
|
363
|
|
|
|
|
1398
|
my $case_had_cond; # the previous CASE had a condition |
|
1945
|
|
|
|
|
|
|
|
|
1946
|
|
|
|
|
|
|
# Repeatedly look for CASE or XSUB body. |
|
1947
|
363
|
|
|
|
|
630
|
while (1) { |
|
1948
|
|
|
|
|
|
|
# Parse a CASE statement if present. |
|
1949
|
742
|
|
|
|
|
2813
|
my ($case) = |
|
1950
|
|
|
|
|
|
|
$self->parse_keywords( |
|
1951
|
|
|
|
|
|
|
$pxs, $self, undef, # xbody not yet present so use undef |
|
1952
|
|
|
|
|
|
|
1, # process maximum of one keyword |
|
1953
|
|
|
|
|
|
|
"CASE", |
|
1954
|
|
|
|
|
|
|
); |
|
1955
|
|
|
|
|
|
|
|
|
1956
|
742
|
100
|
|
|
|
2112
|
if (defined $case) { |
|
1957
|
39
|
|
|
|
|
126
|
$case->{num} = ++$num; |
|
1958
|
39
|
100
|
100
|
|
|
602
|
$pxs->blurt("Error: 'CASE:' after unconditional 'CASE:'") |
|
1959
|
|
|
|
|
|
|
if $num > 1 && ! $case_had_cond; |
|
1960
|
39
|
|
|
|
|
171
|
$case_had_cond = length $case->{cond}; |
|
1961
|
39
|
100
|
|
|
|
266
|
$pxs->blurt("Error: no 'CASE:' at top of function") |
|
1962
|
|
|
|
|
|
|
if $seen_bare_xbody; |
|
1963
|
|
|
|
|
|
|
} |
|
1964
|
|
|
|
|
|
|
else { |
|
1965
|
703
|
|
|
|
|
1236
|
$seen_bare_xbody = 1; |
|
1966
|
703
|
100
|
|
|
|
2068
|
if ($num++) { |
|
1967
|
|
|
|
|
|
|
# After the first CASE+body, we should only encounter |
|
1968
|
|
|
|
|
|
|
# further CASE+bodies or end-of-paragraph |
|
1969
|
357
|
100
|
|
|
|
583
|
last unless @{$pxs->{line}}; |
|
|
357
|
|
|
|
|
1486
|
|
|
1970
|
2
|
|
|
|
|
30
|
my $l = $pxs->{line}[0]; |
|
1971
|
2
|
100
|
|
|
|
163
|
$pxs->death( |
|
1972
|
|
|
|
|
|
|
$l =~ /^$ExtUtils::ParseXS::BLOCK_regexp/o |
|
1973
|
|
|
|
|
|
|
? "Error: misplaced '$1:'" |
|
1974
|
|
|
|
|
|
|
: qq{Error: junk at end of function: "$l"} |
|
1975
|
|
|
|
|
|
|
); |
|
1976
|
|
|
|
|
|
|
} |
|
1977
|
|
|
|
|
|
|
} |
|
1978
|
|
|
|
|
|
|
|
|
1979
|
|
|
|
|
|
|
# Parse the XSUB's body |
|
1980
|
|
|
|
|
|
|
|
|
1981
|
385
|
|
|
|
|
4421
|
my $xbody = ExtUtils::ParseXS::Node::xbody->new(); |
|
1982
|
385
|
50
|
|
|
|
1723
|
$xbody->parse($pxs, $self) |
|
1983
|
|
|
|
|
|
|
or return; |
|
1984
|
|
|
|
|
|
|
|
|
1985
|
379
|
100
|
|
|
|
1195
|
if (defined $case) { |
|
1986
|
|
|
|
|
|
|
# make the xbody a child of the CASE |
|
1987
|
39
|
|
|
|
|
224
|
push @{$case->{kids}}, $xbody; |
|
|
39
|
|
|
|
|
213
|
|
|
1988
|
39
|
|
|
|
|
201
|
$xbody = $case; |
|
1989
|
|
|
|
|
|
|
} |
|
1990
|
|
|
|
|
|
|
else { |
|
1991
|
340
|
|
|
|
|
552
|
push @{$self->{kids}}, $xbody; |
|
|
340
|
|
|
|
|
1178
|
|
|
1992
|
|
|
|
|
|
|
} |
|
1993
|
|
|
|
|
|
|
} # end while (@{ $pxs->{line} }) |
|
1994
|
|
|
|
|
|
|
|
|
1995
|
|
|
|
|
|
|
# If any aliases have been declared, make the main sub name ix 0 |
|
1996
|
|
|
|
|
|
|
# if not specified. |
|
1997
|
|
|
|
|
|
|
|
|
1998
|
355
|
50
|
66
|
|
|
1444
|
if ( $self->{map_alias_name_to_value} |
|
1999
|
17
|
|
|
|
|
112
|
and keys %{ $self->{map_alias_name_to_value} }) |
|
2000
|
|
|
|
|
|
|
{ |
|
2001
|
17
|
|
|
|
|
99
|
my $pname = $self->{decl}{full_perl_name}; |
|
2002
|
|
|
|
|
|
|
$self->{map_alias_name_to_value}{$pname} = 0 |
|
2003
|
17
|
100
|
|
|
|
86
|
unless defined $self->{map_alias_name_to_value}{$pname}; |
|
2004
|
|
|
|
|
|
|
} |
|
2005
|
|
|
|
|
|
|
|
|
2006
|
355
|
|
|
|
|
1297
|
1; |
|
2007
|
|
|
|
|
|
|
} |
|
2008
|
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
|
|
2010
|
|
|
|
|
|
|
sub as_code { |
|
2011
|
354
|
|
|
354
|
|
1313
|
my __PACKAGE__ $self = shift; |
|
2012
|
354
|
|
|
|
|
732
|
my ExtUtils::ParseXS $pxs = shift; |
|
2013
|
|
|
|
|
|
|
|
|
2014
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2015
|
|
|
|
|
|
|
# Emit initial C code for the XSUB |
|
2016
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2017
|
|
|
|
|
|
|
|
|
2018
|
|
|
|
|
|
|
{ |
|
2019
|
354
|
|
|
|
|
648
|
my $extern = $self->{decl}{return_type}{extern_C} |
|
2020
|
354
|
100
|
|
|
|
1995
|
? qq[extern "C"] : ""; |
|
2021
|
354
|
|
|
|
|
1313
|
my $cname = $self->{decl}{full_C_name}; |
|
2022
|
|
|
|
|
|
|
|
|
2023
|
|
|
|
|
|
|
# Emit function header |
|
2024
|
354
|
|
|
|
|
2192
|
print $self->Q(<<"EOF"); |
|
2025
|
|
|
|
|
|
|
|$extern |
|
2026
|
|
|
|
|
|
|
|XS_EUPXS(XS_$cname); /* prototype to pass -Wmissing-prototypes */ |
|
2027
|
|
|
|
|
|
|
|XS_EUPXS(XS_$cname) |
|
2028
|
|
|
|
|
|
|
|$open_brace |
|
2029
|
|
|
|
|
|
|
| dVAR; dXSARGS; |
|
2030
|
|
|
|
|
|
|
EOF |
|
2031
|
|
|
|
|
|
|
} |
|
2032
|
|
|
|
|
|
|
|
|
2033
|
354
|
100
|
|
|
|
3208
|
print $self->Q(<<"EOF") if $self->{seen_ALIAS}; |
|
2034
|
|
|
|
|
|
|
| dXSI32; |
|
2035
|
|
|
|
|
|
|
EOF |
|
2036
|
|
|
|
|
|
|
|
|
2037
|
354
|
100
|
|
|
|
1326
|
if ($self->{seen_INTERFACE}) { |
|
2038
|
9
|
|
|
|
|
60
|
my $type = $self->{decl}{return_type}{type}; |
|
2039
|
|
|
|
|
|
|
$type =~ tr/:/_/ |
|
2040
|
9
|
50
|
|
|
|
141
|
unless $pxs->{config_RetainCplusplusHierarchicalTypes}; |
|
2041
|
9
|
50
|
|
|
|
106
|
print $self->Q(<<"EOF") if $self->{seen_INTERFACE}; |
|
2042
|
|
|
|
|
|
|
| dXSFUNCTION($type); |
|
2043
|
|
|
|
|
|
|
EOF |
|
2044
|
|
|
|
|
|
|
} |
|
2045
|
|
|
|
|
|
|
|
|
2046
|
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
{ |
|
2048
|
354
|
|
|
|
|
756
|
my $params = $self->{decl}{params}; |
|
|
354
|
|
|
|
|
886
|
|
|
2049
|
|
|
|
|
|
|
# the code to emit to determine whether the correct number of argument |
|
2050
|
|
|
|
|
|
|
# have been passed |
|
2051
|
|
|
|
|
|
|
my $condition_code = |
|
2052
|
|
|
|
|
|
|
ExtUtils::ParseXS::set_cond($params->{seen_ellipsis}, |
|
2053
|
|
|
|
|
|
|
$params->{min_args}, |
|
2054
|
354
|
|
|
|
|
4650
|
$params->{nargs}); |
|
2055
|
|
|
|
|
|
|
|
|
2056
|
|
|
|
|
|
|
# "-except" cmd line switch |
|
2057
|
354
|
50
|
|
|
|
1557
|
print $self->Q(<<"EOF") if $pxs->{config_allow_exceptions}; |
|
2058
|
|
|
|
|
|
|
| char errbuf[1024]; |
|
2059
|
|
|
|
|
|
|
| *errbuf = '\\0'; |
|
2060
|
|
|
|
|
|
|
EOF |
|
2061
|
|
|
|
|
|
|
|
|
2062
|
354
|
100
|
|
|
|
880
|
if ($condition_code) { |
|
2063
|
352
|
|
|
|
|
1513
|
my $p = $params->usage_string(); |
|
2064
|
352
|
|
|
|
|
1206
|
$p =~ s/"/\\"/g; |
|
2065
|
352
|
|
|
|
|
2727
|
print $self->Q(<<"EOF"); |
|
2066
|
|
|
|
|
|
|
| if ($condition_code) |
|
2067
|
|
|
|
|
|
|
| croak_xs_usage(cv, "$p"); |
|
2068
|
|
|
|
|
|
|
EOF |
|
2069
|
|
|
|
|
|
|
} |
|
2070
|
|
|
|
|
|
|
else { |
|
2071
|
|
|
|
|
|
|
# cv and items likely to be unused |
|
2072
|
2
|
|
|
|
|
8
|
print $self->Q(<<"EOF"); |
|
2073
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(cv); /* -W */ |
|
2074
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(items); /* -W */ |
|
2075
|
|
|
|
|
|
|
EOF |
|
2076
|
|
|
|
|
|
|
} |
|
2077
|
|
|
|
|
|
|
} |
|
2078
|
|
|
|
|
|
|
|
|
2079
|
|
|
|
|
|
|
# gcc -Wall: if an XSUB has PPCODE, it is possible that none of ST, |
|
2080
|
|
|
|
|
|
|
# XSRETURN or XSprePUSH macros are used. Hence 'ax' (setup by |
|
2081
|
|
|
|
|
|
|
# dXSARGS) is unused. |
|
2082
|
|
|
|
|
|
|
# XXX: could breakup the dXSARGS; into dSP;dMARK;dITEMS |
|
2083
|
|
|
|
|
|
|
# but such a move could break third-party extensions |
|
2084
|
354
|
100
|
|
|
|
3036
|
print $self->Q(<<"EOF") if $self->{seen_PPCODE}; |
|
2085
|
|
|
|
|
|
|
| PERL_UNUSED_VAR(ax); /* -Wall */ |
|
2086
|
|
|
|
|
|
|
EOF |
|
2087
|
|
|
|
|
|
|
|
|
2088
|
354
|
100
|
|
|
|
1326
|
print $self->Q(<<"EOF") if $self->{seen_PPCODE}; |
|
2089
|
|
|
|
|
|
|
| SP -= items; |
|
2090
|
|
|
|
|
|
|
EOF |
|
2091
|
|
|
|
|
|
|
|
|
2092
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2093
|
|
|
|
|
|
|
# Emit the main body of the XSUB (all the CASE statements + bodies |
|
2094
|
|
|
|
|
|
|
# or a single body) |
|
2095
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2096
|
|
|
|
|
|
|
|
|
2097
|
354
|
|
|
|
|
651
|
$_->as_code($pxs, $self) for @{$self->{kids}}; |
|
|
354
|
|
|
|
|
1797
|
|
|
2098
|
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2100
|
|
|
|
|
|
|
# All of the body of the XSUB (including all CASE variants) has now |
|
2101
|
|
|
|
|
|
|
# been processed. Now emit any XSRETURN or similar, plus any closing |
|
2102
|
|
|
|
|
|
|
# bracket. |
|
2103
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2104
|
|
|
|
|
|
|
|
|
2105
|
352
|
50
|
|
|
|
1992
|
print $self->Q(<<"EOF") if $pxs->{config_allow_exceptions}; |
|
2106
|
|
|
|
|
|
|
| if (errbuf[0]) |
|
2107
|
|
|
|
|
|
|
| Perl_croak(aTHX_ errbuf); |
|
2108
|
|
|
|
|
|
|
EOF |
|
2109
|
|
|
|
|
|
|
|
|
2110
|
|
|
|
|
|
|
# Emit XSRETURN(N) or XSRETURN_EMPTY. It's possible that the user's |
|
2111
|
|
|
|
|
|
|
# CODE section rolled its own return, so this code may be |
|
2112
|
|
|
|
|
|
|
# unreachable. So suppress any compiler warnings. |
|
2113
|
|
|
|
|
|
|
# XXX Currently this is just for HP. Make more generic?? |
|
2114
|
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
# Suppress "statement is unreachable" warning on HPUX |
|
2116
|
352
|
50
|
|
|
|
3589
|
print "#if defined(__HP_cc) || defined(__HP_aCC)\n", |
|
2117
|
|
|
|
|
|
|
"#pragma diag_suppress 2128\n", |
|
2118
|
|
|
|
|
|
|
"#endif\n" |
|
2119
|
|
|
|
|
|
|
if $^O eq "hpux"; |
|
2120
|
|
|
|
|
|
|
|
|
2121
|
352
|
100
|
|
|
|
1293
|
unless ($self->{seen_PPCODE}) { |
|
2122
|
|
|
|
|
|
|
my $nret = $self->{XSRETURN_count_basic} |
|
2123
|
345
|
|
|
|
|
913
|
+ $self->{XSRETURN_count_extra}; |
|
2124
|
|
|
|
|
|
|
|
|
2125
|
345
|
100
|
|
|
|
1979
|
print $nret ? " XSRETURN($nret);\n" |
|
2126
|
|
|
|
|
|
|
: " XSRETURN_EMPTY;\n"; |
|
2127
|
|
|
|
|
|
|
} |
|
2128
|
|
|
|
|
|
|
|
|
2129
|
|
|
|
|
|
|
# Suppress "statement is unreachable" warning on HPUX |
|
2130
|
352
|
50
|
|
|
|
3020
|
print "#if defined(__HP_cc) || defined(__HP_aCC)\n", |
|
2131
|
|
|
|
|
|
|
"#pragma diag_default 2128\n", |
|
2132
|
|
|
|
|
|
|
"#endif\n" |
|
2133
|
|
|
|
|
|
|
if $^O eq "hpux"; |
|
2134
|
|
|
|
|
|
|
|
|
2135
|
|
|
|
|
|
|
# Emit final closing bracket for the XSUB. |
|
2136
|
352
|
|
|
|
|
2619
|
print "$close_brace\n\n"; |
|
2137
|
|
|
|
|
|
|
} |
|
2138
|
|
|
|
|
|
|
|
|
2139
|
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
# Return a list of boot code strings for the XSUB, including newXS() |
|
2141
|
|
|
|
|
|
|
# call(s) plus any additional boot stuff like handling attributes or |
|
2142
|
|
|
|
|
|
|
# storing an alias index in the XSUB's CV. |
|
2143
|
|
|
|
|
|
|
|
|
2144
|
|
|
|
|
|
|
sub as_boot_code { |
|
2145
|
352
|
|
|
352
|
|
706
|
my __PACKAGE__ $self = shift; |
|
2146
|
352
|
|
|
|
|
685
|
my ExtUtils::ParseXS $pxs = shift; |
|
2147
|
|
|
|
|
|
|
|
|
2148
|
|
|
|
|
|
|
# Depending on whether the XSUB has a prototype, work out how to |
|
2149
|
|
|
|
|
|
|
# invoke one of the newXS() function variants. Set these: |
|
2150
|
|
|
|
|
|
|
# |
|
2151
|
352
|
|
|
|
|
1461
|
my $newXS; # the newXS() variant to be called in the boot section |
|
2152
|
|
|
|
|
|
|
my $file_arg; # an extra ', file' arg to be passed to newXS call |
|
2153
|
352
|
|
|
|
|
0
|
my $proto_arg; # an extra e.g. ', "$@"' arg to be passed to newXS call |
|
2154
|
|
|
|
|
|
|
|
|
2155
|
352
|
|
|
|
|
0
|
my @code; # boot code for each alias etc |
|
2156
|
|
|
|
|
|
|
|
|
2157
|
352
|
|
|
|
|
853
|
$proto_arg = ""; |
|
2158
|
|
|
|
|
|
|
|
|
2159
|
352
|
100
|
|
|
|
1317
|
unless($self->{prototype}) { |
|
2160
|
|
|
|
|
|
|
# no prototype |
|
2161
|
301
|
|
|
|
|
606
|
$newXS = "newXS_deffile"; |
|
2162
|
301
|
|
|
|
|
1459
|
$file_arg = ""; |
|
2163
|
|
|
|
|
|
|
} |
|
2164
|
|
|
|
|
|
|
else { |
|
2165
|
|
|
|
|
|
|
# needs prototype |
|
2166
|
51
|
|
|
|
|
199
|
$newXS = "newXSproto_portable"; |
|
2167
|
51
|
|
|
|
|
117
|
$file_arg = ", file"; |
|
2168
|
|
|
|
|
|
|
|
|
2169
|
51
|
100
|
|
|
|
349
|
if ($self->{prototype} eq 2) { |
|
|
|
100
|
|
|
|
|
|
|
2170
|
|
|
|
|
|
|
# User has specified an empty prototype |
|
2171
|
|
|
|
|
|
|
} |
|
2172
|
|
|
|
|
|
|
elsif ($self->{prototype} eq 1) { |
|
2173
|
|
|
|
|
|
|
# Protoype enabled, but to be auto-generated by us |
|
2174
|
44
|
|
|
|
|
214
|
$proto_arg = $self->{decl}{params}->proto_string(); |
|
2175
|
44
|
|
|
|
|
126
|
$proto_arg =~ s{\\}{\\\\}g; # escape backslashes |
|
2176
|
|
|
|
|
|
|
} |
|
2177
|
|
|
|
|
|
|
else { |
|
2178
|
|
|
|
|
|
|
# User has manually specified a prototype |
|
2179
|
6
|
|
|
|
|
18
|
$proto_arg = $self->{prototype}; |
|
2180
|
|
|
|
|
|
|
} |
|
2181
|
|
|
|
|
|
|
|
|
2182
|
51
|
|
|
|
|
131
|
$proto_arg = qq{, "$proto_arg"}; |
|
2183
|
|
|
|
|
|
|
} |
|
2184
|
|
|
|
|
|
|
|
|
2185
|
|
|
|
|
|
|
# Now use those values to append suitable newXS() and other code |
|
2186
|
|
|
|
|
|
|
# into @code, for later insertion into the boot sub. |
|
2187
|
|
|
|
|
|
|
|
|
2188
|
352
|
|
|
|
|
1166
|
my $pname = $self->{decl}{full_perl_name}; |
|
2189
|
352
|
|
|
|
|
2468
|
my $cname = $self->{decl}{full_C_name}; |
|
2190
|
|
|
|
|
|
|
|
|
2191
|
352
|
100
|
66
|
|
|
5516
|
if ( $self->{map_alias_name_to_value} |
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
2192
|
17
|
|
|
|
|
101
|
and keys %{ $self->{map_alias_name_to_value} }) |
|
2193
|
|
|
|
|
|
|
{ |
|
2194
|
|
|
|
|
|
|
# For the main XSUB and for each alias name, generate a newXS() call |
|
2195
|
|
|
|
|
|
|
# and 'XSANY.any_i32 = ix' line. |
|
2196
|
|
|
|
|
|
|
|
|
2197
|
17
|
|
|
|
|
29
|
foreach my $xname (sort keys |
|
2198
|
17
|
|
|
|
|
114
|
%{ $self->{map_alias_name_to_value} }) |
|
2199
|
|
|
|
|
|
|
{ |
|
2200
|
66
|
|
|
|
|
132
|
my $value = $self->{map_alias_name_to_value}{$xname}; |
|
2201
|
66
|
|
|
|
|
311
|
push(@code, $self->Q(<<"EOF")); |
|
2202
|
|
|
|
|
|
|
| cv = $newXS(\"$xname\", XS_$cname$file_arg$proto_arg); |
|
2203
|
|
|
|
|
|
|
| XSANY.any_i32 = $value; |
|
2204
|
|
|
|
|
|
|
EOF |
|
2205
|
66
|
|
|
|
|
190
|
$pxs->{need_boot_cv} = 1; |
|
2206
|
|
|
|
|
|
|
} |
|
2207
|
|
|
|
|
|
|
} |
|
2208
|
|
|
|
|
|
|
elsif ($self->{attributes}) { |
|
2209
|
|
|
|
|
|
|
# Generate a standard newXS() call, plus a single call to |
|
2210
|
|
|
|
|
|
|
# apply_attrs_string() call with the string of attributes. |
|
2211
|
4
|
|
|
|
|
13
|
my $attrs = "@{$self->{attributes}}"; |
|
|
4
|
|
|
|
|
35
|
|
|
2212
|
4
|
|
|
|
|
37
|
push(@code, $self->Q(<<"EOF")); |
|
2213
|
|
|
|
|
|
|
| cv = $newXS(\"$pname\", XS_$cname$file_arg$proto_arg); |
|
2214
|
|
|
|
|
|
|
| apply_attrs_string("$self->{PACKAGE_name}", cv, "$attrs", 0); |
|
2215
|
|
|
|
|
|
|
EOF |
|
2216
|
4
|
|
|
|
|
15
|
$pxs->{need_boot_cv} = 1; |
|
2217
|
|
|
|
|
|
|
} |
|
2218
|
|
|
|
|
|
|
elsif ( $self->{seen_INTERFACE} |
|
2219
|
|
|
|
|
|
|
or $self->{seen_INTERFACE_MACRO}) |
|
2220
|
|
|
|
|
|
|
{ |
|
2221
|
|
|
|
|
|
|
# For each interface name, generate both a newXS() and |
|
2222
|
|
|
|
|
|
|
# XSINTERFACE_FUNC_SET() call. |
|
2223
|
9
|
|
|
|
|
34
|
foreach my $yname (sort keys |
|
2224
|
9
|
|
|
|
|
84
|
%{ $self->{map_interface_name_short_to_original} }) |
|
2225
|
|
|
|
|
|
|
{ |
|
2226
|
11
|
|
|
|
|
52
|
my $value = $self->{map_interface_name_short_to_original}{$yname}; |
|
2227
|
11
|
50
|
|
|
|
108
|
$yname = "$self->{PACKAGE_name}\::$yname" unless $yname =~ /::/; |
|
2228
|
|
|
|
|
|
|
|
|
2229
|
11
|
|
|
|
|
37
|
my $macro = $self->{interface_macro_set}; |
|
2230
|
11
|
50
|
|
|
|
67
|
$macro = 'XSINTERFACE_FUNC_SET' unless defined $macro; |
|
2231
|
11
|
|
|
|
|
102
|
push(@code, $self->Q(<<"EOF")); |
|
2232
|
|
|
|
|
|
|
| cv = $newXS(\"$yname\", XS_$cname$file_arg$proto_arg); |
|
2233
|
|
|
|
|
|
|
| $macro(cv,$value); |
|
2234
|
|
|
|
|
|
|
EOF |
|
2235
|
11
|
|
|
|
|
52
|
$pxs->{need_boot_cv} = 1; |
|
2236
|
|
|
|
|
|
|
} |
|
2237
|
|
|
|
|
|
|
} |
|
2238
|
|
|
|
|
|
|
elsif ($newXS eq 'newXS_deffile'){ |
|
2239
|
|
|
|
|
|
|
# Modified default: generate a standard newXS() call; but |
|
2240
|
|
|
|
|
|
|
# work around the CPAN 'P5NCI' distribution doing: |
|
2241
|
|
|
|
|
|
|
# #undef newXS |
|
2242
|
|
|
|
|
|
|
# #define newXS ; |
|
2243
|
|
|
|
|
|
|
# by omitting the initial (void). |
|
2244
|
|
|
|
|
|
|
# XXX DAPM 2024: |
|
2245
|
|
|
|
|
|
|
# this branch was originally: "elsif ($newXS eq 'newXS')" |
|
2246
|
|
|
|
|
|
|
# but when the standard name for the newXS variant changed in |
|
2247
|
|
|
|
|
|
|
# xsubpp, it was changed here too. So this branch no longer actually |
|
2248
|
|
|
|
|
|
|
# handles a workaround for '#define newXS ;'. I also don't |
|
2249
|
|
|
|
|
|
|
# understand how just omitting the '(void)' fixed the problem. |
|
2250
|
277
|
|
|
|
|
1891
|
push(@code, |
|
2251
|
|
|
|
|
|
|
" $newXS(\"$pname\", XS_$cname$file_arg$proto_arg);\n"); |
|
2252
|
|
|
|
|
|
|
} |
|
2253
|
|
|
|
|
|
|
else { |
|
2254
|
|
|
|
|
|
|
# Default: generate a standard newXS() call |
|
2255
|
45
|
|
|
|
|
216
|
push(@code, |
|
2256
|
|
|
|
|
|
|
" (void)$newXS(\"$pname\", XS_$cname$file_arg$proto_arg);\n"); |
|
2257
|
|
|
|
|
|
|
} |
|
2258
|
|
|
|
|
|
|
|
|
2259
|
|
|
|
|
|
|
# For every overload operator, generate an additional newXS() |
|
2260
|
|
|
|
|
|
|
# call to add an alias such as "Foo::(<=>" for this XSUB. |
|
2261
|
|
|
|
|
|
|
|
|
2262
|
352
|
|
|
|
|
709
|
for my $operator (sort keys %{ $self->{overload_name_seen} }) |
|
|
352
|
|
|
|
|
1823
|
|
|
2263
|
|
|
|
|
|
|
{ |
|
2264
|
13
|
|
|
|
|
35
|
my $overload = "$self->{PACKAGE_name}\::($operator"; |
|
2265
|
13
|
|
|
|
|
53
|
push(@code, |
|
2266
|
|
|
|
|
|
|
" (void)$newXS(\"$overload\", XS_$cname$file_arg$proto_arg);\n"); |
|
2267
|
|
|
|
|
|
|
} |
|
2268
|
|
|
|
|
|
|
|
|
2269
|
352
|
|
|
|
|
1316
|
return \@code, []; |
|
2270
|
|
|
|
|
|
|
} |
|
2271
|
|
|
|
|
|
|
|
|
2272
|
|
|
|
|
|
|
|
|
2273
|
|
|
|
|
|
|
# ====================================================================== |
|
2274
|
|
|
|
|
|
|
|
|
2275
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::xsub_decl; |
|
2276
|
|
|
|
|
|
|
|
|
2277
|
|
|
|
|
|
|
# Parse and store the complete declaration part of an XSUB, including |
|
2278
|
|
|
|
|
|
|
# its parameters, name and return type. |
|
2279
|
|
|
|
|
|
|
|
|
2280
|
19
|
|
|
19
|
|
107
|
BEGIN { $build_subclass->( |
|
2281
|
|
|
|
|
|
|
'return_type', # ReturnType object representing e.g "NO_OUTPUT char *" |
|
2282
|
|
|
|
|
|
|
'params', # Params object representing e.g "a, int b, c=0" |
|
2283
|
|
|
|
|
|
|
'class', # Str: the 'Foo::Bar' part of an XSUB's name; |
|
2284
|
|
|
|
|
|
|
# - if defined, this is a C++ method |
|
2285
|
|
|
|
|
|
|
'name', # Str: the 'foo' XSUB name |
|
2286
|
|
|
|
|
|
|
'full_perl_name', # Str: the 'Foo::Bar::foo' perl XSUB name |
|
2287
|
|
|
|
|
|
|
'full_C_name', # Str: the 'Foo__Bar__foo' C XSUB name |
|
2288
|
|
|
|
|
|
|
'is_const', # Bool: declaration had postfix C++ 'const' modifier |
|
2289
|
|
|
|
|
|
|
)}; |
|
2290
|
|
|
|
|
|
|
|
|
2291
|
|
|
|
|
|
|
|
|
2292
|
|
|
|
|
|
|
# Parse the XSUB's declaration - i.e. return type, name and parameters. |
|
2293
|
|
|
|
|
|
|
|
|
2294
|
|
|
|
|
|
|
sub parse { |
|
2295
|
366
|
|
|
366
|
|
971
|
my __PACKAGE__ $self = shift; |
|
2296
|
366
|
|
|
|
|
731
|
my ExtUtils::ParseXS $pxs = shift; |
|
2297
|
366
|
|
|
|
|
641
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
2298
|
|
|
|
|
|
|
|
|
2299
|
|
|
|
|
|
|
|
|
2300
|
366
|
|
|
|
|
1538
|
$self->SUPER::parse($pxs); # set file/line_no |
|
2301
|
|
|
|
|
|
|
|
|
2302
|
|
|
|
|
|
|
# Parse return type |
|
2303
|
|
|
|
|
|
|
|
|
2304
|
366
|
|
|
|
|
15228
|
my $return_type = ExtUtils::ParseXS::Node::ReturnType->new(); |
|
2305
|
|
|
|
|
|
|
|
|
2306
|
366
|
100
|
|
|
|
1425
|
$return_type->parse($pxs, $xsub) |
|
2307
|
|
|
|
|
|
|
or return; |
|
2308
|
|
|
|
|
|
|
|
|
2309
|
365
|
|
|
|
|
1225
|
$self->{return_type} = $return_type; |
|
2310
|
365
|
|
|
|
|
833
|
push @{$self->{kids}}, $return_type; |
|
|
365
|
|
|
|
|
1372
|
|
|
2311
|
|
|
|
|
|
|
|
|
2312
|
|
|
|
|
|
|
# Decompose the function declaration: match a line like |
|
2313
|
|
|
|
|
|
|
# Some::Class::foo_bar( args ) const ; |
|
2314
|
|
|
|
|
|
|
# ----------- ------- ---- ----- -- |
|
2315
|
|
|
|
|
|
|
# $1 $2 $3 $4 $5 |
|
2316
|
|
|
|
|
|
|
# |
|
2317
|
|
|
|
|
|
|
# where everything except $2 and $3 are optional and the 'const' |
|
2318
|
|
|
|
|
|
|
# is for C++ functions. |
|
2319
|
|
|
|
|
|
|
|
|
2320
|
365
|
|
|
|
|
594
|
my $func_header = shift(@{ $pxs->{line} }); |
|
|
365
|
|
|
|
|
1258
|
|
|
2321
|
365
|
100
|
|
|
|
4524
|
$pxs->blurt("Error: cannot parse function definition from '$func_header'"), |
|
2322
|
|
|
|
|
|
|
return |
|
2323
|
|
|
|
|
|
|
unless $func_header =~ |
|
2324
|
|
|
|
|
|
|
/^(?:([\w:]*)::)?(\w+)\s*\(\s*(.*?)\s*\)\s*(const)?\s*(;\s*)?$/s; |
|
2325
|
|
|
|
|
|
|
|
|
2326
|
363
|
|
|
|
|
5824
|
my ($class, $name, $params_text, $const) = ($1, $2, $3, $4); |
|
2327
|
|
|
|
|
|
|
|
|
2328
|
363
|
100
|
100
|
|
|
1460
|
if (defined $const and !defined $class) { |
|
2329
|
1
|
|
|
|
|
26
|
$pxs->blurt("const modifier only allowed on XSUBs which are C++ methods"); |
|
2330
|
1
|
|
|
|
|
8
|
undef $const; |
|
2331
|
|
|
|
|
|
|
} |
|
2332
|
|
|
|
|
|
|
|
|
2333
|
363
|
100
|
100
|
|
|
1666
|
if ($return_type->{static} and !defined $class) |
|
2334
|
|
|
|
|
|
|
{ |
|
2335
|
2
|
|
|
|
|
25
|
$pxs->Warn( "Warning: ignoring 'static' type modifier:" |
|
2336
|
|
|
|
|
|
|
. " only valid with an XSUB name which includes a class"); |
|
2337
|
2
|
|
|
|
|
12
|
$return_type->{static} = 0; |
|
2338
|
|
|
|
|
|
|
} |
|
2339
|
|
|
|
|
|
|
|
|
2340
|
363
|
|
|
|
|
6418
|
(my $full_pname = $name) =~ |
|
2341
|
|
|
|
|
|
|
s/^($pxs->{PREFIX_pattern})?/$pxs->{PACKAGE_class}/; |
|
2342
|
|
|
|
|
|
|
|
|
2343
|
363
|
|
|
|
|
3663
|
(my $clean_func_name = $name) =~ s/^$pxs->{PREFIX_pattern}//; |
|
2344
|
|
|
|
|
|
|
|
|
2345
|
363
|
|
|
|
|
1151
|
my $full_cname = "$pxs->{PACKAGE_C_name}_$clean_func_name"; |
|
2346
|
363
|
50
|
|
|
|
1399
|
$full_cname = $ExtUtils::ParseXS::VMS_SymSet->addsym($full_cname) |
|
2347
|
|
|
|
|
|
|
if $ExtUtils::ParseXS::Is_VMS; |
|
2348
|
|
|
|
|
|
|
|
|
2349
|
363
|
|
|
|
|
1041
|
$self->{class} = $class; |
|
2350
|
363
|
|
|
|
|
991
|
$self->{is_const} = defined $const; |
|
2351
|
363
|
|
|
|
|
957
|
$self->{name} = $name; |
|
2352
|
363
|
|
|
|
|
932
|
$self->{full_perl_name} = $full_pname; |
|
2353
|
363
|
|
|
|
|
948
|
$self->{full_C_name} = $full_cname; |
|
2354
|
|
|
|
|
|
|
|
|
2355
|
|
|
|
|
|
|
# At this point, supposing that the input so far was: |
|
2356
|
|
|
|
|
|
|
# |
|
2357
|
|
|
|
|
|
|
# MODULE = ... PACKAGE = BAR::BAZ PREFIX = foo_ |
|
2358
|
|
|
|
|
|
|
# int |
|
2359
|
|
|
|
|
|
|
# Some::Class::foo_bar(param1, param2, param3) const ; |
|
2360
|
|
|
|
|
|
|
# |
|
2361
|
|
|
|
|
|
|
# we should have: |
|
2362
|
|
|
|
|
|
|
# |
|
2363
|
|
|
|
|
|
|
# $self->{return_type} an object holding "int" |
|
2364
|
|
|
|
|
|
|
# $self->{class} "Some::Class" |
|
2365
|
|
|
|
|
|
|
# $self->{is_const} TRUE |
|
2366
|
|
|
|
|
|
|
# $self->{name} "foo_bar" |
|
2367
|
|
|
|
|
|
|
# $self->{full_perl_name} "BAR::BAZ::bar" |
|
2368
|
|
|
|
|
|
|
# $self->{full_C_name} "BAR__BAZ_bar" |
|
2369
|
|
|
|
|
|
|
# $params_text "param1, param2, param3" |
|
2370
|
|
|
|
|
|
|
|
|
2371
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
2372
|
|
|
|
|
|
|
# Process the XSUB's signature. |
|
2373
|
|
|
|
|
|
|
# |
|
2374
|
|
|
|
|
|
|
# Split $params_text into parameters, parse them, and store them as |
|
2375
|
|
|
|
|
|
|
# Node::Param objects within the Node::Params object. |
|
2376
|
|
|
|
|
|
|
|
|
2377
|
363
|
|
|
|
|
4184
|
my $params = $self->{params} = ExtUtils::ParseXS::Node::Params->new(); |
|
2378
|
|
|
|
|
|
|
|
|
2379
|
363
|
50
|
|
|
|
4698
|
$params->parse($pxs, $xsub, $params_text) |
|
2380
|
|
|
|
|
|
|
or return; |
|
2381
|
363
|
|
|
|
|
1013
|
$self->{params} = $params; |
|
2382
|
363
|
|
|
|
|
768
|
push @{$self->{kids}}, $params; |
|
|
363
|
|
|
|
|
1008
|
|
|
2383
|
|
|
|
|
|
|
|
|
2384
|
|
|
|
|
|
|
# How many OUTLIST SVs get returned in addition to RETVAL |
|
2385
|
|
|
|
|
|
|
$xsub->{XSRETURN_count_extra} = |
|
2386
|
|
|
|
|
|
|
grep { defined $_->{in_out} |
|
2387
|
656
|
100
|
|
|
|
4234
|
&& $_->{in_out} =~ /OUTLIST$/ |
|
2388
|
|
|
|
|
|
|
} |
|
2389
|
363
|
|
|
|
|
703
|
@{$self->{params}{kids}}; |
|
|
363
|
|
|
|
|
1163
|
|
|
2390
|
363
|
|
|
|
|
12968
|
1; |
|
2391
|
|
|
|
|
|
|
} |
|
2392
|
|
|
|
|
|
|
|
|
2393
|
|
|
|
|
|
|
|
|
2394
|
|
|
|
|
|
|
# ====================================================================== |
|
2395
|
|
|
|
|
|
|
|
|
2396
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::ReturnType; |
|
2397
|
|
|
|
|
|
|
|
|
2398
|
|
|
|
|
|
|
# Handle the 'return type' line at the start of an XSUB. |
|
2399
|
|
|
|
|
|
|
# It mainly consists of the return type, but there are also |
|
2400
|
|
|
|
|
|
|
# extra keywords to process, such as NO_RETURN. |
|
2401
|
|
|
|
|
|
|
|
|
2402
|
19
|
|
|
19
|
|
1595
|
BEGIN { $build_subclass->( |
|
2403
|
|
|
|
|
|
|
'type', # Str: the XSUB's C return type |
|
2404
|
|
|
|
|
|
|
'no_output', # Bool: saw 'NO_OUTPUT' |
|
2405
|
|
|
|
|
|
|
'extern_C', # Bool: saw 'extern C' |
|
2406
|
|
|
|
|
|
|
'static', # Bool: saw 'static' |
|
2407
|
|
|
|
|
|
|
'use_early_targ', # Bool: emit an early dTARG for backcompat |
|
2408
|
|
|
|
|
|
|
)}; |
|
2409
|
|
|
|
|
|
|
|
|
2410
|
|
|
|
|
|
|
|
|
2411
|
|
|
|
|
|
|
# Extract out the return type declaration from the start of an XSUB. |
|
2412
|
|
|
|
|
|
|
# If the declaration and function name are on the same line, delete the |
|
2413
|
|
|
|
|
|
|
# type part; else pop the first line. |
|
2414
|
|
|
|
|
|
|
|
|
2415
|
|
|
|
|
|
|
sub parse { |
|
2416
|
366
|
|
|
366
|
|
779
|
my __PACKAGE__ $self = shift; |
|
2417
|
366
|
|
|
|
|
900
|
my ExtUtils::ParseXS $pxs = shift; |
|
2418
|
366
|
|
|
|
|
729
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
2419
|
|
|
|
|
|
|
|
|
2420
|
366
|
|
|
|
|
1320
|
$self->SUPER::parse($pxs); # set file/line_no |
|
2421
|
|
|
|
|
|
|
|
|
2422
|
|
|
|
|
|
|
# Whitespace-tidy the line containing the return type, plus possibly |
|
2423
|
|
|
|
|
|
|
# the function name and arguments too. |
|
2424
|
|
|
|
|
|
|
# XXX Tidying the latter was probably an unintended side-effect of |
|
2425
|
|
|
|
|
|
|
# later allowing the return type and function to be on the same line. |
|
2426
|
|
|
|
|
|
|
|
|
2427
|
366
|
|
|
|
|
598
|
my $line = shift @{$pxs->{line}}; |
|
|
366
|
|
|
|
|
1891
|
|
|
2428
|
366
|
|
|
|
|
1777
|
$line = ExtUtils::Typemaps::tidy_type($line); |
|
2429
|
366
|
|
|
|
|
1042
|
my $type = $line; |
|
2430
|
|
|
|
|
|
|
|
|
2431
|
366
|
100
|
|
|
|
1460
|
$self->{no_output} = 1 if $type =~ s/^NO_OUTPUT\s+//; |
|
2432
|
|
|
|
|
|
|
|
|
2433
|
|
|
|
|
|
|
# Allow one-line declarations. This splits a single line like: |
|
2434
|
|
|
|
|
|
|
# int foo(....) |
|
2435
|
|
|
|
|
|
|
# into the two lines: |
|
2436
|
|
|
|
|
|
|
# int |
|
2437
|
|
|
|
|
|
|
# foo(...) |
|
2438
|
|
|
|
|
|
|
# |
|
2439
|
|
|
|
|
|
|
# Note that this splits both K&R-style 'foo(a, b)' and ANSI-style |
|
2440
|
|
|
|
|
|
|
# 'foo(int a, int b)'. I don't know whether the former was intentional. |
|
2441
|
|
|
|
|
|
|
# As of 5.40.0, the docs don't suggest that a 1-line K&R is legal. Was |
|
2442
|
|
|
|
|
|
|
# added by 11416672a16, first appeared in 5.6.0. |
|
2443
|
|
|
|
|
|
|
# |
|
2444
|
|
|
|
|
|
|
# NB: $pxs->{config_allow_argtypes} is false if xsubpp was invoked |
|
2445
|
|
|
|
|
|
|
# with -noargtypes |
|
2446
|
|
|
|
|
|
|
|
|
2447
|
40
|
|
|
|
|
260
|
unshift @{$pxs->{line}}, $2 |
|
2448
|
|
|
|
|
|
|
if $pxs->{config_allow_argtypes} |
|
2449
|
366
|
100
|
100
|
|
|
5269
|
and $type =~ s/^(.*?\w.*?) \s* \b (\w+\s*\(.*)/$1/sx; |
|
2450
|
|
|
|
|
|
|
|
|
2451
|
|
|
|
|
|
|
# a function definition needs at least 2 lines |
|
2452
|
366
|
100
|
|
|
|
737
|
unless (@{$pxs->{line}}) { |
|
|
366
|
|
|
|
|
1305
|
|
|
2453
|
1
|
|
|
|
|
22
|
$pxs->blurt("Error: function definition too short '$line'"); |
|
2454
|
1
|
|
|
|
|
35
|
return; |
|
2455
|
|
|
|
|
|
|
} |
|
2456
|
|
|
|
|
|
|
|
|
2457
|
365
|
100
|
|
|
|
1168
|
$self->{extern_C} = 1 if $type =~ s/^extern "C"\s+//; |
|
2458
|
365
|
100
|
|
|
|
1108
|
$self->{static} = 1 if $type =~ s/^static\s+//; |
|
2459
|
365
|
|
|
|
|
1069
|
$self->{type} = $type; |
|
2460
|
|
|
|
|
|
|
|
|
2461
|
365
|
100
|
|
|
|
1766
|
if ($type ne "void") { |
|
2462
|
|
|
|
|
|
|
# Set a flag indicating that, for backwards-compatibility reasons, |
|
2463
|
|
|
|
|
|
|
# early dXSTARG should be emitted. |
|
2464
|
|
|
|
|
|
|
# Recent code emits a dXSTARG in a tighter scope and under |
|
2465
|
|
|
|
|
|
|
# additional circumstances, but some XS code relies on TARG |
|
2466
|
|
|
|
|
|
|
# having been declared. So continue to declare it early under |
|
2467
|
|
|
|
|
|
|
# the original circumstances. |
|
2468
|
210
|
|
|
|
|
1265
|
my $outputmap = $pxs->{typemaps_object}->get_outputmap(ctype => $type); |
|
2469
|
|
|
|
|
|
|
|
|
2470
|
210
|
100
|
66
|
|
|
3020
|
if ( $pxs->{config_optimize} |
|
|
|
|
100
|
|
|
|
|
|
2471
|
|
|
|
|
|
|
and $outputmap |
|
2472
|
|
|
|
|
|
|
and $outputmap->targetable_legacy) |
|
2473
|
|
|
|
|
|
|
{ |
|
2474
|
179
|
|
|
|
|
656
|
$self->{use_early_targ} = 1; |
|
2475
|
|
|
|
|
|
|
} |
|
2476
|
|
|
|
|
|
|
} |
|
2477
|
|
|
|
|
|
|
|
|
2478
|
365
|
|
|
|
|
1772
|
1; |
|
2479
|
|
|
|
|
|
|
} |
|
2480
|
|
|
|
|
|
|
|
|
2481
|
|
|
|
|
|
|
|
|
2482
|
|
|
|
|
|
|
# ====================================================================== |
|
2483
|
|
|
|
|
|
|
|
|
2484
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::Param; |
|
2485
|
|
|
|
|
|
|
|
|
2486
|
|
|
|
|
|
|
# Node subclass which holds the state of one XSUB parameter, based on the |
|
2487
|
|
|
|
|
|
|
# just the XSUB's signature. See also the Node::IO_Param subclass, which |
|
2488
|
|
|
|
|
|
|
# augments the parameter declaration with info from INPUT and OUTPUT |
|
2489
|
|
|
|
|
|
|
# lines. |
|
2490
|
|
|
|
|
|
|
|
|
2491
|
19
|
|
|
19
|
|
139
|
BEGIN { $build_subclass->( |
|
2492
|
|
|
|
|
|
|
# values derived from the XSUB's signature |
|
2493
|
|
|
|
|
|
|
'in_out', # Str: The IN/OUT/OUTLIST etc value (if any) |
|
2494
|
|
|
|
|
|
|
'var', # Str: the name of the parameter |
|
2495
|
|
|
|
|
|
|
'arg_num', # Int The arg number (starting at 1) mapped to this param |
|
2496
|
|
|
|
|
|
|
'default', # Str: default value (if any) |
|
2497
|
|
|
|
|
|
|
'default_usage', # Str: how to report default value in "usage:..." error |
|
2498
|
|
|
|
|
|
|
'is_ansi', # Bool: param's type was specified in signature |
|
2499
|
|
|
|
|
|
|
'is_length', # Bool: param is declared as 'length(foo)' in signature |
|
2500
|
|
|
|
|
|
|
'has_length', # Bool: this param has a matching 'length(foo)' |
|
2501
|
|
|
|
|
|
|
# parameter in the signature |
|
2502
|
|
|
|
|
|
|
'len_name' , # Str: the 'foo' in 'length(foo)' in signature |
|
2503
|
|
|
|
|
|
|
'is_synthetic', # Bool: var like 'THIS': we pretend it was in the sig |
|
2504
|
|
|
|
|
|
|
|
|
2505
|
|
|
|
|
|
|
# values derived from both the XSUB's signature and/or INPUT line |
|
2506
|
|
|
|
|
|
|
'type', # Str: The C type of the parameter |
|
2507
|
|
|
|
|
|
|
'no_init', # Bool: don't initialise the parameter |
|
2508
|
|
|
|
|
|
|
|
|
2509
|
|
|
|
|
|
|
# derived values calculated later |
|
2510
|
|
|
|
|
|
|
'proto', # Str: overridden prototype char(s) (if any) from typemap |
|
2511
|
|
|
|
|
|
|
)}; |
|
2512
|
|
|
|
|
|
|
|
|
2513
|
|
|
|
|
|
|
|
|
2514
|
|
|
|
|
|
|
# Parse a parameter. A parameter is of the general form: |
|
2515
|
|
|
|
|
|
|
# |
|
2516
|
|
|
|
|
|
|
# OUT char* foo = expression |
|
2517
|
|
|
|
|
|
|
# |
|
2518
|
|
|
|
|
|
|
# where: |
|
2519
|
|
|
|
|
|
|
# IN/OUT/OUTLIST etc are only allowed under |
|
2520
|
|
|
|
|
|
|
# $pxs->{config_allow_inout} |
|
2521
|
|
|
|
|
|
|
# |
|
2522
|
|
|
|
|
|
|
# a C type is only allowed under |
|
2523
|
|
|
|
|
|
|
# $pxs->{config_allow_argtypes} |
|
2524
|
|
|
|
|
|
|
# |
|
2525
|
|
|
|
|
|
|
# foo can be a plain C variable name, or can be |
|
2526
|
|
|
|
|
|
|
# length(foo) but only under $pxs->{config_allow_argtypes} |
|
2527
|
|
|
|
|
|
|
# |
|
2528
|
|
|
|
|
|
|
# = default default value - only allowed under |
|
2529
|
|
|
|
|
|
|
# $pxs->{config_allow_argtypes} |
|
2530
|
|
|
|
|
|
|
|
|
2531
|
|
|
|
|
|
|
sub parse { |
|
2532
|
451
|
|
|
451
|
|
921
|
my __PACKAGE__ $self = shift; |
|
2533
|
451
|
|
|
|
|
773
|
my ExtUtils::ParseXS $pxs = shift; |
|
2534
|
451
|
|
|
|
|
772
|
my $params = shift; # parent Params |
|
2535
|
451
|
|
|
|
|
1065
|
my $param_text = shift; |
|
2536
|
|
|
|
|
|
|
|
|
2537
|
451
|
|
|
|
|
1528
|
$self->SUPER::parse($pxs); # set file/line_no |
|
2538
|
451
|
|
|
|
|
987
|
$_ = $param_text; |
|
2539
|
|
|
|
|
|
|
|
|
2540
|
|
|
|
|
|
|
# Decompose parameter into its components. |
|
2541
|
|
|
|
|
|
|
# Note that $name can be either 'foo' or 'length(foo)' |
|
2542
|
|
|
|
|
|
|
|
|
2543
|
451
|
|
|
|
|
6207
|
my ($out_type, $type, $name, $sp1, $sp2, $default) = |
|
2544
|
|
|
|
|
|
|
/^ |
|
2545
|
|
|
|
|
|
|
(?: |
|
2546
|
|
|
|
|
|
|
(IN|IN_OUT|IN_OUTLIST|OUT|OUTLIST) |
|
2547
|
|
|
|
|
|
|
\b\s* |
|
2548
|
|
|
|
|
|
|
)? |
|
2549
|
|
|
|
|
|
|
(.*?) # optional type |
|
2550
|
|
|
|
|
|
|
\s* |
|
2551
|
|
|
|
|
|
|
\b |
|
2552
|
|
|
|
|
|
|
( \w+ # var |
|
2553
|
|
|
|
|
|
|
| length\( \s*\w+\s* \) # length(var) |
|
2554
|
|
|
|
|
|
|
) |
|
2555
|
|
|
|
|
|
|
(?: |
|
2556
|
|
|
|
|
|
|
(\s*) = (\s*) ( .*?) # default expr |
|
2557
|
|
|
|
|
|
|
)? |
|
2558
|
|
|
|
|
|
|
\s* |
|
2559
|
|
|
|
|
|
|
$ |
|
2560
|
|
|
|
|
|
|
/x; |
|
2561
|
|
|
|
|
|
|
|
|
2562
|
451
|
100
|
|
|
|
1747
|
unless (defined $name) { |
|
2563
|
5
|
100
|
|
|
|
185
|
if (/^ SV \s* \* $/x) { |
|
2564
|
|
|
|
|
|
|
# special-case SV* as a placeholder for backwards |
|
2565
|
|
|
|
|
|
|
# compatibility. |
|
2566
|
4
|
|
|
|
|
46
|
$self->{var} = 'SV *'; |
|
2567
|
4
|
|
|
|
|
50
|
return 1; |
|
2568
|
|
|
|
|
|
|
} |
|
2569
|
1
|
|
|
|
|
11
|
$pxs->blurt("Error: unparseable XSUB parameter: '$_'"); |
|
2570
|
1
|
|
|
|
|
16
|
return; |
|
2571
|
|
|
|
|
|
|
} |
|
2572
|
|
|
|
|
|
|
|
|
2573
|
446
|
100
|
66
|
|
|
4116
|
undef $type unless length($type) && $type =~ /\S/; |
|
2574
|
446
|
|
|
|
|
1758
|
$self->{var} = $name; |
|
2575
|
|
|
|
|
|
|
|
|
2576
|
|
|
|
|
|
|
# Check for duplicates |
|
2577
|
|
|
|
|
|
|
|
|
2578
|
446
|
|
|
|
|
1160
|
my $old_param = $params->{names}{$name}; |
|
2579
|
446
|
100
|
|
|
|
1337
|
if ($old_param) { |
|
2580
|
|
|
|
|
|
|
# Normally a dup parameter is an error, but we allow RETVAL as |
|
2581
|
|
|
|
|
|
|
# a real parameter, which overrides the synthetic one which |
|
2582
|
|
|
|
|
|
|
# was added earlier if the return value isn't void. |
|
2583
|
29
|
100
|
100
|
|
|
441
|
if ( $name eq 'RETVAL' |
|
|
|
|
100
|
|
|
|
|
|
2584
|
|
|
|
|
|
|
and $old_param->{is_synthetic} |
|
2585
|
|
|
|
|
|
|
and !defined $old_param->{arg_num}) |
|
2586
|
|
|
|
|
|
|
{ |
|
2587
|
|
|
|
|
|
|
# RETVAL is currently fully synthetic. Now that it has |
|
2588
|
|
|
|
|
|
|
# been declared as a parameter too, override any implicit |
|
2589
|
|
|
|
|
|
|
# RETVAL declaration. Delete the original param from the |
|
2590
|
|
|
|
|
|
|
# param list and later re-add it as a parameter in its |
|
2591
|
|
|
|
|
|
|
# correct position. |
|
2592
|
16
|
|
|
|
|
78
|
@{$params->{kids}} = grep $_ != $old_param, @{$params->{kids}}; |
|
|
16
|
|
|
|
|
54
|
|
|
|
16
|
|
|
|
|
102
|
|
|
2593
|
|
|
|
|
|
|
# If the param declaration includes a type, it becomes a |
|
2594
|
|
|
|
|
|
|
# real parameter. Otherwise the param is kept as |
|
2595
|
|
|
|
|
|
|
# 'semi-real' (synthetic, but with an arg_num) until such |
|
2596
|
|
|
|
|
|
|
# time as it gets a type set in INPUT, which would remove |
|
2597
|
|
|
|
|
|
|
# the synthetic/no_init. |
|
2598
|
16
|
100
|
|
|
|
115
|
%$self = %$old_param unless defined $type; |
|
2599
|
|
|
|
|
|
|
} |
|
2600
|
|
|
|
|
|
|
else { |
|
2601
|
13
|
|
|
|
|
218
|
$pxs->blurt( |
|
2602
|
|
|
|
|
|
|
"Error: duplicate definition of parameter '$name' ignored"); |
|
2603
|
13
|
|
|
|
|
218
|
return; |
|
2604
|
|
|
|
|
|
|
} |
|
2605
|
|
|
|
|
|
|
} |
|
2606
|
|
|
|
|
|
|
|
|
2607
|
|
|
|
|
|
|
# Process optional IN/OUT etc modifier |
|
2608
|
|
|
|
|
|
|
|
|
2609
|
433
|
100
|
|
|
|
1121
|
if (defined $out_type) { |
|
2610
|
59
|
100
|
|
|
|
452
|
if ($pxs->{config_allow_inout}) { |
|
2611
|
58
|
100
|
|
|
|
455
|
$out_type = $out_type eq 'IN' ? '' : $out_type; |
|
2612
|
|
|
|
|
|
|
} |
|
2613
|
|
|
|
|
|
|
else { |
|
2614
|
1
|
|
|
|
|
13
|
$pxs->blurt("Error: parameter IN/OUT modifier not allowed under -noinout"); |
|
2615
|
|
|
|
|
|
|
} |
|
2616
|
|
|
|
|
|
|
} |
|
2617
|
|
|
|
|
|
|
else { |
|
2618
|
374
|
|
|
|
|
1275
|
$out_type = ''; |
|
2619
|
|
|
|
|
|
|
} |
|
2620
|
|
|
|
|
|
|
|
|
2621
|
|
|
|
|
|
|
# Process optional type |
|
2622
|
|
|
|
|
|
|
|
|
2623
|
433
|
100
|
100
|
|
|
2937
|
if (defined($type) && !$pxs->{config_allow_argtypes}) { |
|
2624
|
1
|
|
|
|
|
22
|
$pxs->blurt("Error: parameter type not allowed under -noargtypes"); |
|
2625
|
1
|
|
|
|
|
5
|
undef $type; |
|
2626
|
|
|
|
|
|
|
} |
|
2627
|
|
|
|
|
|
|
|
|
2628
|
|
|
|
|
|
|
# Process 'length(foo)' pseudo-parameter |
|
2629
|
|
|
|
|
|
|
|
|
2630
|
433
|
|
|
|
|
928
|
my $is_length; |
|
2631
|
|
|
|
|
|
|
my $len_name; |
|
2632
|
|
|
|
|
|
|
|
|
2633
|
433
|
100
|
|
|
|
1202
|
if ($name =~ /^length\( \s* (\w+) \s* \)\z/x) { |
|
2634
|
15
|
100
|
|
|
|
105
|
if ($pxs->{config_allow_argtypes}) { |
|
2635
|
14
|
|
|
|
|
98
|
$len_name = $1; |
|
2636
|
14
|
|
|
|
|
50
|
$is_length = 1; |
|
2637
|
14
|
100
|
|
|
|
76
|
if (defined $default) { |
|
2638
|
1
|
|
|
|
|
25
|
$pxs->blurt( "Error: default value not allowed on " |
|
2639
|
|
|
|
|
|
|
. "length() parameter '$len_name'"); |
|
2640
|
1
|
|
|
|
|
8
|
undef $default; |
|
2641
|
|
|
|
|
|
|
} |
|
2642
|
|
|
|
|
|
|
} |
|
2643
|
|
|
|
|
|
|
else { |
|
2644
|
1
|
|
|
|
|
16
|
$pxs->blurt( "Error: length() pseudo-parameter not allowed " |
|
2645
|
|
|
|
|
|
|
. "under -noargtypes"); |
|
2646
|
|
|
|
|
|
|
} |
|
2647
|
|
|
|
|
|
|
} |
|
2648
|
|
|
|
|
|
|
|
|
2649
|
|
|
|
|
|
|
# Handle ANSI params: those which have a type or 'length(s)', |
|
2650
|
|
|
|
|
|
|
# and which thus don't need a matching INPUT line. |
|
2651
|
|
|
|
|
|
|
|
|
2652
|
433
|
100
|
100
|
|
|
1890
|
if (defined $type or $is_length) { # 'int foo' or 'length(foo)' |
|
2653
|
287
|
|
|
|
|
2307
|
@$self{qw(type is_ansi)} = ($type, 1); |
|
2654
|
|
|
|
|
|
|
|
|
2655
|
287
|
100
|
|
|
|
1155
|
if ($is_length) { |
|
2656
|
14
|
|
|
|
|
72
|
$self->{no_init} = 1; |
|
2657
|
14
|
|
|
|
|
74
|
$self->{is_length} = 1; |
|
2658
|
14
|
|
|
|
|
39
|
$self->{len_name} = $len_name; |
|
2659
|
|
|
|
|
|
|
} |
|
2660
|
|
|
|
|
|
|
} |
|
2661
|
|
|
|
|
|
|
|
|
2662
|
433
|
100
|
|
|
|
1138
|
$self->{in_out} = $out_type if length $out_type; |
|
2663
|
433
|
100
|
|
|
|
1163
|
$self->{no_init} = 1 if $out_type =~ /^OUT/; |
|
2664
|
|
|
|
|
|
|
|
|
2665
|
|
|
|
|
|
|
# Process the default expression, including making the text |
|
2666
|
|
|
|
|
|
|
# to be used in "usage: ..." error messages. |
|
2667
|
|
|
|
|
|
|
|
|
2668
|
433
|
|
|
|
|
1017
|
my $report_def = ''; |
|
2669
|
433
|
100
|
|
|
|
1093
|
if (defined $default) { |
|
2670
|
|
|
|
|
|
|
# The default expression for reporting usage. For backcompat, |
|
2671
|
|
|
|
|
|
|
# sometimes preserve the spaces either side of the '=' |
|
2672
|
29
|
100
|
66
|
|
|
314
|
$report_def = ((defined $type or $is_length) ? '' : $sp1) |
|
2673
|
|
|
|
|
|
|
. "=$sp2$default"; |
|
2674
|
29
|
|
|
|
|
99
|
$self->{default_usage} = $report_def; |
|
2675
|
29
|
|
|
|
|
73
|
$self->{default} = $default; |
|
2676
|
|
|
|
|
|
|
} |
|
2677
|
|
|
|
|
|
|
|
|
2678
|
433
|
|
|
|
|
1534
|
1; |
|
2679
|
|
|
|
|
|
|
} |
|
2680
|
|
|
|
|
|
|
|
|
2681
|
|
|
|
|
|
|
|
|
2682
|
|
|
|
|
|
|
# Set the 'proto' field of the param. This is based on the value, if any, |
|
2683
|
|
|
|
|
|
|
# of the proto method of the typemap for that param's type. It will |
|
2684
|
|
|
|
|
|
|
# typically be a single character like '$'. |
|
2685
|
|
|
|
|
|
|
# |
|
2686
|
|
|
|
|
|
|
# Note that params can have different types (and thus different proto |
|
2687
|
|
|
|
|
|
|
# chars) in different CASE branches. |
|
2688
|
|
|
|
|
|
|
|
|
2689
|
|
|
|
|
|
|
sub set_proto { |
|
2690
|
689
|
|
|
689
|
|
1375
|
my __PACKAGE__ $self = shift; |
|
2691
|
689
|
|
|
|
|
1178
|
my ExtUtils::ParseXS $pxs = shift; |
|
2692
|
|
|
|
|
|
|
|
|
2693
|
|
|
|
|
|
|
# only needed for real args that the caller may pass. |
|
2694
|
689
|
100
|
|
|
|
1858
|
return unless $self->{arg_num}; |
|
2695
|
423
|
|
|
|
|
1145
|
my $type = $self->{type}; |
|
2696
|
423
|
100
|
|
|
|
990
|
return unless defined $type; |
|
2697
|
384
|
|
|
|
|
1254
|
my $typemap = $pxs->{typemaps_object}->get_typemap(ctype => $type); |
|
2698
|
384
|
100
|
|
|
|
962
|
return unless defined $typemap; |
|
2699
|
379
|
|
|
|
|
1260
|
my $p = $typemap->proto; |
|
2700
|
379
|
100
|
66
|
|
|
2993
|
return unless defined $p && length $p; |
|
2701
|
4
|
|
|
|
|
25
|
$self->{proto} = $p; |
|
2702
|
|
|
|
|
|
|
} |
|
2703
|
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
|
|
2705
|
|
|
|
|
|
|
# ====================================================================== |
|
2706
|
|
|
|
|
|
|
|
|
2707
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::IO_Param; |
|
2708
|
|
|
|
|
|
|
|
|
2709
|
|
|
|
|
|
|
# Subclass of Node::Param which holds the state of one XSUB parameter, |
|
2710
|
|
|
|
|
|
|
# based on the XSUB's signature, but also augmented by info from INPUT or |
|
2711
|
|
|
|
|
|
|
# OUTPUT lines |
|
2712
|
|
|
|
|
|
|
|
|
2713
|
19
|
|
|
19
|
|
107
|
BEGIN { $build_subclass->(-parent => 'Param', |
|
2714
|
|
|
|
|
|
|
# values derived from the XSUB's INPUT line |
|
2715
|
|
|
|
|
|
|
|
|
2716
|
|
|
|
|
|
|
'init_op', # Str: initialisation type: one of =/+/; |
|
2717
|
|
|
|
|
|
|
'init', # Str: initialisation template code |
|
2718
|
|
|
|
|
|
|
'is_addr', # Bool: INPUT var declared as '&foo' |
|
2719
|
|
|
|
|
|
|
'is_alien', # Bool: var declared in INPUT line, but not in signature |
|
2720
|
|
|
|
|
|
|
'in_input', # Bool: the parameter has appeared in an INPUT statement |
|
2721
|
|
|
|
|
|
|
'defer', # Str: deferred initialisation template code |
|
2722
|
|
|
|
|
|
|
|
|
2723
|
|
|
|
|
|
|
# values derived from the XSUB's OUTPUT line |
|
2724
|
|
|
|
|
|
|
# |
|
2725
|
|
|
|
|
|
|
'in_output', # Bool: the parameter has appeared in an OUTPUT statement |
|
2726
|
|
|
|
|
|
|
'do_setmagic', # Bool: 'SETMAGIC: ENABLE' was active for this parameter |
|
2727
|
|
|
|
|
|
|
'output_code', # Str: the optional setting-code for this parameter |
|
2728
|
|
|
|
|
|
|
|
|
2729
|
|
|
|
|
|
|
# ArrayRefs: results of looking up typemaps (which are done in the |
|
2730
|
|
|
|
|
|
|
# parse phase, as the typemap definitions can in theory change |
|
2731
|
|
|
|
|
|
|
# further down in the XS file). For now these just store |
|
2732
|
|
|
|
|
|
|
# uninterpreted, the list returned by the call to |
|
2733
|
|
|
|
|
|
|
# lookup_input_typemap() etc, for later use by the as_input_code() |
|
2734
|
|
|
|
|
|
|
# etc methods. |
|
2735
|
|
|
|
|
|
|
# |
|
2736
|
|
|
|
|
|
|
'input_typemap_vals', # result of lookup_input_typemap() |
|
2737
|
|
|
|
|
|
|
'output_typemap_vals', # result of lookup_output_typemap(...) |
|
2738
|
|
|
|
|
|
|
'output_typemap_vals_outlist', # result of lookup_output_typemap(..., n) |
|
2739
|
|
|
|
|
|
|
)}; |
|
2740
|
|
|
|
|
|
|
|
|
2741
|
|
|
|
|
|
|
|
|
2742
|
|
|
|
|
|
|
# Given a param with known type etc, extract its typemap INPUT template |
|
2743
|
|
|
|
|
|
|
# and also create a hash of vars that can be used to eval that template. |
|
2744
|
|
|
|
|
|
|
# An undef returned hash ref signifies that the returned template string |
|
2745
|
|
|
|
|
|
|
# doesn't need to be evalled. |
|
2746
|
|
|
|
|
|
|
# |
|
2747
|
|
|
|
|
|
|
# Returns ($expr, $eval_vars, $is_template) |
|
2748
|
|
|
|
|
|
|
# or empty list on failure. |
|
2749
|
|
|
|
|
|
|
# |
|
2750
|
|
|
|
|
|
|
# $expr: text like '$var = SvIV($arg)' |
|
2751
|
|
|
|
|
|
|
# $eval_vars: hash ref like { var => 'foo', arg => 'ST(0)', ... } |
|
2752
|
|
|
|
|
|
|
# $is_template: $expr has '$arg' etc and needs evalling |
|
2753
|
|
|
|
|
|
|
|
|
2754
|
|
|
|
|
|
|
sub lookup_input_typemap { |
|
2755
|
647
|
|
|
647
|
|
1405
|
my __PACKAGE__ $self = shift; |
|
2756
|
647
|
|
|
|
|
1059
|
my ExtUtils::ParseXS $pxs = shift; |
|
2757
|
647
|
|
|
|
|
1238
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
2758
|
647
|
|
|
|
|
1028
|
my $xbody = shift; |
|
2759
|
|
|
|
|
|
|
|
|
2760
|
|
|
|
|
|
|
my ($type, $arg_num, $var, $init, $no_init, $default) |
|
2761
|
647
|
|
|
|
|
1299
|
= @{$self}{qw(type arg_num var init no_init default)}; |
|
|
647
|
|
|
|
|
3974
|
|
|
2762
|
647
|
100
|
|
|
|
2018
|
$var = "XSauto_length_of_$self->{len_name}" if $self->{is_length}; |
|
2763
|
647
|
|
|
|
|
2762
|
my $arg = $pxs->ST($arg_num); |
|
2764
|
|
|
|
|
|
|
|
|
2765
|
|
|
|
|
|
|
# whitespace-tidy the type |
|
2766
|
647
|
|
|
|
|
2217
|
$type = ExtUtils::Typemaps::tidy_type($type); |
|
2767
|
|
|
|
|
|
|
|
|
2768
|
|
|
|
|
|
|
# Specify the environment for when the initialiser template is evaled. |
|
2769
|
|
|
|
|
|
|
# Only the common ones are specified here. Other fields may be added |
|
2770
|
|
|
|
|
|
|
# later. |
|
2771
|
|
|
|
|
|
|
my $eval_vars = { |
|
2772
|
|
|
|
|
|
|
type => $type, |
|
2773
|
|
|
|
|
|
|
var => $var, |
|
2774
|
|
|
|
|
|
|
num => $arg_num, |
|
2775
|
|
|
|
|
|
|
arg => $arg, |
|
2776
|
|
|
|
|
|
|
alias => $xsub->{seen_ALIAS}, |
|
2777
|
|
|
|
|
|
|
func_name => $xsub->{decl}{name}, |
|
2778
|
|
|
|
|
|
|
full_perl_name => $xsub->{decl}{full_perl_name}, |
|
2779
|
|
|
|
|
|
|
full_C_name => $xsub->{decl}{full_C_name}, |
|
2780
|
|
|
|
|
|
|
Package => $xsub->{PACKAGE_name}, |
|
2781
|
647
|
|
|
|
|
12216
|
}; |
|
2782
|
|
|
|
|
|
|
|
|
2783
|
|
|
|
|
|
|
# The type looked up in the eval is Foo__Bar rather than Foo::Bar |
|
2784
|
|
|
|
|
|
|
$eval_vars->{type} =~ tr/:/_/ |
|
2785
|
647
|
50
|
|
|
|
4437
|
unless $pxs->{config_RetainCplusplusHierarchicalTypes}; |
|
2786
|
|
|
|
|
|
|
|
|
2787
|
647
|
|
|
|
|
1179
|
my $init_template; |
|
2788
|
|
|
|
|
|
|
|
|
2789
|
647
|
100
|
|
|
|
2030
|
if (defined $init) { |
|
|
|
100
|
|
|
|
|
|
|
2790
|
|
|
|
|
|
|
# Use the supplied code template rather than getting it from the |
|
2791
|
|
|
|
|
|
|
# typemap |
|
2792
|
|
|
|
|
|
|
|
|
2793
|
13
|
50
|
|
|
|
58
|
$pxs->death( |
|
2794
|
|
|
|
|
|
|
"Internal error: ExtUtils::ParseXS::Node::Param::as_code(): " |
|
2795
|
|
|
|
|
|
|
. "both init and no_init supplied") |
|
2796
|
|
|
|
|
|
|
if $no_init; |
|
2797
|
|
|
|
|
|
|
|
|
2798
|
13
|
|
|
|
|
43
|
$eval_vars->{init} = $init; |
|
2799
|
13
|
|
|
|
|
30
|
$init_template = "\$var = $init"; |
|
2800
|
|
|
|
|
|
|
} |
|
2801
|
|
|
|
|
|
|
elsif ($no_init) { |
|
2802
|
|
|
|
|
|
|
# don't add initialiser |
|
2803
|
272
|
|
|
|
|
1345
|
$init_template = ""; |
|
2804
|
|
|
|
|
|
|
} |
|
2805
|
|
|
|
|
|
|
else { |
|
2806
|
|
|
|
|
|
|
# Get the initialiser template from the typemap |
|
2807
|
|
|
|
|
|
|
|
|
2808
|
362
|
|
|
|
|
961
|
my $typemaps = $pxs->{typemaps_object}; |
|
2809
|
|
|
|
|
|
|
|
|
2810
|
|
|
|
|
|
|
# Normalised type ('Foo *' becomes 'FooPtr): one of the valid vars |
|
2811
|
|
|
|
|
|
|
# which can appear within a typemap template. |
|
2812
|
362
|
|
|
|
|
1583
|
(my $ntype = $type) =~ s/\s*\*/Ptr/g; |
|
2813
|
|
|
|
|
|
|
|
|
2814
|
|
|
|
|
|
|
# $subtype is really just for the T_ARRAY / DO_ARRAY_ELEM code below, |
|
2815
|
|
|
|
|
|
|
# where it's the type of each array element. But it's also passed to |
|
2816
|
|
|
|
|
|
|
# the typemap template (although undocumented and virtually unused). |
|
2817
|
362
|
|
|
|
|
2947
|
(my $subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//; |
|
2818
|
|
|
|
|
|
|
|
|
2819
|
|
|
|
|
|
|
# look up the TYPEMAP entry for this C type and grab the corresponding |
|
2820
|
|
|
|
|
|
|
# XS type name (e.g. $type of 'char *' gives $xstype of 'T_PV' |
|
2821
|
362
|
|
|
|
|
1733
|
my $typemap = $typemaps->get_typemap(ctype => $type); |
|
2822
|
362
|
100
|
|
|
|
1103
|
if (not $typemap) { |
|
2823
|
1
|
|
|
|
|
25
|
$pxs->report_typemap_failure($typemaps, $type); |
|
2824
|
1
|
|
|
|
|
16
|
return; |
|
2825
|
|
|
|
|
|
|
} |
|
2826
|
361
|
|
|
|
|
1572
|
my $xstype = $typemap->xstype; |
|
2827
|
|
|
|
|
|
|
|
|
2828
|
|
|
|
|
|
|
# An optimisation: for the typemaps which check that the dereferenced |
|
2829
|
|
|
|
|
|
|
# item is blessed into the right class, skip the test for DESTROY() |
|
2830
|
|
|
|
|
|
|
# methods, as more or less by definition, DESTROY() will be called |
|
2831
|
|
|
|
|
|
|
# on an object of the right class. Basically, for T_foo_OBJ, use |
|
2832
|
|
|
|
|
|
|
# T_foo_REF instead. T_REF_IV_PTR was added in v5.22.0. |
|
2833
|
|
|
|
|
|
|
$xstype =~ s/OBJ$/REF/ || $xstype =~ s/^T_REF_IV_PTR$/T_PTRREF/ |
|
2834
|
361
|
100
|
33
|
|
|
1407
|
if $xsub->{decl}{name} =~ /DESTROY$/; |
|
2835
|
|
|
|
|
|
|
|
|
2836
|
|
|
|
|
|
|
# For a string-ish parameter foo, if length(foo) was also declared |
|
2837
|
|
|
|
|
|
|
# as a pseudo-parameter, then override the normal typedef - which |
|
2838
|
|
|
|
|
|
|
# would emit SvPV_nolen(...) - and instead, emit SvPV(..., |
|
2839
|
|
|
|
|
|
|
# STRLEN_length_of_foo) |
|
2840
|
361
|
100
|
100
|
|
|
1445
|
if ($xstype eq 'T_PV' and $self->{has_length}) { |
|
2841
|
12
|
50
|
|
|
|
105
|
die "default value not supported with length(NAME) supplied" |
|
2842
|
|
|
|
|
|
|
if defined $default; |
|
2843
|
12
|
|
|
|
|
142
|
return "($type)SvPV($arg, STRLEN_length_of_$var);", |
|
2844
|
|
|
|
|
|
|
$eval_vars, 0; |
|
2845
|
|
|
|
|
|
|
} |
|
2846
|
|
|
|
|
|
|
|
|
2847
|
|
|
|
|
|
|
# Get the ExtUtils::Typemaps::InputMap object associated with the |
|
2848
|
|
|
|
|
|
|
# xstype. This contains the template of the code to be embedded, |
|
2849
|
|
|
|
|
|
|
# e.g. 'SvPV_nolen($arg)' |
|
2850
|
349
|
|
|
|
|
1287
|
my $inputmap = $typemaps->get_inputmap(xstype => $xstype); |
|
2851
|
349
|
100
|
|
|
|
873
|
if (not defined $inputmap) { |
|
2852
|
3
|
|
|
|
|
46
|
$pxs->blurt("Error: no INPUT definition for type '$type', typekind '$xstype' found"); |
|
2853
|
3
|
|
|
|
|
23
|
return; |
|
2854
|
|
|
|
|
|
|
} |
|
2855
|
|
|
|
|
|
|
|
|
2856
|
|
|
|
|
|
|
# Get the text of the template, with a few transformations to make it |
|
2857
|
|
|
|
|
|
|
# work better with fussy C compilers. In particular, strip trailing |
|
2858
|
|
|
|
|
|
|
# semicolons and remove any leading white space before a '#'. |
|
2859
|
346
|
|
|
|
|
1329
|
my $expr = $inputmap->cleaned_code; |
|
2860
|
|
|
|
|
|
|
|
|
2861
|
346
|
|
|
|
|
1160
|
my $argoff = $arg_num - 1; |
|
2862
|
|
|
|
|
|
|
|
|
2863
|
|
|
|
|
|
|
# Process DO_ARRAY_ELEM. This is an undocumented hack that makes the |
|
2864
|
|
|
|
|
|
|
# horrible T_ARRAY typemap work. "DO_ARRAY_ELEM" appears as a token |
|
2865
|
|
|
|
|
|
|
# in the INPUT and OUTPUT code for for T_ARRAY, within a "for each |
|
2866
|
|
|
|
|
|
|
# element" loop, and the purpose of this branch is to substitute the |
|
2867
|
|
|
|
|
|
|
# token for some real code which will process each element, based |
|
2868
|
|
|
|
|
|
|
# on the type of the array elements (the $subtype). |
|
2869
|
|
|
|
|
|
|
# |
|
2870
|
|
|
|
|
|
|
# Note: This gruesome bit either needs heavy rethinking or |
|
2871
|
|
|
|
|
|
|
# documentation. I vote for the former. --Steffen, 2011 |
|
2872
|
|
|
|
|
|
|
# Seconded, DAPM 2024. |
|
2873
|
346
|
100
|
|
|
|
1136
|
if ($expr =~ /\bDO_ARRAY_ELEM\b/) { |
|
2874
|
6
|
|
|
|
|
41
|
my $subtypemap = $typemaps->get_typemap(ctype => $subtype); |
|
2875
|
6
|
100
|
|
|
|
55
|
if (not $subtypemap) { |
|
2876
|
1
|
|
|
|
|
31
|
$pxs->report_typemap_failure($typemaps, $subtype); |
|
2877
|
1
|
|
|
|
|
23
|
return; |
|
2878
|
|
|
|
|
|
|
} |
|
2879
|
|
|
|
|
|
|
|
|
2880
|
5
|
|
|
|
|
40
|
my $subinputmap = |
|
2881
|
|
|
|
|
|
|
$typemaps->get_inputmap(xstype => $subtypemap->xstype); |
|
2882
|
5
|
100
|
|
|
|
46
|
if (not $subinputmap) { |
|
2883
|
1
|
|
|
|
|
20
|
$pxs->blurt("Error: no INPUT definition for subtype " |
|
2884
|
|
|
|
|
|
|
. "'$subtype', typekind '" |
|
2885
|
|
|
|
|
|
|
. $subtypemap->xstype . "' found"); |
|
2886
|
1
|
|
|
|
|
38
|
return; |
|
2887
|
|
|
|
|
|
|
} |
|
2888
|
|
|
|
|
|
|
|
|
2889
|
4
|
|
|
|
|
37
|
my $subexpr = $subinputmap->cleaned_code; |
|
2890
|
4
|
|
|
|
|
40
|
$subexpr =~ s/\$type/\$subtype/g; |
|
2891
|
4
|
|
|
|
|
15
|
$subexpr =~ s/ntype/subtype/g; |
|
2892
|
4
|
|
|
|
|
51
|
$subexpr =~ s/\$arg/ST(ix_$var)/g; |
|
2893
|
4
|
|
|
|
|
18
|
$subexpr =~ s/\n\t/\n\t\t/g; |
|
2894
|
4
|
|
|
|
|
13
|
$subexpr =~ s/is not of (.*\")/[arg %d] is not of $1, ix_$var + 1/g; |
|
2895
|
4
|
|
|
|
|
57
|
$subexpr =~ s/\$var/${var}\[ix_$var - $argoff]/; |
|
2896
|
4
|
|
|
|
|
36
|
$expr =~ s/\bDO_ARRAY_ELEM\b/$subexpr/; |
|
2897
|
|
|
|
|
|
|
} |
|
2898
|
|
|
|
|
|
|
|
|
2899
|
344
|
100
|
|
|
|
961
|
if ($expr =~ m#/\*.*scope.*\*/#i) { # "scope" in C comments |
|
2900
|
1
|
|
|
|
|
13
|
$xsub->{SCOPE_enabled} = 1; |
|
2901
|
|
|
|
|
|
|
} |
|
2902
|
|
|
|
|
|
|
|
|
2903
|
|
|
|
|
|
|
# Specify additional environment for when a template derived from a |
|
2904
|
|
|
|
|
|
|
# *typemap* is evalled. |
|
2905
|
344
|
|
|
|
|
2783
|
@$eval_vars{qw(ntype subtype argoff)} = ($ntype, $subtype, $argoff); |
|
2906
|
344
|
|
|
|
|
992
|
$init_template = $expr; |
|
2907
|
|
|
|
|
|
|
} |
|
2908
|
|
|
|
|
|
|
|
|
2909
|
629
|
|
|
|
|
4996
|
return ($init_template, $eval_vars, 1); |
|
2910
|
|
|
|
|
|
|
} |
|
2911
|
|
|
|
|
|
|
|
|
2912
|
|
|
|
|
|
|
|
|
2913
|
|
|
|
|
|
|
|
|
2914
|
|
|
|
|
|
|
# Given a param with known type etc, extract its typemap OUTPUT template |
|
2915
|
|
|
|
|
|
|
# and also create a hash of vars that can be used to eval that template. |
|
2916
|
|
|
|
|
|
|
# An undef returned hash ref signifies that the returned template string |
|
2917
|
|
|
|
|
|
|
# doesn't need to be evalled. |
|
2918
|
|
|
|
|
|
|
# $out_num, if defined, signifies that this lookup is for an OUTLIST param |
|
2919
|
|
|
|
|
|
|
# |
|
2920
|
|
|
|
|
|
|
# Returns ($expr, $eval_vars, $is_template, $saw_DAE) |
|
2921
|
|
|
|
|
|
|
# or empty list on failure. |
|
2922
|
|
|
|
|
|
|
# |
|
2923
|
|
|
|
|
|
|
# $expr: text like 'sv_setiv($arg, $var)' |
|
2924
|
|
|
|
|
|
|
# $eval_vars: hash ref like { var => 'foo', arg => 'ST(0)', ... } |
|
2925
|
|
|
|
|
|
|
# $is_template: $expr has '$arg' etc and needs evalling |
|
2926
|
|
|
|
|
|
|
# $saw_DAE: DO_ARRAY_ELEM was encountered |
|
2927
|
|
|
|
|
|
|
# |
|
2928
|
|
|
|
|
|
|
|
|
2929
|
|
|
|
|
|
|
sub lookup_output_typemap { |
|
2930
|
268
|
|
|
268
|
|
585
|
my __PACKAGE__ $self = shift; |
|
2931
|
268
|
|
|
|
|
523
|
my ExtUtils::ParseXS $pxs = shift; |
|
2932
|
268
|
|
|
|
|
504
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
2933
|
268
|
|
|
|
|
468
|
my $xbody = shift; |
|
2934
|
268
|
|
|
|
|
609
|
my $out_num = shift; |
|
2935
|
|
|
|
|
|
|
|
|
2936
|
|
|
|
|
|
|
my ($type, $num, $var, $do_setmagic, $output_code) |
|
2937
|
268
|
|
|
|
|
696
|
= @{$self}{qw(type arg_num var do_setmagic output_code)}; |
|
|
268
|
|
|
|
|
1565
|
|
|
2938
|
|
|
|
|
|
|
|
|
2939
|
|
|
|
|
|
|
# values to return |
|
2940
|
268
|
|
|
|
|
574
|
my ($expr, $eval_vars, $is_template, $saw_DAE); |
|
2941
|
268
|
|
|
|
|
475
|
$is_template = 1; |
|
2942
|
|
|
|
|
|
|
|
|
2943
|
268
|
100
|
|
|
|
854
|
if ($var eq 'RETVAL') { |
|
2944
|
|
|
|
|
|
|
# Do some preliminary RETVAL-specific checks and settings. |
|
2945
|
|
|
|
|
|
|
|
|
2946
|
|
|
|
|
|
|
# Only OUT/OUTPUT vars (which update one of the passed args) should be |
|
2947
|
|
|
|
|
|
|
# calling set magic; RETVAL and OUTLIST should be setting the value of |
|
2948
|
|
|
|
|
|
|
# a fresh mortal or TARG. Note that a param can be both OUTPUT and |
|
2949
|
|
|
|
|
|
|
# OUTLIST - the value of $do_setmagic only applies to its use as an |
|
2950
|
|
|
|
|
|
|
# OUTPUT (updating) value. |
|
2951
|
|
|
|
|
|
|
|
|
2952
|
186
|
50
|
|
|
|
616
|
$pxs->death("Internal error: do set magic requested on RETVAL") |
|
2953
|
|
|
|
|
|
|
if $do_setmagic; |
|
2954
|
|
|
|
|
|
|
|
|
2955
|
|
|
|
|
|
|
# RETVAL normally has an undefined arg_num, although it can be |
|
2956
|
|
|
|
|
|
|
# set to a real index if RETVAL is also declared as a parameter. |
|
2957
|
|
|
|
|
|
|
# But when returning its value, it's always stored at ST(0). |
|
2958
|
186
|
|
|
|
|
373
|
$num = 1; |
|
2959
|
|
|
|
|
|
|
|
|
2960
|
|
|
|
|
|
|
# It is possible for RETVAL to have multiple types, e.g. |
|
2961
|
|
|
|
|
|
|
# int |
|
2962
|
|
|
|
|
|
|
# foo(long RETVAL) |
|
2963
|
|
|
|
|
|
|
# |
|
2964
|
|
|
|
|
|
|
# In the above, 'long' is used for the RETVAL C var's declaration, |
|
2965
|
|
|
|
|
|
|
# while 'int' is used to generate the return code (for backwards |
|
2966
|
|
|
|
|
|
|
# compatibility). |
|
2967
|
186
|
|
|
|
|
605
|
$type = $xsub->{decl}{return_type}{type}; |
|
2968
|
|
|
|
|
|
|
} |
|
2969
|
|
|
|
|
|
|
|
|
2970
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
2971
|
|
|
|
|
|
|
# Do initial processing of $type, including creating various derived |
|
2972
|
|
|
|
|
|
|
# values |
|
2973
|
|
|
|
|
|
|
|
|
2974
|
268
|
100
|
|
|
|
1271
|
unless (defined $type) { |
|
2975
|
3
|
|
|
|
|
53
|
$pxs->blurt("Error: can't determine output type for '$var'"); |
|
2976
|
3
|
|
|
|
|
29
|
return; |
|
2977
|
|
|
|
|
|
|
} |
|
2978
|
|
|
|
|
|
|
|
|
2979
|
|
|
|
|
|
|
# $ntype: normalised type ('Foo *' becomes 'FooPtr' etc): one of the |
|
2980
|
|
|
|
|
|
|
# valid vars which can appear within a typemap template. |
|
2981
|
265
|
|
|
|
|
1545
|
(my $ntype = $type) =~ s/\s*\*/Ptr/g; |
|
2982
|
265
|
|
|
|
|
708
|
$ntype =~ s/\(\)//g; |
|
2983
|
|
|
|
|
|
|
|
|
2984
|
|
|
|
|
|
|
# $subtype is really just for the T_ARRAY / DO_ARRAY_ELEM code below, |
|
2985
|
|
|
|
|
|
|
# where it's the type of each array element. But it's also passed to |
|
2986
|
|
|
|
|
|
|
# the typemap template (although undocumented and virtually unused). |
|
2987
|
|
|
|
|
|
|
# Basically for a type like FooArray or FooArrayPtr, the subtype is Foo. |
|
2988
|
265
|
|
|
|
|
2627
|
(my $subtype = $ntype) =~ s/(?:Array)?(?:Ptr)?$//; |
|
2989
|
|
|
|
|
|
|
|
|
2990
|
|
|
|
|
|
|
# whitespace-tidy the type |
|
2991
|
265
|
|
|
|
|
1146
|
$type = ExtUtils::Typemaps::tidy_type($type); |
|
2992
|
|
|
|
|
|
|
|
|
2993
|
|
|
|
|
|
|
# The type as supplied to the eval is Foo__Bar rather than Foo::Bar |
|
2994
|
265
|
|
|
|
|
553
|
my $eval_type = $type; |
|
2995
|
|
|
|
|
|
|
$eval_type =~ tr/:/_/ |
|
2996
|
265
|
50
|
|
|
|
1191
|
unless $pxs->{config_RetainCplusplusHierarchicalTypes}; |
|
2997
|
|
|
|
|
|
|
|
|
2998
|
|
|
|
|
|
|
# We can be called twice for the same variable: once to update the |
|
2999
|
|
|
|
|
|
|
# original arg (via an entry in OUTPUT) and once to push the param's |
|
3000
|
|
|
|
|
|
|
# value (via OUTLIST). When doing the latter, any override code on an |
|
3001
|
|
|
|
|
|
|
# OUTPUT line should not be used. |
|
3002
|
265
|
100
|
|
|
|
674
|
undef $output_code if defined $out_num; |
|
3003
|
|
|
|
|
|
|
|
|
3004
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3005
|
|
|
|
|
|
|
# Find the template code (pre any eval) and store it in $expr. |
|
3006
|
|
|
|
|
|
|
# This is typically obtained via a typemap lookup, but can be |
|
3007
|
|
|
|
|
|
|
# overridden. Also set vars ready for evalling the typemap template. |
|
3008
|
|
|
|
|
|
|
|
|
3009
|
265
|
|
|
|
|
448
|
my $outputmap; |
|
3010
|
265
|
|
|
|
|
740
|
my $typemaps = $pxs->{typemaps_object}; |
|
3011
|
|
|
|
|
|
|
|
|
3012
|
265
|
100
|
|
|
|
1159
|
if (defined $output_code) { |
|
|
|
100
|
|
|
|
|
|
|
3013
|
|
|
|
|
|
|
# An override on an OUTPUT line: use that instead of the typemap. |
|
3014
|
|
|
|
|
|
|
# Note that we don't set $expr here, because $expr holds a template |
|
3015
|
|
|
|
|
|
|
# string pre-eval, while OUTPUT override code is *not* |
|
3016
|
|
|
|
|
|
|
# template-expanded, so $output_code is effectively post-eval code. |
|
3017
|
11
|
|
|
|
|
61
|
$is_template = 0; |
|
3018
|
11
|
|
|
|
|
42
|
$expr = $output_code; |
|
3019
|
|
|
|
|
|
|
} |
|
3020
|
|
|
|
|
|
|
elsif ($type =~ /^array\(([^,]*),(.*)\)/) { |
|
3021
|
|
|
|
|
|
|
# Specially handle the implicit array return type, "array(type, nlelem)" |
|
3022
|
|
|
|
|
|
|
# rather than using a typemap entry. It returns a string SV whose |
|
3023
|
|
|
|
|
|
|
# buffer is a copy of $var, which it assumes is a C array of |
|
3024
|
|
|
|
|
|
|
# type 'type' with 'nelem' elements. |
|
3025
|
|
|
|
|
|
|
|
|
3026
|
4
|
|
|
|
|
32
|
my ($atype, $nitems) = ($1, $2); |
|
3027
|
|
|
|
|
|
|
|
|
3028
|
4
|
100
|
|
|
|
24
|
if ($var ne 'RETVAL') { |
|
3029
|
|
|
|
|
|
|
# This special type is intended for use only as the return type of |
|
3030
|
|
|
|
|
|
|
# an XSUB |
|
3031
|
2
|
100
|
|
|
|
55
|
$pxs->blurt( "Error: can't use array(type,nitems) type for " |
|
3032
|
|
|
|
|
|
|
. (defined $out_num ? "OUTLIST" : "OUT") |
|
3033
|
|
|
|
|
|
|
. " parameter"); |
|
3034
|
2
|
|
|
|
|
15
|
return; |
|
3035
|
|
|
|
|
|
|
} |
|
3036
|
|
|
|
|
|
|
|
|
3037
|
|
|
|
|
|
|
$expr = |
|
3038
|
2
|
|
|
|
|
15
|
"\tsv_setpvn(\$arg, (char *)\$var, $nitems * sizeof($atype));\n"; |
|
3039
|
|
|
|
|
|
|
} |
|
3040
|
|
|
|
|
|
|
else { |
|
3041
|
|
|
|
|
|
|
# Handle a normal return type via a typemap. |
|
3042
|
|
|
|
|
|
|
|
|
3043
|
|
|
|
|
|
|
# Get the output map entry for this type; complain if not found. |
|
3044
|
250
|
|
|
|
|
1017
|
my $typemap = $typemaps->get_typemap(ctype => $type); |
|
3045
|
250
|
50
|
|
|
|
862
|
if (not $typemap) { |
|
3046
|
0
|
|
|
|
|
0
|
$pxs->report_typemap_failure($typemaps, $type); |
|
3047
|
0
|
|
|
|
|
0
|
return; |
|
3048
|
|
|
|
|
|
|
} |
|
3049
|
|
|
|
|
|
|
|
|
3050
|
250
|
|
|
|
|
1048
|
$outputmap = $typemaps->get_outputmap(xstype => $typemap->xstype); |
|
3051
|
250
|
100
|
|
|
|
717
|
if (not $outputmap) { |
|
3052
|
1
|
|
|
|
|
18
|
$pxs->blurt( "Error: no OUTPUT definition for type '$type', " |
|
3053
|
|
|
|
|
|
|
. "typekind '" . $typemap->xstype . "' found"); |
|
3054
|
1
|
|
|
|
|
13
|
return; |
|
3055
|
|
|
|
|
|
|
} |
|
3056
|
|
|
|
|
|
|
|
|
3057
|
|
|
|
|
|
|
# Get the text of the typemap template, with a few transformations to |
|
3058
|
|
|
|
|
|
|
# make it work better with fussy C compilers. In particular, strip |
|
3059
|
|
|
|
|
|
|
# trailing semicolons and remove any leading white space before a '#'. |
|
3060
|
|
|
|
|
|
|
|
|
3061
|
249
|
|
|
|
|
1321
|
$expr = $outputmap->cleaned_code; |
|
3062
|
|
|
|
|
|
|
} |
|
3063
|
|
|
|
|
|
|
|
|
3064
|
262
|
100
|
|
|
|
1450
|
my $arg = $pxs->ST(defined $out_num ? $out_num + 1 : $num); |
|
3065
|
|
|
|
|
|
|
|
|
3066
|
|
|
|
|
|
|
# Specify the environment for if/when the code template is evalled. |
|
3067
|
|
|
|
|
|
|
$eval_vars = |
|
3068
|
|
|
|
|
|
|
{ |
|
3069
|
|
|
|
|
|
|
num => $num, |
|
3070
|
|
|
|
|
|
|
var => $var, |
|
3071
|
|
|
|
|
|
|
do_setmagic => $do_setmagic, |
|
3072
|
|
|
|
|
|
|
subtype => $subtype, |
|
3073
|
|
|
|
|
|
|
ntype => $ntype, |
|
3074
|
|
|
|
|
|
|
arg => $arg, |
|
3075
|
|
|
|
|
|
|
type => $eval_type, |
|
3076
|
|
|
|
|
|
|
alias => $xsub->{seen_ALIAS}, |
|
3077
|
|
|
|
|
|
|
func_name => $xsub->{decl}{name}, |
|
3078
|
|
|
|
|
|
|
full_perl_name => $xsub->{decl}{full_perl_name}, |
|
3079
|
|
|
|
|
|
|
full_C_name => $xsub->{decl}{full_C_name}, |
|
3080
|
|
|
|
|
|
|
Package => $xsub->{PACKAGE_name}, |
|
3081
|
262
|
|
|
|
|
4664
|
}; |
|
3082
|
|
|
|
|
|
|
|
|
3083
|
|
|
|
|
|
|
|
|
3084
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3085
|
|
|
|
|
|
|
# Handle DO_ARRAY_ELEM token as a very special case |
|
3086
|
|
|
|
|
|
|
|
|
3087
|
262
|
100
|
100
|
|
|
2349
|
if (!defined $output_code and $expr =~ /\bDO_ARRAY_ELEM\b/) { |
|
3088
|
|
|
|
|
|
|
# See the comments in ExtUtils::ParseXS::Node::Param::as_code() that |
|
3089
|
|
|
|
|
|
|
# explain the similar code for the DO_ARRAY_ELEM hack there. |
|
3090
|
|
|
|
|
|
|
|
|
3091
|
8
|
100
|
|
|
|
47
|
if ($var ne 'RETVAL') { |
|
3092
|
|
|
|
|
|
|
# Typemap templates containing DO_ARRAY_ELEM are assumed to |
|
3093
|
|
|
|
|
|
|
# contain a loop which explicitly stores a new mortal SV at |
|
3094
|
|
|
|
|
|
|
# each of the locations ST(0) .. ST(n-1), and which then uses |
|
3095
|
|
|
|
|
|
|
# the code from the typemap for the underlying array element |
|
3096
|
|
|
|
|
|
|
# to set each SV's value. |
|
3097
|
|
|
|
|
|
|
# |
|
3098
|
|
|
|
|
|
|
# This is a horrible hack for RETVAL, which would probably |
|
3099
|
|
|
|
|
|
|
# fail with OUTLIST due to stack offsets being wrong, and |
|
3100
|
|
|
|
|
|
|
# definitely would fail with OUT, which is supposed to be |
|
3101
|
|
|
|
|
|
|
# updating parameter SVs, not pushing anything on the stack. |
|
3102
|
|
|
|
|
|
|
# So forbid all except RETVAL. |
|
3103
|
2
|
100
|
|
|
|
47
|
$pxs->blurt("Error: can't use typemap containing DO_ARRAY_ELEM for " |
|
3104
|
|
|
|
|
|
|
. (defined $out_num ? "OUTLIST" : "OUT") |
|
3105
|
|
|
|
|
|
|
. " parameter"); |
|
3106
|
2
|
|
|
|
|
34
|
return; |
|
3107
|
|
|
|
|
|
|
} |
|
3108
|
|
|
|
|
|
|
|
|
3109
|
6
|
|
|
|
|
57
|
my $subtypemap = $typemaps->get_typemap(ctype => $subtype); |
|
3110
|
6
|
100
|
|
|
|
44
|
if (not $subtypemap) { |
|
3111
|
1
|
|
|
|
|
23
|
$pxs->report_typemap_failure($typemaps, $subtype); |
|
3112
|
1
|
|
|
|
|
21
|
return; |
|
3113
|
|
|
|
|
|
|
} |
|
3114
|
|
|
|
|
|
|
|
|
3115
|
5
|
|
|
|
|
31
|
my $suboutputmap = |
|
3116
|
|
|
|
|
|
|
$typemaps->get_outputmap(xstype => $subtypemap->xstype); |
|
3117
|
|
|
|
|
|
|
|
|
3118
|
5
|
100
|
|
|
|
28
|
if (not $suboutputmap) { |
|
3119
|
1
|
|
|
|
|
13
|
$pxs->blurt( "Error: no OUTPUT definition for subtype '$subtype', " |
|
3120
|
|
|
|
|
|
|
. "typekind '" . $subtypemap->xstype . "' found"); |
|
3121
|
1
|
|
|
|
|
12
|
return; |
|
3122
|
|
|
|
|
|
|
} |
|
3123
|
|
|
|
|
|
|
|
|
3124
|
4
|
|
|
|
|
26
|
my $subexpr = $suboutputmap->cleaned_code; |
|
3125
|
4
|
|
|
|
|
44
|
$subexpr =~ s/ntype/subtype/g; |
|
3126
|
4
|
|
|
|
|
65
|
$subexpr =~ s/\$arg/ST(ix_$var)/g; |
|
3127
|
4
|
|
|
|
|
59
|
$subexpr =~ s/\$var/${var}\[ix_$var]/g; |
|
3128
|
4
|
|
|
|
|
18
|
$subexpr =~ s/\n\t/\n\t\t/g; |
|
3129
|
4
|
|
|
|
|
58
|
$expr =~ s/\bDO_ARRAY_ELEM\b/$subexpr/; |
|
3130
|
|
|
|
|
|
|
|
|
3131
|
4
|
|
|
|
|
17
|
$saw_DAE = 1; |
|
3132
|
|
|
|
|
|
|
} |
|
3133
|
|
|
|
|
|
|
|
|
3134
|
258
|
|
|
|
|
1829
|
return $expr, $eval_vars, $is_template, $saw_DAE; |
|
3135
|
|
|
|
|
|
|
} |
|
3136
|
|
|
|
|
|
|
|
|
3137
|
|
|
|
|
|
|
|
|
3138
|
|
|
|
|
|
|
# $self->as_input_code(): |
|
3139
|
|
|
|
|
|
|
# |
|
3140
|
|
|
|
|
|
|
# Emit the param object as C code which declares and initialise the variable. |
|
3141
|
|
|
|
|
|
|
# See also the as_output_code() method, which emits code to return the value |
|
3142
|
|
|
|
|
|
|
# of that local var. |
|
3143
|
|
|
|
|
|
|
|
|
3144
|
|
|
|
|
|
|
sub as_input_code { |
|
3145
|
645
|
|
|
645
|
|
1362
|
my __PACKAGE__ $self = shift; |
|
3146
|
645
|
|
|
|
|
1851
|
my ExtUtils::ParseXS $pxs = shift; |
|
3147
|
645
|
|
|
|
|
1075
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
3148
|
645
|
|
|
|
|
1668
|
my $xbody = shift; |
|
3149
|
|
|
|
|
|
|
|
|
3150
|
|
|
|
|
|
|
my ($type, $arg_num, $var, $init, $no_init, $defer, $default) |
|
3151
|
645
|
|
|
|
|
1416
|
= @{$self}{qw(type arg_num var init no_init defer default)}; |
|
|
645
|
|
|
|
|
3952
|
|
|
3152
|
|
|
|
|
|
|
|
|
3153
|
645
|
|
|
|
|
2642
|
my $arg = $pxs->ST($arg_num); |
|
3154
|
|
|
|
|
|
|
|
|
3155
|
645
|
100
|
|
|
|
1986
|
if ($self->{is_length}) { |
|
3156
|
|
|
|
|
|
|
# Process length(foo) parameter. |
|
3157
|
|
|
|
|
|
|
# Basically for something like foo(char *s, int length(s)), |
|
3158
|
|
|
|
|
|
|
# create *two* local C vars: one with STRLEN type, and one with the |
|
3159
|
|
|
|
|
|
|
# type specified in the signature. Eventually, generate code looking |
|
3160
|
|
|
|
|
|
|
# something like: |
|
3161
|
|
|
|
|
|
|
# STRLEN STRLEN_length_of_s; |
|
3162
|
|
|
|
|
|
|
# int XSauto_length_of_s; |
|
3163
|
|
|
|
|
|
|
# char *s = (char *)SvPV(ST(0), STRLEN_length_of_s); |
|
3164
|
|
|
|
|
|
|
# XSauto_length_of_s = STRLEN_length_of_s; |
|
3165
|
|
|
|
|
|
|
# RETVAL = foo(s, XSauto_length_of_s); |
|
3166
|
|
|
|
|
|
|
# |
|
3167
|
|
|
|
|
|
|
# Note that the SvPV() code line is generated via a separate call to |
|
3168
|
|
|
|
|
|
|
# this sub with s as the var (as opposed to *this* call, which is |
|
3169
|
|
|
|
|
|
|
# handling length(s)), by overriding the normal T_PV typemap (which |
|
3170
|
|
|
|
|
|
|
# uses PV_nolen()). |
|
3171
|
|
|
|
|
|
|
|
|
3172
|
14
|
|
|
|
|
63
|
my $name = $self->{len_name}; |
|
3173
|
|
|
|
|
|
|
|
|
3174
|
14
|
|
|
|
|
60
|
print "\tSTRLEN\tSTRLEN_length_of_$name;\n"; |
|
3175
|
|
|
|
|
|
|
# defer this line until after all the other declarations |
|
3176
|
|
|
|
|
|
|
$xbody->{input_part}{deferred_code_lines} .= |
|
3177
|
14
|
|
|
|
|
180
|
"\n\tXSauto_length_of_$name = STRLEN_length_of_$name;\n"; |
|
3178
|
14
|
|
|
|
|
39
|
$var = "XSauto_length_of_$name"; |
|
3179
|
|
|
|
|
|
|
} |
|
3180
|
|
|
|
|
|
|
|
|
3181
|
|
|
|
|
|
|
# Emit the variable's type and name. |
|
3182
|
|
|
|
|
|
|
# |
|
3183
|
|
|
|
|
|
|
# Includes special handling for function pointer types. An INPUT line |
|
3184
|
|
|
|
|
|
|
# always has the C type followed by the variable name. The C code |
|
3185
|
|
|
|
|
|
|
# which is emitted normally follows the same pattern. However for |
|
3186
|
|
|
|
|
|
|
# function pointers, the code is different: the variable name has to |
|
3187
|
|
|
|
|
|
|
# be embedded *within* the type. For example, these two INPUT lines: |
|
3188
|
|
|
|
|
|
|
# |
|
3189
|
|
|
|
|
|
|
# char * s |
|
3190
|
|
|
|
|
|
|
# int (*)(int) fn_ptr |
|
3191
|
|
|
|
|
|
|
# |
|
3192
|
|
|
|
|
|
|
# cause the following lines of C to be emitted; |
|
3193
|
|
|
|
|
|
|
# |
|
3194
|
|
|
|
|
|
|
# char * s = [something from a typemap] |
|
3195
|
|
|
|
|
|
|
# int (* fn_ptr)(int) = [something from a typemap] |
|
3196
|
|
|
|
|
|
|
# |
|
3197
|
|
|
|
|
|
|
# So handle specially the specific case of a type containing '(*)' by |
|
3198
|
|
|
|
|
|
|
# embedding the variable name *within* rather than *after* the type. |
|
3199
|
|
|
|
|
|
|
|
|
3200
|
|
|
|
|
|
|
|
|
3201
|
645
|
100
|
|
|
|
2252
|
if ($type =~ / \( \s* \* \s* \) /x) { |
|
3202
|
|
|
|
|
|
|
# for a fn ptr type, embed the var name in the type declaration |
|
3203
|
1
|
|
|
|
|
8
|
print "\t" . $pxs->map_type($type, $var); |
|
3204
|
|
|
|
|
|
|
} |
|
3205
|
|
|
|
|
|
|
else { |
|
3206
|
|
|
|
|
|
|
print "\t", |
|
3207
|
644
|
100
|
100
|
|
|
5494
|
((defined($xsub->{decl}{class}) && $var eq 'CLASS') |
|
3208
|
|
|
|
|
|
|
? $type |
|
3209
|
|
|
|
|
|
|
: $pxs->map_type($type, undef)), |
|
3210
|
|
|
|
|
|
|
"\t$var"; |
|
3211
|
|
|
|
|
|
|
} |
|
3212
|
|
|
|
|
|
|
|
|
3213
|
|
|
|
|
|
|
# Result of parse-phase lookup of INPUT typemap for this param's type. |
|
3214
|
645
|
|
|
|
|
1808
|
my $lookup = $self->{input_typemap_vals}; |
|
3215
|
645
|
100
|
|
|
|
1774
|
$pxs->death( "Internal error: parameter '$var' " |
|
3216
|
|
|
|
|
|
|
. "doesn't have input_typemap_vals") |
|
3217
|
|
|
|
|
|
|
unless $lookup; |
|
3218
|
|
|
|
|
|
|
|
|
3219
|
643
|
|
|
|
|
1932
|
my ($init_template, $eval_vars, $is_template) = @$lookup; |
|
3220
|
|
|
|
|
|
|
|
|
3221
|
643
|
100
|
|
|
|
1464
|
return unless defined $init_template; # an error occurred |
|
3222
|
|
|
|
|
|
|
|
|
3223
|
637
|
100
|
|
|
|
1656
|
unless ($is_template) { |
|
3224
|
|
|
|
|
|
|
# template already expanded |
|
3225
|
11
|
|
|
|
|
64
|
print " = $init_template\n"; |
|
3226
|
11
|
|
|
|
|
131
|
return; |
|
3227
|
|
|
|
|
|
|
} |
|
3228
|
|
|
|
|
|
|
|
|
3229
|
|
|
|
|
|
|
# whitespace-tidy the type |
|
3230
|
626
|
|
|
|
|
2207
|
$type = ExtUtils::Typemaps::tidy_type($type); |
|
3231
|
|
|
|
|
|
|
|
|
3232
|
|
|
|
|
|
|
# Now finally, emit the actual variable declaration and initialisation |
|
3233
|
|
|
|
|
|
|
# line(s). The variable type and name will already have been emitted. |
|
3234
|
|
|
|
|
|
|
|
|
3235
|
626
|
100
|
|
|
|
4553
|
my $init_code = |
|
3236
|
|
|
|
|
|
|
length $init_template |
|
3237
|
|
|
|
|
|
|
? $pxs->eval_input_typemap_code("qq\a$init_template\a", $eval_vars) |
|
3238
|
|
|
|
|
|
|
: ""; |
|
3239
|
|
|
|
|
|
|
|
|
3240
|
|
|
|
|
|
|
|
|
3241
|
626
|
100
|
100
|
|
|
31339
|
if (defined $default |
|
|
|
100
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
3242
|
|
|
|
|
|
|
# XXX for now, for backcompat, ignore default if the |
|
3243
|
|
|
|
|
|
|
# param has a typemap override |
|
3244
|
|
|
|
|
|
|
&& !(defined $init) |
|
3245
|
|
|
|
|
|
|
# XXX for now, for backcompat, ignore default if the |
|
3246
|
|
|
|
|
|
|
# param wouldn't otherwise get initialised |
|
3247
|
|
|
|
|
|
|
&& !$no_init |
|
3248
|
|
|
|
|
|
|
) { |
|
3249
|
|
|
|
|
|
|
# Has a default value. Just terminate the variable declaration, and |
|
3250
|
|
|
|
|
|
|
# defer the initialisation. |
|
3251
|
|
|
|
|
|
|
|
|
3252
|
21
|
|
|
|
|
100
|
print ";\n"; |
|
3253
|
|
|
|
|
|
|
|
|
3254
|
|
|
|
|
|
|
# indent the code 1 step further |
|
3255
|
21
|
|
|
|
|
596
|
$init_code =~ s/(\t+)/$1 /g; |
|
3256
|
21
|
|
|
|
|
107
|
$init_code =~ s/ /\t/g; |
|
3257
|
|
|
|
|
|
|
|
|
3258
|
21
|
100
|
|
|
|
94
|
if ($default eq 'NO_INIT') { |
|
3259
|
|
|
|
|
|
|
# for foo(a, b = NO_INIT), add code to initialise later only if |
|
3260
|
|
|
|
|
|
|
# an arg was supplied. |
|
3261
|
|
|
|
|
|
|
$xbody->{input_part}{deferred_code_lines} |
|
3262
|
1
|
|
|
|
|
15
|
.= sprintf "\n\tif (items >= %d) {\n%s;\n\t}\n", |
|
3263
|
|
|
|
|
|
|
$arg_num, $init_code; |
|
3264
|
|
|
|
|
|
|
} |
|
3265
|
|
|
|
|
|
|
else { |
|
3266
|
|
|
|
|
|
|
# for foo(a, b = default), add code to initialise later to either |
|
3267
|
|
|
|
|
|
|
# the arg or default value |
|
3268
|
20
|
50
|
|
|
|
169
|
my $else = $init_code =~ /\S/ |
|
3269
|
|
|
|
|
|
|
? "\telse {\n$init_code;\n\t}\n" |
|
3270
|
|
|
|
|
|
|
: ""; |
|
3271
|
|
|
|
|
|
|
|
|
3272
|
20
|
|
|
|
|
91
|
$default =~ s/"/\\"/g; # escape double quotes |
|
3273
|
|
|
|
|
|
|
$xbody->{input_part}{deferred_code_lines} |
|
3274
|
20
|
|
|
|
|
154
|
.= sprintf "\n\tif (items < %d)\n\t %s = %s;\n%s", |
|
3275
|
|
|
|
|
|
|
$arg_num, |
|
3276
|
|
|
|
|
|
|
$var, |
|
3277
|
|
|
|
|
|
|
$pxs->eval_input_typemap_code("qq\a$default\a", |
|
3278
|
|
|
|
|
|
|
$eval_vars), |
|
3279
|
|
|
|
|
|
|
$else; |
|
3280
|
|
|
|
|
|
|
} |
|
3281
|
|
|
|
|
|
|
} |
|
3282
|
|
|
|
|
|
|
elsif ($xsub->{SCOPE_enabled} or $init_code !~ /^\s*\Q$var\E =/) { |
|
3283
|
|
|
|
|
|
|
# The template is likely a full block rather than a '$var = ...' |
|
3284
|
|
|
|
|
|
|
# expression. Just terminate the variable declaration, and defer the |
|
3285
|
|
|
|
|
|
|
# initialisation. |
|
3286
|
|
|
|
|
|
|
# Note that /\Q$var\E/ matches the string containing whatever $var |
|
3287
|
|
|
|
|
|
|
# was expanded to in the eval. |
|
3288
|
|
|
|
|
|
|
|
|
3289
|
280
|
|
|
|
|
1406
|
print ";\n"; |
|
3290
|
|
|
|
|
|
|
|
|
3291
|
|
|
|
|
|
|
$xbody->{input_part}{deferred_code_lines} |
|
3292
|
280
|
100
|
|
|
|
3082
|
.= sprintf "\n%s;\n", $init_code |
|
3293
|
|
|
|
|
|
|
if $init_code =~ /\S/; |
|
3294
|
|
|
|
|
|
|
} |
|
3295
|
|
|
|
|
|
|
else { |
|
3296
|
|
|
|
|
|
|
# The template starts with '$var = ...'. The variable name has already |
|
3297
|
|
|
|
|
|
|
# been emitted, so remove it from the typemap before evalling it, |
|
3298
|
|
|
|
|
|
|
|
|
3299
|
325
|
50
|
|
|
|
17718
|
$init_code =~ s/^\s*\Q$var\E(\s*=\s*)/$1/ |
|
3300
|
|
|
|
|
|
|
# we just checked above that it starts with var=, so this |
|
3301
|
|
|
|
|
|
|
# should never happen |
|
3302
|
|
|
|
|
|
|
or $pxs->death( |
|
3303
|
|
|
|
|
|
|
"Internal error: typemap doesn't start with '\$var='\n"); |
|
3304
|
|
|
|
|
|
|
|
|
3305
|
325
|
|
|
|
|
2207
|
printf "%s;\n", $init_code; |
|
3306
|
|
|
|
|
|
|
} |
|
3307
|
|
|
|
|
|
|
|
|
3308
|
626
|
100
|
|
|
|
5393
|
if (defined $defer) { |
|
3309
|
|
|
|
|
|
|
$xbody->{input_part}{deferred_code_lines} |
|
3310
|
6
|
|
|
|
|
30
|
.= $pxs->eval_input_typemap_code("qq\a$defer\a", $eval_vars) |
|
3311
|
|
|
|
|
|
|
. "\n"; |
|
3312
|
|
|
|
|
|
|
} |
|
3313
|
|
|
|
|
|
|
} |
|
3314
|
|
|
|
|
|
|
|
|
3315
|
|
|
|
|
|
|
|
|
3316
|
|
|
|
|
|
|
# $param->as_output_code($ParseXS_object, $out_num]) |
|
3317
|
|
|
|
|
|
|
# |
|
3318
|
|
|
|
|
|
|
# Emit code to: possibly create, then set the value of, and possibly |
|
3319
|
|
|
|
|
|
|
# push, an output SV, based on the values in the $param object. |
|
3320
|
|
|
|
|
|
|
# |
|
3321
|
|
|
|
|
|
|
# $out_num is optional and its presence indicates that an OUTLIST var is |
|
3322
|
|
|
|
|
|
|
# being pushed: it indicates the position on the stack of that SV. |
|
3323
|
|
|
|
|
|
|
# |
|
3324
|
|
|
|
|
|
|
# This function emits code such as "sv_setiv(ST(0), (IV)foo)", based on |
|
3325
|
|
|
|
|
|
|
# the typemap OUTPUT entry associated with $type. It passes the typemap |
|
3326
|
|
|
|
|
|
|
# code through a double-quotish context eval first to expand variables |
|
3327
|
|
|
|
|
|
|
# such as $arg and $var. It also tries to optimise the emitted code in |
|
3328
|
|
|
|
|
|
|
# various ways, such as using TARG where available rather than calling |
|
3329
|
|
|
|
|
|
|
# sv_newmortal() to obtain an SV to set to the return value. |
|
3330
|
|
|
|
|
|
|
# |
|
3331
|
|
|
|
|
|
|
# It expects to handle three categories of variable, with these general |
|
3332
|
|
|
|
|
|
|
# actions: |
|
3333
|
|
|
|
|
|
|
# |
|
3334
|
|
|
|
|
|
|
# RETVAL, i.e. the return value |
|
3335
|
|
|
|
|
|
|
# |
|
3336
|
|
|
|
|
|
|
# Create a new SV; use the typemap to set its value to RETVAL; then |
|
3337
|
|
|
|
|
|
|
# store it at ST(0). |
|
3338
|
|
|
|
|
|
|
# |
|
3339
|
|
|
|
|
|
|
# OUTLIST foo |
|
3340
|
|
|
|
|
|
|
# |
|
3341
|
|
|
|
|
|
|
# Create a new SV; use the typemap to set its value to foo; then store |
|
3342
|
|
|
|
|
|
|
# it at ST($out_num-1). |
|
3343
|
|
|
|
|
|
|
# |
|
3344
|
|
|
|
|
|
|
# OUTPUT: foo / OUT foo |
|
3345
|
|
|
|
|
|
|
# |
|
3346
|
|
|
|
|
|
|
# Update the value of the passed arg ST($num-1), using the typemap to |
|
3347
|
|
|
|
|
|
|
# set its value |
|
3348
|
|
|
|
|
|
|
# |
|
3349
|
|
|
|
|
|
|
# Note that it's possible for this function to be called *twice* for the |
|
3350
|
|
|
|
|
|
|
# same variable: once for OUTLIST, and once for an 'OUTPUT:' entry. |
|
3351
|
|
|
|
|
|
|
# |
|
3352
|
|
|
|
|
|
|
# It treats output typemaps as falling into two basic categories, |
|
3353
|
|
|
|
|
|
|
# exemplified by: |
|
3354
|
|
|
|
|
|
|
# |
|
3355
|
|
|
|
|
|
|
# sv_setFoo($arg, (Foo)$var)); |
|
3356
|
|
|
|
|
|
|
# |
|
3357
|
|
|
|
|
|
|
# $arg = newFoo($var); |
|
3358
|
|
|
|
|
|
|
# |
|
3359
|
|
|
|
|
|
|
# The first form is the most general and can be used to set the SV value |
|
3360
|
|
|
|
|
|
|
# for all of the three variable categories above. For the first two |
|
3361
|
|
|
|
|
|
|
# categories it typically uses a new mortal, while for the last, it just |
|
3362
|
|
|
|
|
|
|
# uses the passed arg SV. |
|
3363
|
|
|
|
|
|
|
# |
|
3364
|
|
|
|
|
|
|
# The assign form of the typemap can be considered an optimisation of |
|
3365
|
|
|
|
|
|
|
# sv_setsv($arg, newFoo($var)), and is applicable when newFOO() is known |
|
3366
|
|
|
|
|
|
|
# to return a new SV. So rather than copying it to yet another new SV, |
|
3367
|
|
|
|
|
|
|
# just return as-is, possibly after mortalising it, |
|
3368
|
|
|
|
|
|
|
# |
|
3369
|
|
|
|
|
|
|
# Some typemaps evaluate to different code depending on whether the var is |
|
3370
|
|
|
|
|
|
|
# RETVAL, e.g T_BOOL is currently defined as: |
|
3371
|
|
|
|
|
|
|
# |
|
3372
|
|
|
|
|
|
|
# ${"$var" eq "RETVAL" ? \"$arg = boolSV($var);" |
|
3373
|
|
|
|
|
|
|
# : \"sv_setsv($arg, boolSV($var));"} |
|
3374
|
|
|
|
|
|
|
# |
|
3375
|
|
|
|
|
|
|
# So we examine the typemap *after* evaluation to determine whether it's |
|
3376
|
|
|
|
|
|
|
# of the form '$arg = ' or not. |
|
3377
|
|
|
|
|
|
|
# |
|
3378
|
|
|
|
|
|
|
# Note that *currently* we generally end up with the pessimised option for |
|
3379
|
|
|
|
|
|
|
# OUTLIST vars, since the typmaps onlt check for RETVAL. |
|
3380
|
|
|
|
|
|
|
# |
|
3381
|
|
|
|
|
|
|
# Currently RETVAL and 'OUTLIST var' mostly share the same code paths |
|
3382
|
|
|
|
|
|
|
# below, so they both benefit from optimisations such as using TARG |
|
3383
|
|
|
|
|
|
|
# instead of creating a new mortal, and using the RETVALSV C var to keep |
|
3384
|
|
|
|
|
|
|
# track of the temp SV, rather than repeatedly retrieving it from ST(0) |
|
3385
|
|
|
|
|
|
|
# etc. Note that RETVALSV is private and shouldn't be referenced within XS |
|
3386
|
|
|
|
|
|
|
# code or typemaps. |
|
3387
|
|
|
|
|
|
|
|
|
3388
|
|
|
|
|
|
|
sub as_output_code { |
|
3389
|
266
|
|
|
266
|
|
573
|
my __PACKAGE__ $self = shift; |
|
3390
|
266
|
|
|
|
|
427
|
my ExtUtils::ParseXS $pxs = shift; |
|
3391
|
266
|
|
|
|
|
546
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
3392
|
266
|
|
|
|
|
469
|
my $xbody = shift; |
|
3393
|
266
|
|
|
|
|
544
|
my $out_num = shift; |
|
3394
|
|
|
|
|
|
|
|
|
3395
|
|
|
|
|
|
|
my ($type, $var, $do_setmagic, $output_code) |
|
3396
|
266
|
|
|
|
|
608
|
= @{$self}{qw(type var do_setmagic output_code)}; |
|
|
266
|
|
|
|
|
1434
|
|
|
3397
|
|
|
|
|
|
|
|
|
3398
|
266
|
100
|
|
|
|
779
|
if ($var eq 'RETVAL') { |
|
3399
|
|
|
|
|
|
|
# It is possible for RETVAL to have multiple types, e.g. |
|
3400
|
|
|
|
|
|
|
# int |
|
3401
|
|
|
|
|
|
|
# foo(long RETVAL) |
|
3402
|
|
|
|
|
|
|
# |
|
3403
|
|
|
|
|
|
|
# In the above, 'long' is used for the RETVAL C var's declaration, |
|
3404
|
|
|
|
|
|
|
# while 'int' is used to generate the return code (for backwards |
|
3405
|
|
|
|
|
|
|
# compatibility). |
|
3406
|
184
|
|
|
|
|
566
|
$type = $xsub->{decl}{return_type}{type}; |
|
3407
|
|
|
|
|
|
|
} |
|
3408
|
|
|
|
|
|
|
|
|
3409
|
|
|
|
|
|
|
# whitespace-tidy the type |
|
3410
|
266
|
|
|
|
|
997
|
$type = ExtUtils::Typemaps::tidy_type($type); |
|
3411
|
|
|
|
|
|
|
|
|
3412
|
|
|
|
|
|
|
# We can be called twice for the same variable: once to update the |
|
3413
|
|
|
|
|
|
|
# original arg (via an entry in OUTPUT) and once to push the param's |
|
3414
|
|
|
|
|
|
|
# value (via OUTLIST). When doing the latter, any override code on an |
|
3415
|
|
|
|
|
|
|
# OUTPUT line should not be used. |
|
3416
|
266
|
100
|
|
|
|
791
|
undef $output_code if defined $out_num; |
|
3417
|
|
|
|
|
|
|
|
|
3418
|
|
|
|
|
|
|
# Result of parse-phase lookup of OUTPUT typemap for this param's type. |
|
3419
|
|
|
|
|
|
|
my $lookup = defined $out_num |
|
3420
|
|
|
|
|
|
|
? $self->{output_typemap_vals_outlist} |
|
3421
|
266
|
100
|
|
|
|
814
|
: $self->{output_typemap_vals}; |
|
3422
|
266
|
50
|
|
|
|
666
|
$pxs->death( "Internal error: parameter '$var' " |
|
3423
|
|
|
|
|
|
|
. "doesn't have output_typemap_vals") |
|
3424
|
|
|
|
|
|
|
unless $lookup; |
|
3425
|
|
|
|
|
|
|
|
|
3426
|
266
|
|
|
|
|
1566
|
my ($expr, $eval_vars, $is_template, $saw_DAE) = @$lookup; |
|
3427
|
|
|
|
|
|
|
|
|
3428
|
266
|
100
|
|
|
|
942
|
return unless defined $expr; # error |
|
3429
|
|
|
|
|
|
|
|
|
3430
|
256
|
100
|
|
|
|
834
|
if ($saw_DAE) { |
|
|
|
100
|
|
|
|
|
|
|
3431
|
|
|
|
|
|
|
# We do our own code emitting and return here (rather than control |
|
3432
|
|
|
|
|
|
|
# passing on to normal RETVAL processing) since that processing is |
|
3433
|
|
|
|
|
|
|
# expecting to push a single temp onto the stack, while our code |
|
3434
|
|
|
|
|
|
|
# pushes several temps. |
|
3435
|
4
|
|
|
|
|
54
|
print $pxs->eval_output_typemap_code("qq\a$expr\a", $eval_vars); |
|
3436
|
4
|
|
|
|
|
57
|
return; |
|
3437
|
|
|
|
|
|
|
} |
|
3438
|
|
|
|
|
|
|
elsif (!$is_template) { |
|
3439
|
|
|
|
|
|
|
# $expr doesn't need evalling - use as-is |
|
3440
|
11
|
|
|
|
|
44
|
$output_code = $expr; |
|
3441
|
|
|
|
|
|
|
} |
|
3442
|
|
|
|
|
|
|
|
|
3443
|
252
|
|
|
|
|
753
|
my $ntype = $eval_vars->{ntype}; |
|
3444
|
252
|
|
|
|
|
692
|
my $num = $eval_vars->{num}; |
|
3445
|
252
|
|
|
|
|
699
|
my $arg = $eval_vars->{arg}; |
|
3446
|
|
|
|
|
|
|
|
|
3447
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3448
|
|
|
|
|
|
|
# Now emit code for the three types of return value: |
|
3449
|
|
|
|
|
|
|
# |
|
3450
|
|
|
|
|
|
|
# RETVAL - The usual case: store an SV at ST(0) which is set |
|
3451
|
|
|
|
|
|
|
# to the value of RETVAL. This is typically a new |
|
3452
|
|
|
|
|
|
|
# mortal, but may be optimised to use TARG. |
|
3453
|
|
|
|
|
|
|
# |
|
3454
|
|
|
|
|
|
|
# OUTLIST param - if $out_num is defined (and will be >= 0) Push |
|
3455
|
|
|
|
|
|
|
# after any RETVAL, new mortal(s) containing the |
|
3456
|
|
|
|
|
|
|
# current values of the local var set from that |
|
3457
|
|
|
|
|
|
|
# parameter. (May also use TARG if not already used |
|
3458
|
|
|
|
|
|
|
# by RETVAL). |
|
3459
|
|
|
|
|
|
|
# |
|
3460
|
|
|
|
|
|
|
# OUT/OUTPUT param - update passed arg SV at ST($num-1) (which |
|
3461
|
|
|
|
|
|
|
# corresponds to param) with the current value of |
|
3462
|
|
|
|
|
|
|
# the local var set from that parameter. |
|
3463
|
|
|
|
|
|
|
|
|
3464
|
252
|
100
|
100
|
|
|
1182
|
if ($var ne 'RETVAL' and not defined $out_num) { |
|
3465
|
|
|
|
|
|
|
# This is a normal OUTPUT var: i.e. a named parameter whose |
|
3466
|
|
|
|
|
|
|
# corresponding arg on the stack should be updated with the |
|
3467
|
|
|
|
|
|
|
# parameter's current value by using the code contained in the |
|
3468
|
|
|
|
|
|
|
# output typemap. |
|
3469
|
|
|
|
|
|
|
# |
|
3470
|
|
|
|
|
|
|
# Note that for args being *updated* (as opposed to replaced), this |
|
3471
|
|
|
|
|
|
|
# branch relies on the typemap to Do The Right Thing. For example, |
|
3472
|
|
|
|
|
|
|
# T_BOOL currently has this typemap entry: |
|
3473
|
|
|
|
|
|
|
# |
|
3474
|
|
|
|
|
|
|
# ${"$var" eq "RETVAL" ? \"$arg = boolSV($var);" |
|
3475
|
|
|
|
|
|
|
# : \"sv_setsv($arg, boolSV($var));"} |
|
3476
|
|
|
|
|
|
|
# |
|
3477
|
|
|
|
|
|
|
# which means that if we hit this branch, $evalexpr will have been |
|
3478
|
|
|
|
|
|
|
# expanded to something like "sv_setsv(ST(2), boolSV(foo))". |
|
3479
|
|
|
|
|
|
|
|
|
3480
|
33
|
50
|
|
|
|
74
|
unless (defined $num) { |
|
3481
|
0
|
|
|
|
|
0
|
$pxs->blurt( |
|
3482
|
|
|
|
|
|
|
"Internal error: OUT parameter has undefined argument number"); |
|
3483
|
0
|
|
|
|
|
0
|
return; |
|
3484
|
|
|
|
|
|
|
} |
|
3485
|
|
|
|
|
|
|
|
|
3486
|
|
|
|
|
|
|
# Use the code on the OUTPUT line if specified, otherwise use the |
|
3487
|
|
|
|
|
|
|
# typemap |
|
3488
|
33
|
100
|
|
|
|
192
|
my $code = defined $output_code |
|
3489
|
|
|
|
|
|
|
? "\t$output_code\n" |
|
3490
|
|
|
|
|
|
|
: $pxs->eval_output_typemap_code("qq\a$expr\a", $eval_vars); |
|
3491
|
33
|
|
|
|
|
160
|
print $code; |
|
3492
|
|
|
|
|
|
|
|
|
3493
|
|
|
|
|
|
|
# For parameters in the OUTPUT section, honour the SETMAGIC in force |
|
3494
|
|
|
|
|
|
|
# at the time. For parameters instead being output because of an OUT |
|
3495
|
|
|
|
|
|
|
# keyword in the signature, assume set magic always. |
|
3496
|
33
|
100
|
100
|
|
|
568
|
print "\tSvSETMAGIC($arg);\n" if !$self->{in_output} || $do_setmagic; |
|
3497
|
33
|
|
|
|
|
260
|
return; |
|
3498
|
|
|
|
|
|
|
} |
|
3499
|
|
|
|
|
|
|
|
|
3500
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3501
|
|
|
|
|
|
|
# The rest of this main body handles RETVAL or "OUTLIST foo". |
|
3502
|
|
|
|
|
|
|
|
|
3503
|
219
|
100
|
66
|
|
|
833
|
if (defined $output_code and !defined $out_num) { |
|
3504
|
|
|
|
|
|
|
# Handle this (just emit overridden code as-is): |
|
3505
|
|
|
|
|
|
|
# OUTPUT: |
|
3506
|
|
|
|
|
|
|
# RETVAL output_code |
|
3507
|
8
|
|
|
|
|
81
|
print "\t$output_code\n"; |
|
3508
|
8
|
50
|
|
|
|
146
|
print "\t++SP;\n" if $xbody->{output_part}{stack_was_reset}; |
|
3509
|
8
|
|
|
|
|
51
|
return; |
|
3510
|
|
|
|
|
|
|
} |
|
3511
|
|
|
|
|
|
|
|
|
3512
|
|
|
|
|
|
|
# Emit a standard RETVAL/OUTLIST return |
|
3513
|
|
|
|
|
|
|
|
|
3514
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3515
|
|
|
|
|
|
|
# First, evaluate the typemap, expanding any vars like $var and $arg, |
|
3516
|
|
|
|
|
|
|
# for example, |
|
3517
|
|
|
|
|
|
|
# |
|
3518
|
|
|
|
|
|
|
# $arg = newFoo($var); |
|
3519
|
|
|
|
|
|
|
# or |
|
3520
|
|
|
|
|
|
|
# sv_setFoo($arg, $var); |
|
3521
|
|
|
|
|
|
|
# |
|
3522
|
|
|
|
|
|
|
# However, rather than using the actual destination (such as ST(0)) |
|
3523
|
|
|
|
|
|
|
# for the value of $arg, we instead set it initially to RETVALSV. This |
|
3524
|
|
|
|
|
|
|
# is because often the SV will be used in more than one statement, |
|
3525
|
|
|
|
|
|
|
# and so it is more efficient to temporarily store it in a C auto var. |
|
3526
|
|
|
|
|
|
|
# So we normally emit code such as: |
|
3527
|
|
|
|
|
|
|
# |
|
3528
|
|
|
|
|
|
|
# { |
|
3529
|
|
|
|
|
|
|
# SV *RETVALSV; |
|
3530
|
|
|
|
|
|
|
# RETVALSV = newFoo(RETVAL); |
|
3531
|
|
|
|
|
|
|
# RETVALSV = sv_2mortal(RETVALSV); |
|
3532
|
|
|
|
|
|
|
# ST(0) = RETVALSV; |
|
3533
|
|
|
|
|
|
|
# } |
|
3534
|
|
|
|
|
|
|
# |
|
3535
|
|
|
|
|
|
|
# Rather than |
|
3536
|
|
|
|
|
|
|
# |
|
3537
|
|
|
|
|
|
|
# ST(0) = newFoo(RETVAL); |
|
3538
|
|
|
|
|
|
|
# sv_2mortal(ST(0)); |
|
3539
|
|
|
|
|
|
|
# |
|
3540
|
|
|
|
|
|
|
# Later we sometimes modify the evalled typemap to change 'RETVALSV' |
|
3541
|
|
|
|
|
|
|
# to some other value: |
|
3542
|
|
|
|
|
|
|
# - back to e.g. 'ST(0)' if there is no other use of the SV; |
|
3543
|
|
|
|
|
|
|
# - to TARG when we are using the OP_ENTERSUB's targ; |
|
3544
|
|
|
|
|
|
|
# - to $var when then return type is SV* (and thus ntype is SVPtr) |
|
3545
|
|
|
|
|
|
|
# and so the variable will already have been declared as type 'SV*' |
|
3546
|
|
|
|
|
|
|
# and thus there is no need for a RETVALSV too. |
|
3547
|
|
|
|
|
|
|
# |
|
3548
|
|
|
|
|
|
|
# Note that we evaluate the typemap early here so that the various |
|
3549
|
|
|
|
|
|
|
# regexes below such as /^\s*\Q$arg\E\s*=/ can be matched against |
|
3550
|
|
|
|
|
|
|
# the *evalled* result of typemap entries such as |
|
3551
|
|
|
|
|
|
|
# |
|
3552
|
|
|
|
|
|
|
# ${ "$var" eq "RETVAL" ? \"$arg = $var;" : \"sv_setsv_mg($arg, $var);" } |
|
3553
|
|
|
|
|
|
|
# |
|
3554
|
|
|
|
|
|
|
# which may eval to something like "RETVALSV = RETVAL" and |
|
3555
|
|
|
|
|
|
|
# subsequently match /^\s*\Q$arg\E =/ (where $arg is "RETVAL"), but |
|
3556
|
|
|
|
|
|
|
# couldn't have matched against the original typemap. |
|
3557
|
|
|
|
|
|
|
# This is why we *always* set $arg to 'RETVALSV' first and then modify |
|
3558
|
|
|
|
|
|
|
# the typemap later - we don't know what final value we want for $arg |
|
3559
|
|
|
|
|
|
|
# until after we've examined the evalled result. |
|
3560
|
|
|
|
|
|
|
|
|
3561
|
211
|
|
|
|
|
483
|
my $orig_arg = $arg; |
|
3562
|
211
|
|
|
|
|
505
|
$eval_vars->{arg} = $arg = 'RETVALSV'; |
|
3563
|
211
|
|
|
|
|
1488
|
my $evalexpr = $pxs->eval_output_typemap_code("qq\a$expr\a", $eval_vars); |
|
3564
|
|
|
|
|
|
|
|
|
3565
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3566
|
|
|
|
|
|
|
# Examine the just-evalled typemap code to determine what optimisations |
|
3567
|
|
|
|
|
|
|
# etc can be performed and what sort of code needs emitting. The two |
|
3568
|
|
|
|
|
|
|
# halves of this following if/else examine the two forms of evalled |
|
3569
|
|
|
|
|
|
|
# typemap: |
|
3570
|
|
|
|
|
|
|
# |
|
3571
|
|
|
|
|
|
|
# RETVALSV = newFoo((Foo)RETVAL); |
|
3572
|
|
|
|
|
|
|
# and |
|
3573
|
|
|
|
|
|
|
# sv_setFoo(RETVALSV, (Foo)RETVAL); |
|
3574
|
|
|
|
|
|
|
# |
|
3575
|
|
|
|
|
|
|
# In particular, the first form is assumed to be returning an SV which |
|
3576
|
|
|
|
|
|
|
# the function has generated itself (e.g. newSVREF()) and which may |
|
3577
|
|
|
|
|
|
|
# just need mortalising; while the second form generally needs a call |
|
3578
|
|
|
|
|
|
|
# to sv_newmortal() first to create an SV which the function can then |
|
3579
|
|
|
|
|
|
|
# set the value of. |
|
3580
|
|
|
|
|
|
|
|
|
3581
|
211
|
|
|
|
|
526
|
my $do_mortalize = 0; # Emit an sv_2mortal() |
|
3582
|
211
|
|
|
|
|
334
|
my $want_newmortal = 0; # Emit an sv_newmortal() |
|
3583
|
211
|
|
|
|
|
462
|
my $retvar = 'RETVALSV'; # The name of the C var which holds the SV |
|
3584
|
|
|
|
|
|
|
# (likely tmp) to set to the value of the var |
|
3585
|
|
|
|
|
|
|
|
|
3586
|
211
|
100
|
|
|
|
2630
|
if ($evalexpr =~ /^\s*\Q$arg\E\s*=/) { |
|
3587
|
|
|
|
|
|
|
# Handle this form: RETVALSV = newFoo((Foo)RETVAL); |
|
3588
|
|
|
|
|
|
|
# newFoo creates its own SV: we just need to mortalise and return it |
|
3589
|
|
|
|
|
|
|
|
|
3590
|
|
|
|
|
|
|
# Is the SV one of the immortal SVs? |
|
3591
|
9
|
100
|
|
|
|
399
|
if ($evalexpr =~ |
|
3592
|
|
|
|
|
|
|
/^\s* |
|
3593
|
|
|
|
|
|
|
\Q$arg\E |
|
3594
|
|
|
|
|
|
|
\s*=\s* |
|
3595
|
|
|
|
|
|
|
( boolSV\(.*\) |
|
3596
|
|
|
|
|
|
|
| &PL_sv_yes |
|
3597
|
|
|
|
|
|
|
| &PL_sv_no |
|
3598
|
|
|
|
|
|
|
| &PL_sv_undef |
|
3599
|
|
|
|
|
|
|
| &PL_sv_zero |
|
3600
|
|
|
|
|
|
|
) |
|
3601
|
|
|
|
|
|
|
\s*;\s*$ |
|
3602
|
|
|
|
|
|
|
/x) |
|
3603
|
|
|
|
|
|
|
{ |
|
3604
|
|
|
|
|
|
|
# If so, we can skip mortalising it to stop it leaking. |
|
3605
|
6
|
|
|
|
|
17
|
$retvar = $orig_arg; # just assign to ST(N) directly |
|
3606
|
|
|
|
|
|
|
} |
|
3607
|
|
|
|
|
|
|
else { |
|
3608
|
|
|
|
|
|
|
# general '$arg = newFOO()' typemap |
|
3609
|
3
|
|
|
|
|
14
|
$do_mortalize = 1; |
|
3610
|
|
|
|
|
|
|
|
|
3611
|
|
|
|
|
|
|
# If $var is already of type SV*, then use that instead of |
|
3612
|
|
|
|
|
|
|
# declaring 'SV* RETVALSV' as an intermediate var. |
|
3613
|
3
|
100
|
|
|
|
19
|
$retvar = $var if $ntype eq "SVPtr"; |
|
3614
|
|
|
|
|
|
|
} |
|
3615
|
|
|
|
|
|
|
} |
|
3616
|
|
|
|
|
|
|
else { |
|
3617
|
|
|
|
|
|
|
# Handle this (eval-expanded) form of typemap: |
|
3618
|
|
|
|
|
|
|
# sv_setFoo(RETVALSV, (Foo)var); |
|
3619
|
|
|
|
|
|
|
# We generally need to supply a mortal SV for the typemap code to |
|
3620
|
|
|
|
|
|
|
# set, and then return it on the stack, |
|
3621
|
|
|
|
|
|
|
|
|
3622
|
|
|
|
|
|
|
# First, see if we can use the targ (if any) attached to the current |
|
3623
|
|
|
|
|
|
|
# OP_ENTERSUB, to avoid having to create a new mortal. |
|
3624
|
|
|
|
|
|
|
# |
|
3625
|
|
|
|
|
|
|
# The targetable() OutputMap class method looks at whether the code |
|
3626
|
|
|
|
|
|
|
# snippet is of a form suitable for using TARG as the destination. |
|
3627
|
|
|
|
|
|
|
# It looks for one of a known list of well-behaved setting function |
|
3628
|
|
|
|
|
|
|
# calls, like sv_setiv() which will set the TARG to a value that |
|
3629
|
|
|
|
|
|
|
# doesn't include magic, tieing, being a reference (which would leak |
|
3630
|
|
|
|
|
|
|
# as the TARG is never freed), etc. If so, emit dXSTARG and replace |
|
3631
|
|
|
|
|
|
|
# RETVALSV with TARG. |
|
3632
|
|
|
|
|
|
|
# |
|
3633
|
|
|
|
|
|
|
# For backwards-compatibility, dXSTARG may have already been emitted |
|
3634
|
|
|
|
|
|
|
# early in the XSUB body, when a more restrictive set of targ- |
|
3635
|
|
|
|
|
|
|
# compatible typemap entries were checked for. Note that dXSTARG is |
|
3636
|
|
|
|
|
|
|
# defined as something like: |
|
3637
|
|
|
|
|
|
|
# |
|
3638
|
|
|
|
|
|
|
# SV * targ = (PL_op->op_private & OPpENTERSUB_HASTARG) |
|
3639
|
|
|
|
|
|
|
# ? PAD_SV(PL_op->op_targ) : sv_newmortal() |
|
3640
|
|
|
|
|
|
|
|
|
3641
|
202
|
100
|
66
|
|
|
2718
|
if ( $pxs->{config_optimize} |
|
|
|
|
100
|
|
|
|
|
|
3642
|
|
|
|
|
|
|
&& ExtUtils::Typemaps::OutputMap->targetable($evalexpr) |
|
3643
|
|
|
|
|
|
|
&& !$xbody->{output_part}{targ_used}) |
|
3644
|
|
|
|
|
|
|
{ |
|
3645
|
|
|
|
|
|
|
# So TARG is available for use. |
|
3646
|
170
|
|
|
|
|
462
|
$retvar = 'TARG'; |
|
3647
|
|
|
|
|
|
|
# can only use TARG to return one value |
|
3648
|
170
|
|
|
|
|
529
|
$xbody->{output_part}{targ_used} = 1; |
|
3649
|
|
|
|
|
|
|
|
|
3650
|
|
|
|
|
|
|
# Since we're using TARG for the return SV, see if we can use |
|
3651
|
|
|
|
|
|
|
# the TARG[iun] macros as appropriate to speed up setting it. |
|
3652
|
|
|
|
|
|
|
# If so, convert "sv_setiv(RETVALSV, val)" to "TARGi(val,1)" |
|
3653
|
|
|
|
|
|
|
# and similarly for uv and nv. These macros skip a function |
|
3654
|
|
|
|
|
|
|
# call for the common case where TARG is already a simple |
|
3655
|
|
|
|
|
|
|
# IV/UV/NV. Convert the _mg forms too: since we're setting the |
|
3656
|
|
|
|
|
|
|
# TARG, there shouldn't be set magic on it, so the _mg action |
|
3657
|
|
|
|
|
|
|
# can be safely ignored. |
|
3658
|
|
|
|
|
|
|
|
|
3659
|
170
|
|
|
|
|
4072
|
$evalexpr =~ s{ |
|
3660
|
|
|
|
|
|
|
^ |
|
3661
|
|
|
|
|
|
|
(\s*) |
|
3662
|
|
|
|
|
|
|
sv_set([iun])v(?:_mg)? |
|
3663
|
|
|
|
|
|
|
\( |
|
3664
|
|
|
|
|
|
|
\s* RETVALSV \s* , |
|
3665
|
|
|
|
|
|
|
\s* (.*) |
|
3666
|
|
|
|
|
|
|
\) |
|
3667
|
|
|
|
|
|
|
( \s* ; \s*) |
|
3668
|
|
|
|
|
|
|
$ |
|
3669
|
|
|
|
|
|
|
} |
|
3670
|
|
|
|
|
|
|
{$1TARG$2($3, 1)$4}x; |
|
3671
|
|
|
|
|
|
|
} |
|
3672
|
|
|
|
|
|
|
else { |
|
3673
|
|
|
|
|
|
|
# general typemap: give it a fresh SV to set the value of. |
|
3674
|
32
|
|
|
|
|
79
|
$want_newmortal = 1; |
|
3675
|
|
|
|
|
|
|
} |
|
3676
|
|
|
|
|
|
|
} |
|
3677
|
|
|
|
|
|
|
|
|
3678
|
|
|
|
|
|
|
# ------------------------------------------------------------------ |
|
3679
|
|
|
|
|
|
|
# Now emit the return C code, based on the various flags and values |
|
3680
|
|
|
|
|
|
|
# determined above. |
|
3681
|
|
|
|
|
|
|
|
|
3682
|
211
|
|
|
|
|
777
|
my $do_scope; # wrap code in a {} block |
|
3683
|
|
|
|
|
|
|
my @lines; # Lines of code to eventually emit |
|
3684
|
|
|
|
|
|
|
|
|
3685
|
|
|
|
|
|
|
# Do any declarations first |
|
3686
|
|
|
|
|
|
|
|
|
3687
|
211
|
100
|
100
|
|
|
1739
|
if ($retvar eq 'TARG' && !$xsub->{decl}{return_type}{use_early_targ}) { |
|
|
|
100
|
|
|
|
|
|
|
3688
|
18
|
|
|
|
|
123
|
push @lines, "\tdXSTARG;\n"; |
|
3689
|
18
|
|
|
|
|
107
|
$do_scope = 1; |
|
3690
|
|
|
|
|
|
|
} |
|
3691
|
|
|
|
|
|
|
elsif ($retvar eq 'RETVALSV') { |
|
3692
|
34
|
|
|
|
|
274
|
push @lines, "\tSV * $retvar;\n"; |
|
3693
|
34
|
|
|
|
|
108
|
$do_scope = 1; |
|
3694
|
|
|
|
|
|
|
} |
|
3695
|
|
|
|
|
|
|
|
|
3696
|
211
|
100
|
|
|
|
582
|
push @lines, "\tRETVALSV = sv_newmortal();\n" if $want_newmortal; |
|
3697
|
|
|
|
|
|
|
|
|
3698
|
|
|
|
|
|
|
# Emit the typemap, while changing the name of the destination SV back |
|
3699
|
|
|
|
|
|
|
# from RETVALSV to one of the other forms (varname/TARG/ST(N)) if was |
|
3700
|
|
|
|
|
|
|
# determined earlier to be necessary. |
|
3701
|
|
|
|
|
|
|
# Skip emitting it if it's of the trivial form "var = var", which is |
|
3702
|
|
|
|
|
|
|
# generated when the typemap is of the form '$arg = $var' and the SVPtr |
|
3703
|
|
|
|
|
|
|
# optimisation is using $var for the destination. |
|
3704
|
|
|
|
|
|
|
|
|
3705
|
211
|
100
|
|
|
|
862
|
$evalexpr =~ s/\bRETVALSV\b/$retvar/g if $retvar ne 'RETVALSV'; |
|
3706
|
|
|
|
|
|
|
|
|
3707
|
211
|
100
|
|
|
|
7143
|
unless ($evalexpr =~ /^\s*\Q$var\E\s*=\s*\Q$var\E\s*;\s*$/) { |
|
3708
|
210
|
|
|
|
|
855
|
push @lines, split /^/, $evalexpr |
|
3709
|
|
|
|
|
|
|
} |
|
3710
|
|
|
|
|
|
|
|
|
3711
|
|
|
|
|
|
|
# Emit mortalisation on the result SV if needed |
|
3712
|
211
|
100
|
|
|
|
679
|
push @lines, "\t$retvar = sv_2mortal($retvar);\n" if $do_mortalize; |
|
3713
|
|
|
|
|
|
|
|
|
3714
|
|
|
|
|
|
|
# Emit the final 'ST(n) = RETVALSV' or similar, unless ST(n) |
|
3715
|
|
|
|
|
|
|
# was already assigned to earlier directly by the typemap. |
|
3716
|
211
|
100
|
|
|
|
972
|
push @lines, "\t$orig_arg = $retvar;\n" unless $retvar eq $orig_arg; |
|
3717
|
|
|
|
|
|
|
|
|
3718
|
211
|
100
|
|
|
|
656
|
if ($do_scope) { |
|
3719
|
|
|
|
|
|
|
# Add an extra 4-indent, then wrap the output code in a new block |
|
3720
|
52
|
|
|
|
|
209
|
for (@lines) { |
|
3721
|
190
|
|
|
|
|
583
|
s/\t/ /g; # break down all tabs into spaces |
|
3722
|
190
|
|
|
|
|
563
|
s/^/ /; # add 4-space extra indent |
|
3723
|
190
|
|
|
|
|
745
|
s/ /\t/g; # convert 8 spaces back to tabs |
|
3724
|
|
|
|
|
|
|
} |
|
3725
|
52
|
|
|
|
|
190
|
unshift @lines, "\t{\n"; |
|
3726
|
52
|
|
|
|
|
164
|
push @lines, "\t}\n"; |
|
3727
|
|
|
|
|
|
|
} |
|
3728
|
|
|
|
|
|
|
|
|
3729
|
211
|
|
|
|
|
1256
|
print @lines; |
|
3730
|
211
|
100
|
|
|
|
2409
|
print "\t++SP;\n" if $xbody->{output_part}{stack_was_reset}; |
|
3731
|
|
|
|
|
|
|
} |
|
3732
|
|
|
|
|
|
|
|
|
3733
|
|
|
|
|
|
|
|
|
3734
|
|
|
|
|
|
|
# ====================================================================== |
|
3735
|
|
|
|
|
|
|
|
|
3736
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::Params; |
|
3737
|
|
|
|
|
|
|
|
|
3738
|
|
|
|
|
|
|
# A Node subclass which holds a list of the parameters for an XSUB. |
|
3739
|
|
|
|
|
|
|
# It is a mainly a list of Node::Param or Node::IO_Param kids, and is |
|
3740
|
|
|
|
|
|
|
# used in two contexts. |
|
3741
|
|
|
|
|
|
|
# |
|
3742
|
|
|
|
|
|
|
# First, as a field of an xsub_decl node, where it holds a list of Param |
|
3743
|
|
|
|
|
|
|
# objects which represent the individual parameters found within an XSUB's |
|
3744
|
|
|
|
|
|
|
# signature, plus possibly extra synthetic ones such as THIS and RETVAL. |
|
3745
|
|
|
|
|
|
|
# |
|
3746
|
|
|
|
|
|
|
# Second, as a field of an xbody node, where it contains a copy of the |
|
3747
|
|
|
|
|
|
|
# signature's Params object (and Param children), but where the children |
|
3748
|
|
|
|
|
|
|
# are in fact IO_param objects and hold augmented information provided by |
|
3749
|
|
|
|
|
|
|
# any INPUT and OUTPUT blocks within that XSUB body (of which there can be |
|
3750
|
|
|
|
|
|
|
# more than one in the presence of CASE). |
|
3751
|
|
|
|
|
|
|
|
|
3752
|
19
|
|
|
19
|
|
125
|
BEGIN { $build_subclass->( |
|
3753
|
|
|
|
|
|
|
|
|
3754
|
|
|
|
|
|
|
'names', # Hash ref mapping variable names to Node::Param |
|
3755
|
|
|
|
|
|
|
# or Node::IO_Param objects |
|
3756
|
|
|
|
|
|
|
|
|
3757
|
|
|
|
|
|
|
'params_text', # Str: The original text of the sig, e.g. |
|
3758
|
|
|
|
|
|
|
# "param1, int param2 = 0" |
|
3759
|
|
|
|
|
|
|
|
|
3760
|
|
|
|
|
|
|
'seen_ellipsis', # Bool: XSUB signature has ( ,...) |
|
3761
|
|
|
|
|
|
|
|
|
3762
|
|
|
|
|
|
|
'nargs', # Int: The number of args expected from caller |
|
3763
|
|
|
|
|
|
|
'min_args', # Int: The minimum number of args allowed from caller |
|
3764
|
|
|
|
|
|
|
|
|
3765
|
|
|
|
|
|
|
'auto_function_sig_override', # Str: the C_ARGS value, if any |
|
3766
|
|
|
|
|
|
|
)}; |
|
3767
|
|
|
|
|
|
|
|
|
3768
|
|
|
|
|
|
|
|
|
3769
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
3770
|
|
|
|
|
|
|
# Parse the parameter list of an XSUB's signature. |
|
3771
|
|
|
|
|
|
|
# |
|
3772
|
|
|
|
|
|
|
# Split the XSUB's parameter list on commas into parameters, while |
|
3773
|
|
|
|
|
|
|
# allowing for things like '(a = ",", b)'. |
|
3774
|
|
|
|
|
|
|
# |
|
3775
|
|
|
|
|
|
|
# Then for each parameter, parse its various fields and store in a |
|
3776
|
|
|
|
|
|
|
# ExtUtils::ParseXS::Node::Param object. Store those Param objects within |
|
3777
|
|
|
|
|
|
|
# the Params object, plus any other state deduced from the signature, such |
|
3778
|
|
|
|
|
|
|
# as min/max permitted number of args. |
|
3779
|
|
|
|
|
|
|
# |
|
3780
|
|
|
|
|
|
|
# A typical signature might look like: |
|
3781
|
|
|
|
|
|
|
# |
|
3782
|
|
|
|
|
|
|
# OUT char *s, \ |
|
3783
|
|
|
|
|
|
|
# int length(s), \ |
|
3784
|
|
|
|
|
|
|
# OUTLIST int size = 10) |
|
3785
|
|
|
|
|
|
|
# |
|
3786
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
3787
|
|
|
|
|
|
|
|
|
3788
|
|
|
|
|
|
|
my ($C_group_rex, $C_arg); |
|
3789
|
|
|
|
|
|
|
|
|
3790
|
|
|
|
|
|
|
# Group in C (no support for comments or literals) |
|
3791
|
|
|
|
|
|
|
# |
|
3792
|
|
|
|
|
|
|
# DAPM 2024: I'm not entirely clear what this is supposed to match. |
|
3793
|
|
|
|
|
|
|
# It appears to match balanced and possibly nested [], {} etc, with |
|
3794
|
|
|
|
|
|
|
# similar but possibly unbalanced punctuation within. But the balancing |
|
3795
|
|
|
|
|
|
|
# brackets don't have to correspond: so [} is just as valid as [] or {}, |
|
3796
|
|
|
|
|
|
|
# as is [{{{{] or even [}}}}} |
|
3797
|
|
|
|
|
|
|
|
|
3798
|
|
|
|
|
|
|
$C_group_rex = qr/ [({\[] |
|
3799
|
|
|
|
|
|
|
(?: (?> [^()\[\]{}]+ ) | (??{ $C_group_rex }) )* |
|
3800
|
|
|
|
|
|
|
[)}\]] /x; |
|
3801
|
|
|
|
|
|
|
|
|
3802
|
|
|
|
|
|
|
# $C_arg: match a chunk in C without comma at toplevel (no comments), |
|
3803
|
|
|
|
|
|
|
# i.e. a single arg within an XS signature, such as |
|
3804
|
|
|
|
|
|
|
# foo = ',' |
|
3805
|
|
|
|
|
|
|
# |
|
3806
|
|
|
|
|
|
|
# DAPM 2024. This appears to match zero, one or more of: |
|
3807
|
|
|
|
|
|
|
# a random collection of non-bracket/quote/comma chars (e.g, a word or |
|
3808
|
|
|
|
|
|
|
# number or 'int *foo' etc), or |
|
3809
|
|
|
|
|
|
|
# a balanced(ish) nested brackets, or |
|
3810
|
|
|
|
|
|
|
# a "string literal", or |
|
3811
|
|
|
|
|
|
|
# a 'c' char literal |
|
3812
|
|
|
|
|
|
|
# So (I guess), it captures the next item in a function signature |
|
3813
|
|
|
|
|
|
|
|
|
3814
|
|
|
|
|
|
|
$C_arg = qr/ (?: (?> [^()\[\]{},"']+ ) |
|
3815
|
|
|
|
|
|
|
| (??{ $C_group_rex }) |
|
3816
|
|
|
|
|
|
|
| " (?: (?> [^\\"]+ ) |
|
3817
|
|
|
|
|
|
|
| \\. |
|
3818
|
|
|
|
|
|
|
)* " # String literal |
|
3819
|
|
|
|
|
|
|
| ' (?: (?> [^\\']+ ) | \\. )* ' # Char literal |
|
3820
|
|
|
|
|
|
|
)* /xs; |
|
3821
|
|
|
|
|
|
|
|
|
3822
|
|
|
|
|
|
|
|
|
3823
|
|
|
|
|
|
|
sub parse { |
|
3824
|
363
|
|
|
363
|
|
1550
|
my __PACKAGE__ $self = shift; |
|
3825
|
363
|
|
|
|
|
726
|
my ExtUtils::ParseXS $pxs = shift; |
|
3826
|
363
|
|
|
|
|
1481
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
3827
|
363
|
|
|
|
|
863
|
my $params_text = shift; |
|
3828
|
|
|
|
|
|
|
|
|
3829
|
363
|
|
|
|
|
1740
|
$self->SUPER::parse($pxs); # set file/line_no |
|
3830
|
|
|
|
|
|
|
|
|
3831
|
|
|
|
|
|
|
# remove line continuation chars (\) |
|
3832
|
363
|
|
|
|
|
2013
|
$params_text =~ s/\\\s*/ /g; |
|
3833
|
363
|
|
|
|
|
1165
|
$self->{params_text} = $params_text; |
|
3834
|
|
|
|
|
|
|
|
|
3835
|
363
|
|
|
|
|
645
|
my @param_texts; |
|
3836
|
363
|
|
|
|
|
909
|
my $opt_args = 0; # how many params with default values seen |
|
3837
|
363
|
|
|
|
|
645
|
my $nargs = 0; # how many args are expected |
|
3838
|
|
|
|
|
|
|
|
|
3839
|
|
|
|
|
|
|
# First, split signature into separate parameters |
|
3840
|
|
|
|
|
|
|
|
|
3841
|
363
|
100
|
|
|
|
3170
|
if ($params_text =~ /\S/) { |
|
3842
|
259
|
|
|
|
|
797
|
my $sig_c = "$params_text ,"; |
|
3843
|
19
|
|
|
19
|
|
210
|
use re 'eval'; # needed for 5.16.0 and earlier |
|
|
19
|
|
|
|
|
38
|
|
|
|
19
|
|
|
|
|
2492
|
|
|
3844
|
259
|
|
|
|
|
1976
|
my $can_use_regex = ($sig_c =~ /^( (??{ $C_arg }) , )* $ /x); |
|
3845
|
19
|
|
|
19
|
|
153
|
no re 'eval'; |
|
|
19
|
|
|
|
|
63
|
|
|
|
19
|
|
|
|
|
993
|
|
|
3846
|
|
|
|
|
|
|
|
|
3847
|
259
|
50
|
|
|
|
1374
|
if ($can_use_regex) { |
|
3848
|
|
|
|
|
|
|
# If the parameters are capable of being split by using the |
|
3849
|
|
|
|
|
|
|
# fancy regex, do so. This splits the params on commas, but |
|
3850
|
|
|
|
|
|
|
# can handle things like foo(a = ",", b) |
|
3851
|
19
|
|
|
19
|
|
128
|
use re 'eval'; |
|
|
19
|
|
|
|
|
38
|
|
|
|
19
|
|
|
|
|
30328
|
|
|
3852
|
259
|
|
|
|
|
1105
|
@param_texts = ($sig_c =~ /\G ( (??{ $C_arg }) ) , /xg); |
|
3853
|
|
|
|
|
|
|
} |
|
3854
|
|
|
|
|
|
|
else { |
|
3855
|
|
|
|
|
|
|
# This is the fallback parameter-splitting path for when the |
|
3856
|
|
|
|
|
|
|
# $C_arg regex doesn't work. This code path should ideally |
|
3857
|
|
|
|
|
|
|
# never be reached, and indicates a design weakness in $C_arg. |
|
3858
|
0
|
|
|
|
|
0
|
@param_texts = split(/\s*,\s*/, $params_text); |
|
3859
|
0
|
|
|
|
|
0
|
Warn($pxs, "Warning: cannot parse parameter list " |
|
3860
|
|
|
|
|
|
|
. "'$params_text', fallback to split"); |
|
3861
|
|
|
|
|
|
|
} |
|
3862
|
|
|
|
|
|
|
} |
|
3863
|
|
|
|
|
|
|
else { |
|
3864
|
104
|
|
|
|
|
324
|
@param_texts = (); |
|
3865
|
|
|
|
|
|
|
} |
|
3866
|
|
|
|
|
|
|
|
|
3867
|
|
|
|
|
|
|
# C++ methods get a fake object/class param at the start. |
|
3868
|
|
|
|
|
|
|
# This affects arg numbering. |
|
3869
|
363
|
100
|
|
|
|
2266
|
if (defined($xsub->{decl}{class})) { |
|
3870
|
|
|
|
|
|
|
my ($var, $type) = |
|
3871
|
|
|
|
|
|
|
( $xsub->{decl}{return_type}{static} |
|
3872
|
|
|
|
|
|
|
or $xsub->{decl}{name} eq 'new' |
|
3873
|
|
|
|
|
|
|
) |
|
3874
|
|
|
|
|
|
|
? ('CLASS', "char *") |
|
3875
|
27
|
100
|
100
|
|
|
798
|
: ('THIS', ($xsub->{decl}{is_const} ? "const " : "") |
|
|
|
100
|
|
|
|
|
|
|
3876
|
|
|
|
|
|
|
. "$xsub->{decl}{class} *"); |
|
3877
|
|
|
|
|
|
|
|
|
3878
|
27
|
|
|
|
|
534
|
my ExtUtils::ParseXS::Node::Param $param |
|
3879
|
|
|
|
|
|
|
= ExtUtils::ParseXS::Node::Param->new( { |
|
3880
|
|
|
|
|
|
|
var => $var, |
|
3881
|
|
|
|
|
|
|
type => $type, |
|
3882
|
|
|
|
|
|
|
is_synthetic => 1, |
|
3883
|
|
|
|
|
|
|
arg_num => ++$nargs, |
|
3884
|
|
|
|
|
|
|
}); |
|
3885
|
27
|
|
|
|
|
121
|
push @{$self->{kids}}, $param; |
|
|
27
|
|
|
|
|
295
|
|
|
3886
|
27
|
|
|
|
|
261
|
$self->{names}{$var} = $param; |
|
3887
|
|
|
|
|
|
|
} |
|
3888
|
|
|
|
|
|
|
|
|
3889
|
|
|
|
|
|
|
# For non-void return types, add a fake RETVAL parameter. This triggers |
|
3890
|
|
|
|
|
|
|
# the emitting of an 'int RETVAL;' declaration or similar, and (e.g. if |
|
3891
|
|
|
|
|
|
|
# later flagged as in_output), triggers the emitting of code to return |
|
3892
|
|
|
|
|
|
|
# RETVAL's value. |
|
3893
|
|
|
|
|
|
|
# |
|
3894
|
|
|
|
|
|
|
# Note that a RETVAL param can be in three main states: |
|
3895
|
|
|
|
|
|
|
# |
|
3896
|
|
|
|
|
|
|
# fully-synthetic What is being created here. RETVAL hasn't appeared |
|
3897
|
|
|
|
|
|
|
# in a signature or INPUT. |
|
3898
|
|
|
|
|
|
|
# |
|
3899
|
|
|
|
|
|
|
# semi-real Same as fully-synthetic, but with a defined arg_num, |
|
3900
|
|
|
|
|
|
|
# and with an updated position within |
|
3901
|
|
|
|
|
|
|
# @{$self->{kids}}. A RETVAL has appeared in the |
|
3902
|
|
|
|
|
|
|
# signature, but without a type yet specified, so it |
|
3903
|
|
|
|
|
|
|
# continues to use $xsub->{decl}{return_type}{type}. |
|
3904
|
|
|
|
|
|
|
# |
|
3905
|
|
|
|
|
|
|
# real is_synthetic, no_init flags turned off. Its type |
|
3906
|
|
|
|
|
|
|
# comes from the sig or INPUT line. This is just a |
|
3907
|
|
|
|
|
|
|
# normal parameter now. |
|
3908
|
|
|
|
|
|
|
|
|
3909
|
363
|
100
|
|
|
|
1709
|
if ($xsub->{decl}{return_type}{type} ne 'void') { |
|
3910
|
|
|
|
|
|
|
my ExtUtils::ParseXS::Node::Param $param = |
|
3911
|
|
|
|
|
|
|
ExtUtils::ParseXS::Node::Param->new( { |
|
3912
|
|
|
|
|
|
|
var => 'RETVAL', |
|
3913
|
|
|
|
|
|
|
type => $xsub->{decl}{return_type}{type}, |
|
3914
|
208
|
|
|
|
|
2772
|
no_init => 1, # just declare the var, don't initialise it |
|
3915
|
|
|
|
|
|
|
is_synthetic => 1, |
|
3916
|
|
|
|
|
|
|
} ); |
|
3917
|
|
|
|
|
|
|
|
|
3918
|
208
|
|
|
|
|
826
|
push @{$self->{kids}}, $param; |
|
|
208
|
|
|
|
|
887
|
|
|
3919
|
208
|
|
|
|
|
810
|
$self->{names}{RETVAL} = $param; |
|
3920
|
|
|
|
|
|
|
} |
|
3921
|
|
|
|
|
|
|
|
|
3922
|
363
|
|
|
|
|
2255
|
for my $param_text (@param_texts) { |
|
3923
|
|
|
|
|
|
|
# Parse each parameter. |
|
3924
|
|
|
|
|
|
|
|
|
3925
|
462
|
|
|
|
|
2184
|
$param_text =~ s/^\s+//; |
|
3926
|
462
|
|
|
|
|
2582
|
$param_text =~ s/\s+$//; |
|
3927
|
|
|
|
|
|
|
|
|
3928
|
|
|
|
|
|
|
# Process ellipsis (...) |
|
3929
|
|
|
|
|
|
|
|
|
3930
|
|
|
|
|
|
|
$pxs->blurt("Error: further XSUB parameter seen after ellipsis (...)") |
|
3931
|
462
|
100
|
|
|
|
1487
|
if $self->{seen_ellipsis}; |
|
3932
|
|
|
|
|
|
|
|
|
3933
|
462
|
100
|
|
|
|
1314
|
if ($param_text eq '...') { |
|
3934
|
11
|
|
|
|
|
70
|
$self->{seen_ellipsis} = 1; |
|
3935
|
11
|
|
|
|
|
35
|
next; |
|
3936
|
|
|
|
|
|
|
} |
|
3937
|
|
|
|
|
|
|
|
|
3938
|
451
|
|
|
|
|
2122
|
my $param = ExtUtils::ParseXS::Node::Param->new(); |
|
3939
|
451
|
100
|
|
|
|
2808
|
$param->parse($pxs, $self, $param_text) |
|
3940
|
|
|
|
|
|
|
or next; |
|
3941
|
|
|
|
|
|
|
|
|
3942
|
437
|
|
|
|
|
752
|
push @{$self->{kids}}, $param; |
|
|
437
|
|
|
|
|
1471
|
|
|
3943
|
437
|
100
|
|
|
|
3426
|
$self->{names}{$param->{var}} = $param unless $param->{var} eq 'SV *'; |
|
3944
|
437
|
100
|
|
|
|
1381
|
$opt_args++ if defined $param->{default}; |
|
3945
|
|
|
|
|
|
|
# Give the param a number if it will consume one of the passed args |
|
3946
|
|
|
|
|
|
|
$param->{arg_num} = ++$nargs |
|
3947
|
|
|
|
|
|
|
unless ( defined $param->{in_out} && $param->{in_out} eq "OUTLIST" |
|
3948
|
|
|
|
|
|
|
or $param->{is_length}) |
|
3949
|
|
|
|
|
|
|
|
|
3950
|
437
|
100
|
100
|
|
|
3954
|
} # for (@param_texts) |
|
|
|
|
100
|
|
|
|
|
|
3951
|
|
|
|
|
|
|
|
|
3952
|
363
|
|
|
|
|
1197
|
$self->{nargs} = $nargs; |
|
3953
|
363
|
|
|
|
|
957
|
$self->{min_args} = $nargs - $opt_args; |
|
3954
|
|
|
|
|
|
|
|
|
3955
|
|
|
|
|
|
|
# for each parameter of the form 'length(foo)', mark the corresponding |
|
3956
|
|
|
|
|
|
|
# 'foo' parameter as 'has_length', or error out if foo not found. |
|
3957
|
363
|
|
|
|
|
610
|
for my $param (@{$self->{kids}}) { |
|
|
363
|
|
|
|
|
1066
|
|
|
3958
|
656
|
100
|
|
|
|
1658
|
next unless $param->{is_length}; |
|
3959
|
14
|
|
|
|
|
75
|
my $name = $param->{len_name}; |
|
3960
|
14
|
100
|
|
|
|
113
|
if (exists $self->{names}{$name}) { |
|
3961
|
13
|
|
|
|
|
61
|
$self->{names}{$name}{has_length} = 1; |
|
3962
|
|
|
|
|
|
|
} |
|
3963
|
|
|
|
|
|
|
else { |
|
3964
|
1
|
|
|
|
|
27
|
$pxs->blurt("Error: length() on non-parameter '$name'"); |
|
3965
|
|
|
|
|
|
|
} |
|
3966
|
|
|
|
|
|
|
} |
|
3967
|
|
|
|
|
|
|
|
|
3968
|
363
|
|
|
|
|
1517
|
1; |
|
3969
|
|
|
|
|
|
|
} |
|
3970
|
|
|
|
|
|
|
|
|
3971
|
|
|
|
|
|
|
|
|
3972
|
|
|
|
|
|
|
# Return a string to be used in "usage: .." error messages. |
|
3973
|
|
|
|
|
|
|
|
|
3974
|
|
|
|
|
|
|
sub usage_string { |
|
3975
|
352
|
|
|
352
|
|
738
|
my __PACKAGE__ $self = shift; |
|
3976
|
|
|
|
|
|
|
|
|
3977
|
|
|
|
|
|
|
my @args = map { |
|
3978
|
|
|
|
|
|
|
$_->{var} |
|
3979
|
|
|
|
|
|
|
. (defined $_->{default_usage} |
|
3980
|
|
|
|
|
|
|
?$_->{default_usage} |
|
3981
|
409
|
100
|
|
|
|
1908
|
: '' |
|
3982
|
|
|
|
|
|
|
) |
|
3983
|
|
|
|
|
|
|
} |
|
3984
|
|
|
|
|
|
|
grep { |
|
3985
|
|
|
|
|
|
|
defined $_->{arg_num}, |
|
3986
|
644
|
|
|
|
|
2112
|
} |
|
3987
|
352
|
|
|
|
|
759
|
@{$self->{kids}}; |
|
|
352
|
|
|
|
|
1410
|
|
|
3988
|
|
|
|
|
|
|
|
|
3989
|
352
|
100
|
|
|
|
1127
|
push @args, '...' if $self->{seen_ellipsis}; |
|
3990
|
352
|
|
|
|
|
1633
|
return join ', ', @args; |
|
3991
|
|
|
|
|
|
|
} |
|
3992
|
|
|
|
|
|
|
|
|
3993
|
|
|
|
|
|
|
|
|
3994
|
|
|
|
|
|
|
# $self->C_func_signature(): |
|
3995
|
|
|
|
|
|
|
# |
|
3996
|
|
|
|
|
|
|
# return two arrays |
|
3997
|
|
|
|
|
|
|
# the first contains the arguments to pass to an autocall C |
|
3998
|
|
|
|
|
|
|
# function, e.g. ['a', '&b', 'c']; |
|
3999
|
|
|
|
|
|
|
# the second contains the types of those args, for use in declaring |
|
4000
|
|
|
|
|
|
|
# a function pointer type, e.g. ['int', 'char*', 'long']. |
|
4001
|
|
|
|
|
|
|
|
|
4002
|
|
|
|
|
|
|
sub C_func_signature { |
|
4003
|
240
|
|
|
240
|
|
931
|
my __PACKAGE__ $self = shift; |
|
4004
|
240
|
|
|
|
|
491
|
my ExtUtils::ParseXS $pxs = shift; |
|
4005
|
|
|
|
|
|
|
|
|
4006
|
240
|
|
|
|
|
618
|
my @args; |
|
4007
|
|
|
|
|
|
|
my @types; |
|
4008
|
240
|
|
|
|
|
571
|
for my $param (@{$self->{kids}}) { |
|
|
240
|
|
|
|
|
1129
|
|
|
4009
|
|
|
|
|
|
|
next if $param->{is_synthetic} # THIS/CLASS/RETVAL |
|
4010
|
|
|
|
|
|
|
# if a synthetic RETVAL has acquired an arg_num, then |
|
4011
|
|
|
|
|
|
|
# it's appeared in the signature (although without a |
|
4012
|
|
|
|
|
|
|
# type) and has become semi-real. |
|
4013
|
430
|
100
|
100
|
|
|
3734
|
&& !($param->{var} eq 'RETVAL' && defined($param->{arg_num})); |
|
|
|
|
100
|
|
|
|
|
|
4014
|
|
|
|
|
|
|
|
|
4015
|
271
|
100
|
|
|
|
722
|
if ($param->{is_length}) { |
|
4016
|
13
|
|
|
|
|
57
|
push @args, "XSauto_length_of_$param->{len_name}"; |
|
4017
|
13
|
|
|
|
|
39
|
push @types, $param->{type}; |
|
4018
|
13
|
|
|
|
|
37
|
next; |
|
4019
|
|
|
|
|
|
|
} |
|
4020
|
|
|
|
|
|
|
|
|
4021
|
258
|
100
|
|
|
|
828
|
if ($param->{var} eq 'SV *') { |
|
4022
|
|
|
|
|
|
|
#backcompat placeholder |
|
4023
|
1
|
|
|
|
|
27
|
$pxs->blurt("Error: parameter 'SV *' not valid as a C argument"); |
|
4024
|
1
|
|
|
|
|
9
|
next; |
|
4025
|
|
|
|
|
|
|
} |
|
4026
|
|
|
|
|
|
|
|
|
4027
|
257
|
|
|
|
|
518
|
my $io = $param->{in_out}; |
|
4028
|
257
|
100
|
|
|
|
928
|
$io = '' unless defined $io; |
|
4029
|
|
|
|
|
|
|
|
|
4030
|
|
|
|
|
|
|
# Ignore fake/alien stuff, except an OUTLIST arg, which |
|
4031
|
|
|
|
|
|
|
# isn't passed from perl (so no arg_num), but *is* passed to |
|
4032
|
|
|
|
|
|
|
# the C function and then back to perl. |
|
4033
|
257
|
100
|
100
|
|
|
1155
|
next unless defined $param->{arg_num} or $io eq 'OUTLIST'; |
|
4034
|
|
|
|
|
|
|
|
|
4035
|
245
|
|
|
|
|
484
|
my $a = $param->{var}; |
|
4036
|
245
|
100
|
100
|
|
|
1705
|
$a = "&$a" if $param->{is_addr} or $io =~ /OUT/; |
|
4037
|
245
|
|
|
|
|
654
|
push @args, $a; |
|
4038
|
245
|
|
|
|
|
593
|
my $t = $param->{type}; |
|
4039
|
245
|
100
|
|
|
|
989
|
push @types, defined $t ? $t : 'void*'; |
|
4040
|
|
|
|
|
|
|
} |
|
4041
|
|
|
|
|
|
|
|
|
4042
|
240
|
|
|
|
|
1184
|
return \@args, \@types; |
|
4043
|
|
|
|
|
|
|
} |
|
4044
|
|
|
|
|
|
|
|
|
4045
|
|
|
|
|
|
|
|
|
4046
|
|
|
|
|
|
|
# $self->proto_string(): |
|
4047
|
|
|
|
|
|
|
# |
|
4048
|
|
|
|
|
|
|
# return a string containing the perl prototype string for this XSUB, |
|
4049
|
|
|
|
|
|
|
# e.g. '$$;$$@'. |
|
4050
|
|
|
|
|
|
|
|
|
4051
|
|
|
|
|
|
|
sub proto_string { |
|
4052
|
44
|
|
|
44
|
|
97
|
my __PACKAGE__ $self = shift; |
|
4053
|
|
|
|
|
|
|
|
|
4054
|
|
|
|
|
|
|
# Generate a prototype entry for each param that's bound to a real |
|
4055
|
|
|
|
|
|
|
# arg. Use '$' unless the typemap for that param has specified an |
|
4056
|
|
|
|
|
|
|
# overridden entry. |
|
4057
|
|
|
|
|
|
|
my @p = map defined $_->{proto} ? $_->{proto} : '$', |
|
4058
|
|
|
|
|
|
|
grep defined $_->{arg_num} && $_->{arg_num} > 0, |
|
4059
|
44
|
100
|
66
|
|
|
3269
|
@{$self->{kids}}; |
|
|
44
|
|
|
|
|
576
|
|
|
4060
|
|
|
|
|
|
|
|
|
4061
|
44
|
|
|
|
|
152
|
my @sep = (';'); # separator between required and optional args |
|
4062
|
44
|
|
|
|
|
95
|
my $min = $self->{min_args}; |
|
4063
|
44
|
100
|
|
|
|
147
|
if ($min < $self->{nargs}) { |
|
4064
|
|
|
|
|
|
|
# has some default vals |
|
4065
|
8
|
|
|
|
|
38
|
splice (@p, $min, 0, ';'); |
|
4066
|
8
|
|
|
|
|
42
|
@sep = (); # separator already added |
|
4067
|
|
|
|
|
|
|
} |
|
4068
|
44
|
100
|
|
|
|
165
|
push @p, @sep, '@' if $self->{seen_ellipsis}; # '...' |
|
4069
|
44
|
|
|
|
|
285
|
return join '', @p; |
|
4070
|
|
|
|
|
|
|
} |
|
4071
|
|
|
|
|
|
|
|
|
4072
|
|
|
|
|
|
|
|
|
4073
|
|
|
|
|
|
|
# ====================================================================== |
|
4074
|
|
|
|
|
|
|
|
|
4075
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::xbody; |
|
4076
|
|
|
|
|
|
|
|
|
4077
|
|
|
|
|
|
|
# This node holds all the foo_part nodes which make up the body of an |
|
4078
|
|
|
|
|
|
|
# XSUB. Note that in the presence of CASE: keywords, an XSUB may have |
|
4079
|
|
|
|
|
|
|
# multiple xbodys, one per CASE. |
|
4080
|
|
|
|
|
|
|
# This node doesn't contain the signature, and nor is it responsible |
|
4081
|
|
|
|
|
|
|
# for emitting the code for the closing part of an XSUB e.g. the |
|
4082
|
|
|
|
|
|
|
# XSRETURN(N); there is only one of those per XSUB, so is handled by a |
|
4083
|
|
|
|
|
|
|
# higher-level node. |
|
4084
|
|
|
|
|
|
|
|
|
4085
|
19
|
|
|
19
|
|
104
|
BEGIN { $build_subclass->( |
|
4086
|
|
|
|
|
|
|
'ioparams', # Params object: per-body copy of params which accumulate |
|
4087
|
|
|
|
|
|
|
# extra info from any INPUT and OUTPUT sections (which can |
|
4088
|
|
|
|
|
|
|
# vary between different CASEs) |
|
4089
|
|
|
|
|
|
|
|
|
4090
|
|
|
|
|
|
|
# Node objects representing the various parts of an xbody. These |
|
4091
|
|
|
|
|
|
|
# are aliases of the same objects in @{$self->{kids}} for easier |
|
4092
|
|
|
|
|
|
|
# access. |
|
4093
|
|
|
|
|
|
|
'input_part', |
|
4094
|
|
|
|
|
|
|
'init_part', |
|
4095
|
|
|
|
|
|
|
'code_part', |
|
4096
|
|
|
|
|
|
|
'output_part', |
|
4097
|
|
|
|
|
|
|
'cleanup_part', |
|
4098
|
|
|
|
|
|
|
|
|
4099
|
|
|
|
|
|
|
# Misc parse state |
|
4100
|
|
|
|
|
|
|
|
|
4101
|
|
|
|
|
|
|
'seen_RETVAL_in_CODE', # Bool: have seen 'RETVAL' within a CODE block |
|
4102
|
|
|
|
|
|
|
'seen_autocall', # Bool: this xbody has an autocall node |
|
4103
|
|
|
|
|
|
|
'OUTPUT_SETMAGIC_state', # Bool: most recent value of SETMAGIC in an |
|
4104
|
|
|
|
|
|
|
# OUTPUT section. |
|
4105
|
|
|
|
|
|
|
|
|
4106
|
|
|
|
|
|
|
)}; |
|
4107
|
|
|
|
|
|
|
|
|
4108
|
|
|
|
|
|
|
|
|
4109
|
|
|
|
|
|
|
sub parse { |
|
4110
|
385
|
|
|
385
|
|
864
|
my __PACKAGE__ $self = shift; |
|
4111
|
385
|
|
|
|
|
701
|
my ExtUtils::ParseXS $pxs = shift; |
|
4112
|
385
|
|
|
|
|
747
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4113
|
|
|
|
|
|
|
|
|
4114
|
385
|
|
|
|
|
1581
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4115
|
|
|
|
|
|
|
|
|
4116
|
|
|
|
|
|
|
{ |
|
4117
|
|
|
|
|
|
|
# Make a per-xbody copy of the Params object, which will |
|
4118
|
|
|
|
|
|
|
# accumulate any extra info from (per-CASE) INPUT and OUTPUT |
|
4119
|
|
|
|
|
|
|
# sections. |
|
4120
|
|
|
|
|
|
|
|
|
4121
|
385
|
|
|
|
|
692
|
my $orig = $xsub->{decl}{params}; |
|
|
385
|
|
|
|
|
1034
|
|
|
4122
|
|
|
|
|
|
|
|
|
4123
|
|
|
|
|
|
|
# make a shallow copy |
|
4124
|
385
|
|
|
|
|
1350
|
my $ioparams = ExtUtils::ParseXS::Node::Params->new($orig); |
|
4125
|
|
|
|
|
|
|
|
|
4126
|
|
|
|
|
|
|
# now duplicate (deep copy) any Param objects and regenerate a new |
|
4127
|
|
|
|
|
|
|
# names-mapping hash |
|
4128
|
|
|
|
|
|
|
|
|
4129
|
385
|
|
|
|
|
1183
|
$ioparams->{kids} = []; |
|
4130
|
385
|
|
|
|
|
1060
|
$ioparams->{names} = {}; |
|
4131
|
|
|
|
|
|
|
|
|
4132
|
385
|
|
|
|
|
829
|
for my $op (@{$orig->{kids}}) { |
|
|
385
|
|
|
|
|
3002
|
|
|
4133
|
683
|
|
|
|
|
4103
|
my $p = ExtUtils::ParseXS::Node::IO_Param->new($op); |
|
4134
|
|
|
|
|
|
|
# don't copy the current proto state (from the most recent |
|
4135
|
|
|
|
|
|
|
# CASE) into the new CASE. |
|
4136
|
683
|
|
|
|
|
1901
|
undef $p->{proto}; |
|
4137
|
683
|
|
|
|
|
1282
|
push @{$ioparams->{kids}}, $p; |
|
|
683
|
|
|
|
|
1958
|
|
|
4138
|
683
|
|
|
|
|
2948
|
$ioparams->{names}{$p->{var}} = $p; |
|
4139
|
|
|
|
|
|
|
} |
|
4140
|
|
|
|
|
|
|
|
|
4141
|
385
|
|
|
|
|
15771
|
$self->{ioparams} = $ioparams; |
|
4142
|
|
|
|
|
|
|
} |
|
4143
|
|
|
|
|
|
|
|
|
4144
|
|
|
|
|
|
|
# by default, OUTPUT entries have SETMAGIC: ENABLE |
|
4145
|
385
|
|
|
|
|
1008
|
$self->{OUTPUT_SETMAGIC_state} = 1; |
|
4146
|
|
|
|
|
|
|
|
|
4147
|
385
|
|
|
|
|
1078
|
for my $part (qw(input_part init_part code_part output_part cleanup_part)) { |
|
4148
|
1903
|
|
|
|
|
25243
|
my $kid = "ExtUtils::ParseXS::Node::$part"->new(); |
|
4149
|
1903
|
50
|
|
|
|
11745
|
if ($kid->parse($pxs, $xsub, $self)) { |
|
4150
|
1897
|
|
|
|
|
2894
|
push @{$self->{kids}}, $kid; |
|
|
1897
|
|
|
|
|
5293
|
|
|
4151
|
1897
|
|
|
|
|
6620
|
$self->{$part} = $kid; |
|
4152
|
|
|
|
|
|
|
} |
|
4153
|
|
|
|
|
|
|
} |
|
4154
|
|
|
|
|
|
|
|
|
4155
|
379
|
|
|
|
|
1328
|
1; |
|
4156
|
|
|
|
|
|
|
} |
|
4157
|
|
|
|
|
|
|
|
|
4158
|
|
|
|
|
|
|
|
|
4159
|
|
|
|
|
|
|
sub as_code { |
|
4160
|
376
|
|
|
376
|
|
735
|
my __PACKAGE__ $self = shift; |
|
4161
|
376
|
|
|
|
|
758
|
my ExtUtils::ParseXS $pxs = shift; |
|
4162
|
376
|
|
|
|
|
695
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4163
|
|
|
|
|
|
|
|
|
4164
|
|
|
|
|
|
|
# Emit opening brace. With cmd-line switch "-except", prefix it with 'TRY' |
|
4165
|
376
|
50
|
|
|
|
2129
|
print +($pxs->{config_allow_exceptions} ? ' TRY' : '') |
|
4166
|
|
|
|
|
|
|
. " $open_brace\n"; |
|
4167
|
|
|
|
|
|
|
|
|
4168
|
376
|
50
|
|
|
|
2859
|
if ($self->{kids}) { |
|
4169
|
376
|
|
|
|
|
602
|
$_->as_code($pxs, $xsub, $self) for @{$self->{kids}}; |
|
|
376
|
|
|
|
|
1893
|
|
|
4170
|
|
|
|
|
|
|
} |
|
4171
|
|
|
|
|
|
|
|
|
4172
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
4173
|
|
|
|
|
|
|
# Emit trailers for the body of the XSUB |
|
4174
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
4175
|
|
|
|
|
|
|
|
|
4176
|
374
|
100
|
|
|
|
1292
|
if ($xsub->{SCOPE_enabled}) { |
|
4177
|
|
|
|
|
|
|
# the matching opens were emitted in input_part->as_code() |
|
4178
|
4
|
|
|
|
|
24
|
print " $close_brace\n"; |
|
4179
|
|
|
|
|
|
|
# PPCODE->as_code emits its own LEAVE and return, so this |
|
4180
|
|
|
|
|
|
|
# line would never be reached. |
|
4181
|
4
|
50
|
|
|
|
49
|
print " LEAVE;\n" unless $xsub->{seen_PPCODE}; |
|
4182
|
|
|
|
|
|
|
} |
|
4183
|
|
|
|
|
|
|
|
|
4184
|
|
|
|
|
|
|
# matches the $open_brace at the start of this function |
|
4185
|
374
|
|
|
|
|
2002
|
print " $close_brace\n"; |
|
4186
|
|
|
|
|
|
|
|
|
4187
|
374
|
50
|
|
|
|
3748
|
print $self->Q(<<"EOF") if $pxs->{config_allow_exceptions}; |
|
4188
|
|
|
|
|
|
|
| BEGHANDLERS |
|
4189
|
|
|
|
|
|
|
| CATCHALL |
|
4190
|
|
|
|
|
|
|
| sprintf(errbuf, "%s: %s\\tpropagated", Xname, Xreason); |
|
4191
|
|
|
|
|
|
|
| ENDHANDLERS |
|
4192
|
|
|
|
|
|
|
EOF |
|
4193
|
|
|
|
|
|
|
|
|
4194
|
|
|
|
|
|
|
} |
|
4195
|
|
|
|
|
|
|
|
|
4196
|
|
|
|
|
|
|
|
|
4197
|
|
|
|
|
|
|
# ====================================================================== |
|
4198
|
|
|
|
|
|
|
|
|
4199
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::input_part; |
|
4200
|
|
|
|
|
|
|
|
|
4201
|
19
|
|
|
19
|
|
123
|
BEGIN { $build_subclass->( |
|
4202
|
|
|
|
|
|
|
|
|
4203
|
|
|
|
|
|
|
# Str: used during code generation: |
|
4204
|
|
|
|
|
|
|
# a multi-line string containing lines of code to be emitted *after* |
|
4205
|
|
|
|
|
|
|
# all INPUT and PREINIT keywords have been processed. |
|
4206
|
|
|
|
|
|
|
'deferred_code_lines', |
|
4207
|
|
|
|
|
|
|
)}; |
|
4208
|
|
|
|
|
|
|
|
|
4209
|
|
|
|
|
|
|
|
|
4210
|
|
|
|
|
|
|
sub parse { |
|
4211
|
385
|
|
|
385
|
|
954
|
my __PACKAGE__ $self = shift; |
|
4212
|
385
|
|
|
|
|
784
|
my ExtUtils::ParseXS $pxs = shift; |
|
4213
|
385
|
|
|
|
|
1342
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4214
|
385
|
|
|
|
|
838
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4215
|
|
|
|
|
|
|
|
|
4216
|
385
|
|
|
|
|
1622
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4217
|
|
|
|
|
|
|
|
|
4218
|
|
|
|
|
|
|
# Process any implicit INPUT section. |
|
4219
|
|
|
|
|
|
|
{ |
|
4220
|
385
|
|
|
|
|
731
|
my $input = ExtUtils::ParseXS::Node::INPUT->new(); |
|
|
385
|
|
|
|
|
3638
|
|
|
4221
|
385
|
100
|
66
|
|
|
3166
|
if ( $input->parse($pxs, $xsub, $xbody) |
|
|
|
|
66
|
|
|
|
|
|
4222
|
|
|
|
|
|
|
&& $input->{kids} |
|
4223
|
100
|
|
|
|
|
511
|
&& @{$input->{kids}}) |
|
4224
|
|
|
|
|
|
|
{ |
|
4225
|
100
|
|
|
|
|
233
|
$input->{implicit} = 1; |
|
4226
|
100
|
|
|
|
|
168
|
push @{$self->{kids}}, $input; |
|
|
100
|
|
|
|
|
342
|
|
|
4227
|
|
|
|
|
|
|
} |
|
4228
|
|
|
|
|
|
|
} |
|
4229
|
|
|
|
|
|
|
|
|
4230
|
|
|
|
|
|
|
# Repeatedly look for INPUT or similar or generic keywords, |
|
4231
|
|
|
|
|
|
|
# parse the text following them, and add any resultant nodes |
|
4232
|
|
|
|
|
|
|
# as kids to the current node. |
|
4233
|
|
|
|
|
|
|
$self->parse_keywords( |
|
4234
|
385
|
|
|
|
|
2754
|
$pxs, $xsub, $xbody, |
|
4235
|
|
|
|
|
|
|
undef, # implies process as many keywords as possible |
|
4236
|
|
|
|
|
|
|
|
|
4237
|
|
|
|
|
|
|
"C_ARGS|INPUT|INTERFACE_MACRO|PREINIT|SCOPE|" |
|
4238
|
|
|
|
|
|
|
. $ExtUtils::ParseXS::Constants::generic_xsub_keywords_alt, |
|
4239
|
|
|
|
|
|
|
); |
|
4240
|
|
|
|
|
|
|
|
|
4241
|
|
|
|
|
|
|
# For each param, look up its INPUT typemap information now (at parse |
|
4242
|
|
|
|
|
|
|
# time) and save the results for use later in as_input_code(). |
|
4243
|
|
|
|
|
|
|
|
|
4244
|
380
|
|
|
|
|
906
|
for my $ioparam (@{$xbody->{ioparams}{kids}}) { |
|
|
380
|
|
|
|
|
2882
|
|
|
4245
|
|
|
|
|
|
|
# might be placeholder param which doesn't get emitted |
|
4246
|
689
|
100
|
|
|
|
3318
|
next unless defined $ioparam->{type}; |
|
4247
|
|
|
|
|
|
|
$ioparam->{input_typemap_vals} = |
|
4248
|
647
|
|
|
|
|
3571
|
[ $ioparam->lookup_input_typemap($pxs, $xsub, $xbody) ]; |
|
4249
|
|
|
|
|
|
|
} |
|
4250
|
|
|
|
|
|
|
|
|
4251
|
|
|
|
|
|
|
# Now that the type of each param is finalised, calculate its |
|
4252
|
|
|
|
|
|
|
# overridden prototype character, if any. |
|
4253
|
|
|
|
|
|
|
# |
|
4254
|
|
|
|
|
|
|
# Note that the type of a param can change during parsing, so when to |
|
4255
|
|
|
|
|
|
|
# call this method is significant. In particular: |
|
4256
|
|
|
|
|
|
|
# - THIS's type may be set provisionally based on the XSUB's package, |
|
4257
|
|
|
|
|
|
|
# then updated if it appears as a parameter or on an INPUT line. |
|
4258
|
|
|
|
|
|
|
# - typemaps can be overridden using the TYPEMAP keyword, so |
|
4259
|
|
|
|
|
|
|
# it's possible the typemap->proto() method will return something |
|
4260
|
|
|
|
|
|
|
# different by the time the proto field is used to emit boot code. |
|
4261
|
|
|
|
|
|
|
# - params can have different types (and thus typemap entries and |
|
4262
|
|
|
|
|
|
|
# proto chars) per CASE branch. |
|
4263
|
|
|
|
|
|
|
# So we calculate the per-case/xbody params' proto values here, and |
|
4264
|
|
|
|
|
|
|
# also use that value to update the per-XSUB value, warning if the |
|
4265
|
|
|
|
|
|
|
# value changes. |
|
4266
|
|
|
|
|
|
|
|
|
4267
|
380
|
|
|
|
|
1115
|
for my $ioparam (@{$xbody->{ioparams}{kids}}) { |
|
|
380
|
|
|
|
|
1423
|
|
|
4268
|
689
|
|
|
|
|
2488
|
$ioparam->set_proto($pxs); |
|
4269
|
689
|
|
|
|
|
1374
|
my $ioproto = $ioparam->{proto}; |
|
4270
|
689
|
|
|
|
|
1791
|
my $name = $ioparam->{var}; |
|
4271
|
689
|
50
|
|
|
|
1510
|
next unless defined $name; |
|
4272
|
689
|
100
|
|
|
|
1797
|
next unless $ioparam->{arg_num}; |
|
4273
|
|
|
|
|
|
|
|
|
4274
|
423
|
|
|
|
|
1882
|
my $param = $$xsub{decl}{params}{names}{$name}; |
|
4275
|
423
|
|
|
|
|
791
|
my $proto = $param->{proto}; |
|
4276
|
423
|
100
|
|
|
|
1071
|
$ioproto = '$' unless defined $ioproto; |
|
4277
|
423
|
100
|
100
|
|
|
1347
|
if (defined $proto and $proto ne $ioproto) { |
|
4278
|
2
|
|
|
|
|
15
|
$pxs->Warn("Warning: prototype for '$name' varies: '$proto' versus '$ioproto'"); |
|
4279
|
|
|
|
|
|
|
} |
|
4280
|
423
|
|
|
|
|
1306
|
$param->{proto} = $ioproto; |
|
4281
|
|
|
|
|
|
|
} |
|
4282
|
|
|
|
|
|
|
|
|
4283
|
380
|
|
|
|
|
1534
|
1; |
|
4284
|
|
|
|
|
|
|
} |
|
4285
|
|
|
|
|
|
|
|
|
4286
|
|
|
|
|
|
|
|
|
4287
|
|
|
|
|
|
|
sub as_code { |
|
4288
|
376
|
|
|
376
|
|
657
|
my __PACKAGE__ $self = shift; |
|
4289
|
376
|
|
|
|
|
704
|
my ExtUtils::ParseXS $pxs = shift; |
|
4290
|
376
|
|
|
|
|
773
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4291
|
376
|
|
|
|
|
635
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4292
|
|
|
|
|
|
|
|
|
4293
|
376
|
|
|
|
|
839
|
my $ioparams = $xbody->{ioparams}; |
|
4294
|
|
|
|
|
|
|
|
|
4295
|
|
|
|
|
|
|
# Lines to be emitted after PREINIT/INPUT. This may get populated |
|
4296
|
|
|
|
|
|
|
# by the as_code() methods we call of our kids. |
|
4297
|
376
|
|
|
|
|
1414
|
$self->{deferred_code_lines} = ""; |
|
4298
|
|
|
|
|
|
|
|
|
4299
|
376
|
100
|
|
|
|
1357
|
if ($self->{kids}) { |
|
4300
|
141
|
|
|
|
|
227
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
141
|
|
|
|
|
874
|
|
|
4301
|
|
|
|
|
|
|
} |
|
4302
|
|
|
|
|
|
|
|
|
4303
|
|
|
|
|
|
|
# The matching closes will be emitted in xbody->as_code() |
|
4304
|
376
|
100
|
|
|
|
1550
|
print $self->Q(<<"EOF") if $xsub->{SCOPE_enabled}; |
|
4305
|
|
|
|
|
|
|
| ENTER; |
|
4306
|
|
|
|
|
|
|
| $open_brace |
|
4307
|
|
|
|
|
|
|
EOF |
|
4308
|
|
|
|
|
|
|
|
|
4309
|
|
|
|
|
|
|
# Emit any 'char * CLASS' or 'Foo::Bar *THIS' declaration if needed |
|
4310
|
|
|
|
|
|
|
|
|
4311
|
376
|
|
|
|
|
744
|
for my $ioparam (grep $_->{is_synthetic}, @{$ioparams->{kids}}) { |
|
|
376
|
|
|
|
|
3371
|
|
|
4312
|
227
|
|
|
|
|
1056
|
$ioparam->as_input_code($pxs, $xsub, $xbody); |
|
4313
|
|
|
|
|
|
|
} |
|
4314
|
|
|
|
|
|
|
|
|
4315
|
|
|
|
|
|
|
# Recent code emits a dXSTARG in a tighter scope and under |
|
4316
|
|
|
|
|
|
|
# additional circumstances, but some XS code relies on TARG |
|
4317
|
|
|
|
|
|
|
# having been declared. So continue to declare it early under |
|
4318
|
|
|
|
|
|
|
# the original circumstances. |
|
4319
|
376
|
100
|
|
|
|
2380
|
if ($xsub->{decl}{return_type}{use_early_targ}) { |
|
4320
|
186
|
|
|
|
|
543
|
print "\tdXSTARG;\n"; |
|
4321
|
|
|
|
|
|
|
} |
|
4322
|
|
|
|
|
|
|
|
|
4323
|
|
|
|
|
|
|
# Emit declaration/init code for any parameters which were |
|
4324
|
|
|
|
|
|
|
# declared with a type or length(foo). Do the length() ones first. |
|
4325
|
|
|
|
|
|
|
|
|
4326
|
376
|
|
|
|
|
2086
|
for my $ioparam ( |
|
4327
|
|
|
|
|
|
|
grep $_->{is_ansi}, |
|
4328
|
|
|
|
|
|
|
( |
|
4329
|
376
|
|
|
|
|
1474
|
grep( $_->{is_length}, @{$ioparams->{kids}} ), |
|
4330
|
376
|
|
|
|
|
1916
|
grep(! $_->{is_length}, @{$ioparams->{kids}} ), |
|
4331
|
|
|
|
|
|
|
) |
|
4332
|
|
|
|
|
|
|
) |
|
4333
|
|
|
|
|
|
|
|
|
4334
|
|
|
|
|
|
|
{ |
|
4335
|
286
|
|
|
|
|
1212
|
$ioparam->as_input_code($pxs, $xsub, $xbody); |
|
4336
|
|
|
|
|
|
|
} |
|
4337
|
|
|
|
|
|
|
|
|
4338
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
4339
|
|
|
|
|
|
|
# All C variable declarations have now been emitted. It's now time |
|
4340
|
|
|
|
|
|
|
# to emit any code which goes before the main body (i.e. the CODE: |
|
4341
|
|
|
|
|
|
|
# etc or the implicit call to the wrapped function). |
|
4342
|
|
|
|
|
|
|
# ---------------------------------------------------------------- |
|
4343
|
|
|
|
|
|
|
|
|
4344
|
|
|
|
|
|
|
# Emit any code which has been deferred until all declarations |
|
4345
|
|
|
|
|
|
|
# have been done. This is typically INPUT typemaps which don't |
|
4346
|
|
|
|
|
|
|
# start with a simple '$var =' and so would not have been emitted |
|
4347
|
|
|
|
|
|
|
# at the variable declaration stage. |
|
4348
|
374
|
|
|
|
|
1530
|
print $self->{deferred_code_lines}; |
|
4349
|
|
|
|
|
|
|
} |
|
4350
|
|
|
|
|
|
|
|
|
4351
|
|
|
|
|
|
|
|
|
4352
|
|
|
|
|
|
|
# ====================================================================== |
|
4353
|
|
|
|
|
|
|
|
|
4354
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::init_part; |
|
4355
|
|
|
|
|
|
|
|
|
4356
|
19
|
|
|
19
|
|
308
|
BEGIN { $build_subclass->( |
|
4357
|
|
|
|
|
|
|
)}; |
|
4358
|
|
|
|
|
|
|
|
|
4359
|
|
|
|
|
|
|
|
|
4360
|
|
|
|
|
|
|
sub parse { |
|
4361
|
380
|
|
|
380
|
|
973
|
my __PACKAGE__ $self = shift; |
|
4362
|
380
|
|
|
|
|
733
|
my ExtUtils::ParseXS $pxs = shift; |
|
4363
|
380
|
|
|
|
|
639
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4364
|
380
|
|
|
|
|
620
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4365
|
|
|
|
|
|
|
|
|
4366
|
380
|
|
|
|
|
1359
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4367
|
|
|
|
|
|
|
|
|
4368
|
|
|
|
|
|
|
# Repeatedly look for INIT or generic keywords, |
|
4369
|
|
|
|
|
|
|
# parse the text following them, and add any resultant nodes |
|
4370
|
|
|
|
|
|
|
# as kids to the current node. |
|
4371
|
380
|
|
|
|
|
1867
|
$self->parse_keywords( |
|
4372
|
|
|
|
|
|
|
$pxs, $xsub, $xbody, |
|
4373
|
|
|
|
|
|
|
undef, # implies process as many keywords as possible |
|
4374
|
|
|
|
|
|
|
|
|
4375
|
|
|
|
|
|
|
"C_ARGS|INIT|INTERFACE|INTERFACE_MACRO|" |
|
4376
|
|
|
|
|
|
|
. $ExtUtils::ParseXS::Constants::generic_xsub_keywords_alt, |
|
4377
|
|
|
|
|
|
|
); |
|
4378
|
|
|
|
|
|
|
|
|
4379
|
380
|
|
|
|
|
1388
|
1; |
|
4380
|
|
|
|
|
|
|
} |
|
4381
|
|
|
|
|
|
|
|
|
4382
|
|
|
|
|
|
|
|
|
4383
|
|
|
|
|
|
|
sub as_code { |
|
4384
|
374
|
|
|
374
|
|
2383
|
my __PACKAGE__ $self = shift; |
|
4385
|
374
|
|
|
|
|
652
|
my ExtUtils::ParseXS $pxs = shift; |
|
4386
|
374
|
|
|
|
|
742
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4387
|
374
|
|
|
|
|
629
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4388
|
|
|
|
|
|
|
|
|
4389
|
374
|
100
|
|
|
|
2221
|
if ($self->{kids}) { |
|
4390
|
13
|
|
|
|
|
32
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
13
|
|
|
|
|
158
|
|
|
4391
|
|
|
|
|
|
|
} |
|
4392
|
|
|
|
|
|
|
} |
|
4393
|
|
|
|
|
|
|
|
|
4394
|
|
|
|
|
|
|
|
|
4395
|
|
|
|
|
|
|
# ====================================================================== |
|
4396
|
|
|
|
|
|
|
|
|
4397
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::code_part; |
|
4398
|
|
|
|
|
|
|
|
|
4399
|
19
|
|
|
19
|
|
93
|
BEGIN { $build_subclass->( |
|
4400
|
|
|
|
|
|
|
)}; |
|
4401
|
|
|
|
|
|
|
|
|
4402
|
|
|
|
|
|
|
|
|
4403
|
|
|
|
|
|
|
sub parse { |
|
4404
|
380
|
|
|
380
|
|
807
|
my __PACKAGE__ $self = shift; |
|
4405
|
380
|
|
|
|
|
731
|
my ExtUtils::ParseXS $pxs = shift; |
|
4406
|
380
|
|
|
|
|
718
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4407
|
380
|
|
|
|
|
772
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4408
|
|
|
|
|
|
|
|
|
4409
|
380
|
|
|
|
|
1534
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4410
|
|
|
|
|
|
|
|
|
4411
|
|
|
|
|
|
|
# Look for a CODE/PPCODE/NOT_IMPLEMENTED_YET keyword; if found, add |
|
4412
|
|
|
|
|
|
|
# the kid to the current node. |
|
4413
|
380
|
100
|
|
|
|
1314
|
return 1 if $self->parse_keywords( |
|
4414
|
|
|
|
|
|
|
$pxs, $xsub, $xbody, |
|
4415
|
|
|
|
|
|
|
1, # match at most one keyword |
|
4416
|
|
|
|
|
|
|
"CODE|PPCODE", |
|
4417
|
|
|
|
|
|
|
$keywords_flag_NOT_IMPLEMENTED_YET, |
|
4418
|
|
|
|
|
|
|
); |
|
4419
|
|
|
|
|
|
|
|
|
4420
|
|
|
|
|
|
|
# Didn't find a CODE keyword or similar, so auto-generate a call |
|
4421
|
|
|
|
|
|
|
# to the same-named C library function. |
|
4422
|
|
|
|
|
|
|
|
|
4423
|
258
|
|
|
|
|
2312
|
my $autocall = ExtUtils::ParseXS::Node::autocall->new(); |
|
4424
|
|
|
|
|
|
|
# mainly a NOOP, but sets line number etc and flags that autocall seen |
|
4425
|
258
|
50
|
|
|
|
2255
|
$autocall->parse($pxs, $xsub, $xbody) |
|
4426
|
|
|
|
|
|
|
or return; |
|
4427
|
258
|
|
|
|
|
446
|
push @{$self->{kids}}, $autocall; |
|
|
258
|
|
|
|
|
931
|
|
|
4428
|
|
|
|
|
|
|
|
|
4429
|
258
|
|
|
|
|
776
|
1; |
|
4430
|
|
|
|
|
|
|
} |
|
4431
|
|
|
|
|
|
|
|
|
4432
|
|
|
|
|
|
|
|
|
4433
|
|
|
|
|
|
|
sub as_code { |
|
4434
|
374
|
|
|
374
|
|
875
|
my __PACKAGE__ $self = shift; |
|
4435
|
374
|
|
|
|
|
797
|
my ExtUtils::ParseXS $pxs = shift; |
|
4436
|
374
|
|
|
|
|
701
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4437
|
374
|
|
|
|
|
731
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4438
|
|
|
|
|
|
|
|
|
4439
|
374
|
50
|
|
|
|
1163
|
if ($self->{kids}) { |
|
4440
|
374
|
|
|
|
|
830
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
374
|
|
|
|
|
2920
|
|
|
4441
|
|
|
|
|
|
|
} |
|
4442
|
|
|
|
|
|
|
} |
|
4443
|
|
|
|
|
|
|
|
|
4444
|
|
|
|
|
|
|
|
|
4445
|
|
|
|
|
|
|
# ====================================================================== |
|
4446
|
|
|
|
|
|
|
|
|
4447
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::output_part; |
|
4448
|
|
|
|
|
|
|
|
|
4449
|
19
|
|
|
19
|
|
96
|
BEGIN { $build_subclass->( |
|
4450
|
|
|
|
|
|
|
|
|
4451
|
|
|
|
|
|
|
# State during code emitting |
|
4452
|
|
|
|
|
|
|
|
|
4453
|
|
|
|
|
|
|
'targ_used', # Bool: the TARG has been allocated for this body, |
|
4454
|
|
|
|
|
|
|
# so is no longer available for use. |
|
4455
|
|
|
|
|
|
|
|
|
4456
|
|
|
|
|
|
|
'stack_was_reset', # Bool: An XSprePUSH was emitted, so return values |
|
4457
|
|
|
|
|
|
|
# should be PUSHed rather than just set. |
|
4458
|
|
|
|
|
|
|
)}; |
|
4459
|
|
|
|
|
|
|
|
|
4460
|
|
|
|
|
|
|
|
|
4461
|
|
|
|
|
|
|
sub parse { |
|
4462
|
379
|
|
|
379
|
|
805
|
my __PACKAGE__ $self = shift; |
|
4463
|
379
|
|
|
|
|
709
|
my ExtUtils::ParseXS $pxs = shift; |
|
4464
|
379
|
|
|
|
|
855
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4465
|
379
|
|
|
|
|
659
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4466
|
|
|
|
|
|
|
|
|
4467
|
379
|
|
|
|
|
1412
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4468
|
|
|
|
|
|
|
|
|
4469
|
|
|
|
|
|
|
# Repeatedly look for POSTCALL, OUTPUT or generic keywords, |
|
4470
|
|
|
|
|
|
|
# parse the text following them, and add any resultant nodes |
|
4471
|
|
|
|
|
|
|
# as kids to the current node. |
|
4472
|
|
|
|
|
|
|
# XXX POSTCALL is documented to precede OUTPUT, but here we allow |
|
4473
|
|
|
|
|
|
|
# them in any order and multiplicity. |
|
4474
|
379
|
|
|
|
|
2018
|
$self->parse_keywords( |
|
4475
|
|
|
|
|
|
|
$pxs, $xsub, $xbody, |
|
4476
|
|
|
|
|
|
|
undef, # implies process as many keywords as possible |
|
4477
|
|
|
|
|
|
|
"POSTCALL|OUTPUT|" |
|
4478
|
|
|
|
|
|
|
. $ExtUtils::ParseXS::Constants::generic_xsub_keywords_alt, |
|
4479
|
|
|
|
|
|
|
); |
|
4480
|
|
|
|
|
|
|
|
|
4481
|
|
|
|
|
|
|
# Work out whether a RETVAL SV will be returned. Note that this should |
|
4482
|
|
|
|
|
|
|
# be consistent across CASEs; we warn elsewhere if CODE_sets_ST0 isn't |
|
4483
|
|
|
|
|
|
|
# consistent. |
|
4484
|
|
|
|
|
|
|
|
|
4485
|
|
|
|
|
|
|
$xsub->{XSRETURN_count_basic} = |
|
4486
|
|
|
|
|
|
|
( $xsub->{CODE_sets_ST0} |
|
4487
|
|
|
|
|
|
|
or ( $xsub->{decl}{return_type}{type} ne "void" |
|
4488
|
|
|
|
|
|
|
&& !$xsub->{decl}{return_type}{no_output}) |
|
4489
|
379
|
100
|
100
|
|
|
6031
|
) |
|
4490
|
|
|
|
|
|
|
? 1 : 0; |
|
4491
|
|
|
|
|
|
|
|
|
4492
|
|
|
|
|
|
|
# For each param, look up its OUTPUT typemap information now (at parse |
|
4493
|
|
|
|
|
|
|
# time) and save the results for use later in as_output_code_(). |
|
4494
|
|
|
|
|
|
|
|
|
4495
|
379
|
|
|
|
|
884
|
for my $ioparam (@{$xbody->{ioparams}{kids}}) { |
|
|
379
|
|
|
|
|
2925
|
|
|
4496
|
|
|
|
|
|
|
# might be placeholder param which doesn't get emitted |
|
4497
|
|
|
|
|
|
|
# XXXX next unless defined $ioparam->{type}; |
|
4498
|
|
|
|
|
|
|
|
|
4499
|
|
|
|
|
|
|
next unless |
|
4500
|
|
|
|
|
|
|
# XXX simplify all this |
|
4501
|
|
|
|
|
|
|
( defined $ioparam->{in_out} |
|
4502
|
|
|
|
|
|
|
&& $ioparam->{in_out} =~ /OUT$/ |
|
4503
|
|
|
|
|
|
|
&& !$ioparam->{in_output} |
|
4504
|
|
|
|
|
|
|
) |
|
4505
|
|
|
|
|
|
|
|| |
|
4506
|
|
|
|
|
|
|
|
|
4507
|
|
|
|
|
|
|
( |
|
4508
|
|
|
|
|
|
|
$ioparam->{var} eq "RETVAL" |
|
4509
|
|
|
|
|
|
|
&& ( $ioparam->{in_output} |
|
4510
|
|
|
|
|
|
|
or ( $xbody->{seen_autocall} |
|
4511
|
|
|
|
|
|
|
&& $xsub->{decl}{return_type}{type} ne "void" |
|
4512
|
|
|
|
|
|
|
&& !$xsub->{decl}{return_type}{no_output} |
|
4513
|
|
|
|
|
|
|
) |
|
4514
|
|
|
|
|
|
|
) |
|
4515
|
|
|
|
|
|
|
) |
|
4516
|
|
|
|
|
|
|
|| |
|
4517
|
|
|
|
|
|
|
( |
|
4518
|
|
|
|
|
|
|
$ioparam->{in_output} |
|
4519
|
688
|
100
|
100
|
|
|
11910
|
&& $ioparam->{var} ne 'RETVAL' |
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
4520
|
|
|
|
|
|
|
) |
|
4521
|
|
|
|
|
|
|
; |
|
4522
|
|
|
|
|
|
|
|
|
4523
|
|
|
|
|
|
|
$ioparam->{output_typemap_vals} = |
|
4524
|
224
|
|
|
|
|
1231
|
[ $ioparam->lookup_output_typemap($pxs, $xsub, $xbody) ]; |
|
4525
|
|
|
|
|
|
|
} |
|
4526
|
|
|
|
|
|
|
|
|
4527
|
379
|
|
|
|
|
1079
|
my $out_num = $xsub->{XSRETURN_count_basic}; |
|
4528
|
|
|
|
|
|
|
|
|
4529
|
379
|
|
|
|
|
681
|
for my $ioparam (@{$xbody->{ioparams}{kids}}) { |
|
|
379
|
|
|
|
|
1283
|
|
|
4530
|
|
|
|
|
|
|
next unless defined $ioparam->{in_out} |
|
4531
|
688
|
100
|
100
|
|
|
2511
|
&& $ioparam->{in_out} =~ /OUTLIST$/; |
|
4532
|
|
|
|
|
|
|
$ioparam->{output_typemap_vals_outlist} = |
|
4533
|
44
|
|
|
|
|
236
|
[ $ioparam->lookup_output_typemap($pxs, $xsub, $xbody, $out_num++) ]; |
|
4534
|
|
|
|
|
|
|
} |
|
4535
|
|
|
|
|
|
|
|
|
4536
|
379
|
|
|
|
|
1164
|
1; |
|
4537
|
|
|
|
|
|
|
} |
|
4538
|
|
|
|
|
|
|
|
|
4539
|
|
|
|
|
|
|
|
|
4540
|
|
|
|
|
|
|
sub as_code { |
|
4541
|
374
|
|
|
374
|
|
4720
|
my __PACKAGE__ $self = shift; |
|
4542
|
374
|
|
|
|
|
1532
|
my ExtUtils::ParseXS $pxs = shift; |
|
4543
|
374
|
|
|
|
|
672
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4544
|
374
|
|
|
|
|
596
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4545
|
|
|
|
|
|
|
|
|
4546
|
|
|
|
|
|
|
# TARG is available for use within this body. |
|
4547
|
374
|
|
|
|
|
1190
|
$self->{targ_used} = 0; |
|
4548
|
|
|
|
|
|
|
|
|
4549
|
|
|
|
|
|
|
# SP still pointing at top arg |
|
4550
|
374
|
|
|
|
|
1094
|
$self->{stack_was_reset} = 0; |
|
4551
|
|
|
|
|
|
|
|
|
4552
|
374
|
100
|
|
|
|
1238
|
if ($self->{kids}) { |
|
4553
|
68
|
|
|
|
|
122
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
68
|
|
|
|
|
379
|
|
|
4554
|
|
|
|
|
|
|
} |
|
4555
|
|
|
|
|
|
|
|
|
4556
|
374
|
|
|
|
|
1748
|
my $ioparams = $xbody->{ioparams}; |
|
4557
|
|
|
|
|
|
|
|
|
4558
|
374
|
|
|
|
|
1221
|
my $retval = $ioparams->{names}{RETVAL}; |
|
4559
|
|
|
|
|
|
|
|
|
4560
|
|
|
|
|
|
|
# A CODE section using RETVAL must also have an OUTPUT entry |
|
4561
|
374
|
100
|
100
|
|
|
1791
|
if ( $xbody->{seen_RETVAL_in_CODE} |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
4562
|
|
|
|
|
|
|
and not ($retval && $retval->{in_output}) |
|
4563
|
|
|
|
|
|
|
and $xsub->{decl}{return_type}{type} ne 'void') |
|
4564
|
|
|
|
|
|
|
{ |
|
4565
|
3
|
|
|
|
|
31
|
$pxs->Warn( "Warning: found a 'CODE' section which seems to be " |
|
4566
|
|
|
|
|
|
|
. "using 'RETVAL' but no 'OUTPUT' section."); |
|
4567
|
|
|
|
|
|
|
} |
|
4568
|
|
|
|
|
|
|
|
|
4569
|
|
|
|
|
|
|
# Process any OUT vars: i.e. vars that are declared OUT in |
|
4570
|
|
|
|
|
|
|
# the XSUB's signature rather than in an OUTPUT section. |
|
4571
|
|
|
|
|
|
|
|
|
4572
|
374
|
|
|
|
|
771
|
for my $param ( |
|
4573
|
|
|
|
|
|
|
grep { |
|
4574
|
|
|
|
|
|
|
defined $_->{in_out} |
|
4575
|
|
|
|
|
|
|
&& $_->{in_out} =~ /OUT$/ |
|
4576
|
|
|
|
|
|
|
&& !$_->{in_output} |
|
4577
|
682
|
100
|
100
|
|
|
4566
|
} |
|
4578
|
374
|
|
|
|
|
1296
|
@{$ioparams->{kids}}) |
|
4579
|
|
|
|
|
|
|
{ |
|
4580
|
15
|
|
|
|
|
93
|
$param->as_output_code($pxs, $xsub, $xbody); |
|
4581
|
|
|
|
|
|
|
} |
|
4582
|
|
|
|
|
|
|
|
|
4583
|
374
|
|
|
|
|
1116
|
my $basic = $xsub->{XSRETURN_count_basic}; |
|
4584
|
374
|
|
|
|
|
1508
|
my $extra = $xsub->{XSRETURN_count_extra}; |
|
4585
|
|
|
|
|
|
|
|
|
4586
|
374
|
100
|
|
|
|
1068
|
if ($extra) { |
|
4587
|
|
|
|
|
|
|
# If there are any OUTLIST vars to be returned, we reset SP to |
|
4588
|
|
|
|
|
|
|
# the base of the stack frame and then PUSH any return values. |
|
4589
|
36
|
|
|
|
|
198
|
print "\tXSprePUSH;\n"; |
|
4590
|
36
|
|
|
|
|
346
|
$self->{stack_was_reset} = 1; |
|
4591
|
|
|
|
|
|
|
} |
|
4592
|
|
|
|
|
|
|
|
|
4593
|
|
|
|
|
|
|
# Extend the stack if we're going to return more values than were |
|
4594
|
|
|
|
|
|
|
# passed to us: which would consist of the GV or CV on the stack |
|
4595
|
|
|
|
|
|
|
# plus at least min_args at the time ENTERSUB was called. |
|
4596
|
|
|
|
|
|
|
|
|
4597
|
374
|
|
|
|
|
801
|
my $n = $basic + $extra; |
|
4598
|
|
|
|
|
|
|
print "\tEXTEND(SP,$n);\n" |
|
4599
|
374
|
100
|
|
|
|
1457
|
if $n > $ioparams->{min_args} + 1; |
|
4600
|
|
|
|
|
|
|
|
|
4601
|
|
|
|
|
|
|
# All OUTPUT done; now handle an implicit or deferred RETVAL: |
|
4602
|
|
|
|
|
|
|
# - OUTPUT_line::as_code() will have skipped/deferred any RETVAL line, |
|
4603
|
|
|
|
|
|
|
# - non-void CODE-less XSUBs have an implicit 'OUTPUT: RETVAL' |
|
4604
|
|
|
|
|
|
|
|
|
4605
|
374
|
100
|
100
|
|
|
6705
|
if ( ($retval && $retval->{in_output}) |
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
4606
|
|
|
|
|
|
|
or ( $xbody->{seen_autocall} |
|
4607
|
|
|
|
|
|
|
&& $xsub->{decl}{return_type}{type} ne "void" |
|
4608
|
|
|
|
|
|
|
&& !$xsub->{decl}{return_type}{no_output} |
|
4609
|
|
|
|
|
|
|
) |
|
4610
|
|
|
|
|
|
|
) |
|
4611
|
|
|
|
|
|
|
{ |
|
4612
|
|
|
|
|
|
|
# emit a deferred RETVAL from OUTPUT or implicit RETVAL |
|
4613
|
184
|
|
|
|
|
819
|
$retval->as_output_code($pxs, $xsub, $xbody); |
|
4614
|
|
|
|
|
|
|
} |
|
4615
|
|
|
|
|
|
|
|
|
4616
|
|
|
|
|
|
|
# Now that RETVAL is on the stack, also push any OUTLIST vars too |
|
4617
|
374
|
|
|
|
|
1260
|
for my $param (grep { defined $_->{in_out} |
|
4618
|
682
|
100
|
|
|
|
4444
|
&& $_->{in_out} =~ /OUTLIST$/ |
|
4619
|
|
|
|
|
|
|
} |
|
4620
|
374
|
|
|
|
|
1401
|
@{$ioparams->{kids}} |
|
4621
|
|
|
|
|
|
|
) { |
|
4622
|
44
|
|
|
|
|
307
|
$param->as_output_code($pxs, $xsub, $xbody, $basic++); |
|
4623
|
|
|
|
|
|
|
} |
|
4624
|
|
|
|
|
|
|
} |
|
4625
|
|
|
|
|
|
|
|
|
4626
|
|
|
|
|
|
|
|
|
4627
|
|
|
|
|
|
|
# ====================================================================== |
|
4628
|
|
|
|
|
|
|
|
|
4629
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::cleanup_part; |
|
4630
|
|
|
|
|
|
|
|
|
4631
|
19
|
|
|
19
|
|
119
|
BEGIN { $build_subclass->( |
|
4632
|
|
|
|
|
|
|
)}; |
|
4633
|
|
|
|
|
|
|
|
|
4634
|
|
|
|
|
|
|
|
|
4635
|
|
|
|
|
|
|
sub parse { |
|
4636
|
379
|
|
|
379
|
|
742
|
my __PACKAGE__ $self = shift; |
|
4637
|
379
|
|
|
|
|
828
|
my ExtUtils::ParseXS $pxs = shift; |
|
4638
|
379
|
|
|
|
|
835
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4639
|
379
|
|
|
|
|
699
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4640
|
|
|
|
|
|
|
|
|
4641
|
379
|
|
|
|
|
1363
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4642
|
|
|
|
|
|
|
|
|
4643
|
|
|
|
|
|
|
# Repeatedly look for CLEANUP or generic keywords, |
|
4644
|
|
|
|
|
|
|
# parse the text following them, and add any resultant nodes |
|
4645
|
|
|
|
|
|
|
# as kids to the current node. |
|
4646
|
379
|
|
|
|
|
1714
|
$self->parse_keywords( |
|
4647
|
|
|
|
|
|
|
$pxs, $xsub, $xbody, |
|
4648
|
|
|
|
|
|
|
undef, # implies process as many keywords as possible |
|
4649
|
|
|
|
|
|
|
"CLEANUP|" |
|
4650
|
|
|
|
|
|
|
. $ExtUtils::ParseXS::Constants::generic_xsub_keywords_alt, |
|
4651
|
|
|
|
|
|
|
); |
|
4652
|
|
|
|
|
|
|
|
|
4653
|
379
|
|
|
|
|
1086
|
1; |
|
4654
|
|
|
|
|
|
|
} |
|
4655
|
|
|
|
|
|
|
|
|
4656
|
|
|
|
|
|
|
|
|
4657
|
|
|
|
|
|
|
sub as_code { |
|
4658
|
374
|
|
|
374
|
|
1140
|
my __PACKAGE__ $self = shift; |
|
4659
|
374
|
|
|
|
|
762
|
my ExtUtils::ParseXS $pxs = shift; |
|
4660
|
374
|
|
|
|
|
700
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4661
|
374
|
|
|
|
|
758
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4662
|
|
|
|
|
|
|
|
|
4663
|
374
|
100
|
|
|
|
1504
|
if ($self->{kids}) { |
|
4664
|
3
|
|
|
|
|
11
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
3
|
|
|
|
|
40
|
|
|
4665
|
|
|
|
|
|
|
} |
|
4666
|
|
|
|
|
|
|
} |
|
4667
|
|
|
|
|
|
|
|
|
4668
|
|
|
|
|
|
|
|
|
4669
|
|
|
|
|
|
|
# ====================================================================== |
|
4670
|
|
|
|
|
|
|
|
|
4671
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::oneline; |
|
4672
|
|
|
|
|
|
|
|
|
4673
|
|
|
|
|
|
|
# Generic base class for keyword Nodes which consume only a single source |
|
4674
|
|
|
|
|
|
|
# line, such as 'SCOPE: ENABLE'. |
|
4675
|
|
|
|
|
|
|
# On entry, $self->lines[0] will be any text (on the same line) which |
|
4676
|
|
|
|
|
|
|
# follows the keyword. |
|
4677
|
|
|
|
|
|
|
|
|
4678
|
19
|
|
|
19
|
|
187
|
BEGIN { $build_subclass->( |
|
4679
|
|
|
|
|
|
|
'text', # Str: any text following the keyword |
|
4680
|
|
|
|
|
|
|
)}; |
|
4681
|
|
|
|
|
|
|
|
|
4682
|
|
|
|
|
|
|
|
|
4683
|
|
|
|
|
|
|
sub parse { |
|
4684
|
697
|
|
|
697
|
|
1352
|
my __PACKAGE__ $self = shift; |
|
4685
|
697
|
|
|
|
|
3038
|
my ExtUtils::ParseXS $pxs = shift; |
|
4686
|
|
|
|
|
|
|
|
|
4687
|
697
|
|
|
|
|
2391
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4688
|
697
|
|
|
|
|
1177
|
my $s = shift @{$pxs->{line}}; |
|
|
697
|
|
|
|
|
2002
|
|
|
4689
|
697
|
|
|
|
|
3707
|
ExtUtils::ParseXS::Utilities::trim_whitespace($s); |
|
4690
|
697
|
|
|
|
|
2259
|
$self->{text} = $s; |
|
4691
|
697
|
|
|
|
|
1376
|
1; |
|
4692
|
|
|
|
|
|
|
} |
|
4693
|
|
|
|
|
|
|
|
|
4694
|
|
|
|
|
|
|
|
|
4695
|
|
|
|
|
|
|
# ====================================================================== |
|
4696
|
|
|
|
|
|
|
|
|
4697
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::MODULE; |
|
4698
|
|
|
|
|
|
|
|
|
4699
|
|
|
|
|
|
|
# Process a MODULE keyword, e.g. |
|
4700
|
|
|
|
|
|
|
# |
|
4701
|
|
|
|
|
|
|
# MODULE = Foo PACKAGE = Foo::Bar PREFIX = foo_ |
|
4702
|
|
|
|
|
|
|
|
|
4703
|
19
|
|
|
19
|
|
100
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
4704
|
|
|
|
|
|
|
'module', # Str |
|
4705
|
|
|
|
|
|
|
'package', # Str: may be '' |
|
4706
|
|
|
|
|
|
|
'prefix', # Str: may be '' |
|
4707
|
|
|
|
|
|
|
)}; |
|
4708
|
|
|
|
|
|
|
|
|
4709
|
|
|
|
|
|
|
|
|
4710
|
|
|
|
|
|
|
sub parse { |
|
4711
|
323
|
|
|
323
|
|
759
|
my __PACKAGE__ $self = shift; |
|
4712
|
323
|
|
|
|
|
751
|
my ExtUtils::ParseXS $pxs = shift; |
|
4713
|
|
|
|
|
|
|
|
|
4714
|
323
|
|
|
|
|
3181
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4715
|
|
|
|
|
|
|
|
|
4716
|
323
|
|
|
|
|
1047
|
my $line = $self->{text}; |
|
4717
|
323
|
100
|
|
|
|
6577
|
my ($module, $pkg, $prefix) = $line =~ |
|
4718
|
|
|
|
|
|
|
/^ |
|
4719
|
|
|
|
|
|
|
MODULE \s* = \s* ([\w:]+) |
|
4720
|
|
|
|
|
|
|
(?: \s+ PACKAGE \s* = \s* ([\w:]+))? |
|
4721
|
|
|
|
|
|
|
(?: \s+ PREFIX \s* = \s* (\S+))? |
|
4722
|
|
|
|
|
|
|
\s* |
|
4723
|
|
|
|
|
|
|
$/x |
|
4724
|
|
|
|
|
|
|
or $pxs->death("Error: unparseable MODULE line: '$line'"); |
|
4725
|
|
|
|
|
|
|
|
|
4726
|
319
|
|
|
|
|
1373
|
$self->{module} = $module; |
|
4727
|
319
|
|
|
|
|
1289
|
($pxs->{MODULE_cname} = $module) =~ s/\W/_/g; |
|
4728
|
|
|
|
|
|
|
|
|
4729
|
319
|
50
|
|
|
|
1734
|
$self->{package} = $pxs->{PACKAGE_name} = defined($pkg) ? $pkg : ''; |
|
4730
|
|
|
|
|
|
|
|
|
4731
|
319
|
100
|
|
|
|
1803
|
$self->{prefix} = $prefix = defined($prefix) ? $prefix : ''; |
|
4732
|
319
|
|
|
|
|
1388
|
$pxs->{PREFIX_pattern} = quotemeta($prefix); |
|
4733
|
|
|
|
|
|
|
|
|
4734
|
319
|
|
|
|
|
1929
|
($pxs->{PACKAGE_C_name} = $pxs->{PACKAGE_name}) =~ tr/:/_/; |
|
4735
|
|
|
|
|
|
|
|
|
4736
|
319
|
|
|
|
|
1233
|
$pxs->{PACKAGE_class} = $pxs->{PACKAGE_name}; |
|
4737
|
319
|
50
|
|
|
|
2136
|
$pxs->{PACKAGE_class} .= "::" if $pxs->{PACKAGE_class} ne ""; |
|
4738
|
|
|
|
|
|
|
|
|
4739
|
319
|
|
|
|
|
1156
|
1; |
|
4740
|
|
|
|
|
|
|
} |
|
4741
|
|
|
|
|
|
|
|
|
4742
|
|
|
|
|
|
|
|
|
4743
|
|
|
|
|
|
|
# ====================================================================== |
|
4744
|
|
|
|
|
|
|
|
|
4745
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::NOT_IMPLEMENTED_YET; |
|
4746
|
|
|
|
|
|
|
|
|
4747
|
|
|
|
|
|
|
# Handle NOT_IMPLEMENTED_YET pseudo-keyword |
|
4748
|
|
|
|
|
|
|
|
|
4749
|
19
|
|
|
19
|
|
106
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
4750
|
|
|
|
|
|
|
)}; |
|
4751
|
|
|
|
|
|
|
|
|
4752
|
|
|
|
|
|
|
sub as_code { |
|
4753
|
2
|
|
|
2
|
|
12
|
my __PACKAGE__ $self = shift; |
|
4754
|
2
|
|
|
|
|
7
|
my ExtUtils::ParseXS $pxs = shift; |
|
4755
|
2
|
|
|
|
|
12
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4756
|
|
|
|
|
|
|
|
|
4757
|
2
|
|
|
|
|
18
|
print "\n" |
|
4758
|
|
|
|
|
|
|
. "\tPerl_croak(aTHX_ \"$xsub->{decl}{full_perl_name}: " |
|
4759
|
|
|
|
|
|
|
. "not implemented yet\");\n"; |
|
4760
|
|
|
|
|
|
|
} |
|
4761
|
|
|
|
|
|
|
|
|
4762
|
|
|
|
|
|
|
|
|
4763
|
|
|
|
|
|
|
# ====================================================================== |
|
4764
|
|
|
|
|
|
|
|
|
4765
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::CASE; |
|
4766
|
|
|
|
|
|
|
|
|
4767
|
|
|
|
|
|
|
# Process the 'CASE:' keyword |
|
4768
|
|
|
|
|
|
|
|
|
4769
|
19
|
|
|
19
|
|
84
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
4770
|
|
|
|
|
|
|
'cond', # Str: the C code of the condition for the CASE, or '' |
|
4771
|
|
|
|
|
|
|
'num', # Int: which CASE number this is (starting at 1) |
|
4772
|
|
|
|
|
|
|
)}; |
|
4773
|
|
|
|
|
|
|
|
|
4774
|
|
|
|
|
|
|
|
|
4775
|
|
|
|
|
|
|
sub parse { |
|
4776
|
39
|
|
|
39
|
|
221
|
my __PACKAGE__ $self = shift; |
|
4777
|
39
|
|
|
|
|
183
|
my ExtUtils::ParseXS $pxs = shift; |
|
4778
|
|
|
|
|
|
|
|
|
4779
|
39
|
|
|
|
|
343
|
$self->SUPER::parse($pxs); # set file/line_no/text |
|
4780
|
39
|
|
|
|
|
129
|
$self->{cond} = $self->{text}; |
|
4781
|
|
|
|
|
|
|
# Note that setting num, and consistency checking (like "else" |
|
4782
|
|
|
|
|
|
|
# without "if") is done by the caller, Node::xsub. |
|
4783
|
39
|
|
|
|
|
1988
|
1; |
|
4784
|
|
|
|
|
|
|
} |
|
4785
|
|
|
|
|
|
|
|
|
4786
|
|
|
|
|
|
|
|
|
4787
|
|
|
|
|
|
|
sub as_code { |
|
4788
|
38
|
|
|
38
|
|
174
|
my __PACKAGE__ $self = shift; |
|
4789
|
38
|
|
|
|
|
118
|
my ExtUtils::ParseXS $pxs = shift; |
|
4790
|
38
|
|
|
|
|
73
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4791
|
|
|
|
|
|
|
|
|
4792
|
38
|
|
|
|
|
181
|
my $cond = $self->{cond}; |
|
4793
|
38
|
100
|
|
|
|
247
|
$cond = " if ($cond)" if length $cond; |
|
4794
|
38
|
100
|
|
|
|
254
|
print " ", ($self->{num} > 1 ? " else" : ""), $cond, "\n"; |
|
4795
|
38
|
|
|
|
|
315
|
$_->as_code($pxs, $xsub) for @{$self->{kids}}; |
|
|
38
|
|
|
|
|
233
|
|
|
4796
|
|
|
|
|
|
|
} |
|
4797
|
|
|
|
|
|
|
|
|
4798
|
|
|
|
|
|
|
|
|
4799
|
|
|
|
|
|
|
# ====================================================================== |
|
4800
|
|
|
|
|
|
|
|
|
4801
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::autocall; |
|
4802
|
|
|
|
|
|
|
|
|
4803
|
|
|
|
|
|
|
# Handle an empty XSUB body (i.e. no CODE or PPCODE) |
|
4804
|
|
|
|
|
|
|
# by auto-generating a call to a C library function of the same |
|
4805
|
|
|
|
|
|
|
# name |
|
4806
|
|
|
|
|
|
|
|
|
4807
|
19
|
|
|
19
|
|
108
|
BEGIN { $build_subclass->( |
|
4808
|
|
|
|
|
|
|
'args', # Str: text to use for auto function call arguments |
|
4809
|
|
|
|
|
|
|
'types', # Str: text to use for auto function type declaration |
|
4810
|
|
|
|
|
|
|
)}; |
|
4811
|
|
|
|
|
|
|
|
|
4812
|
|
|
|
|
|
|
|
|
4813
|
|
|
|
|
|
|
sub parse { |
|
4814
|
258
|
|
|
258
|
|
671
|
my __PACKAGE__ $self = shift; |
|
4815
|
258
|
|
|
|
|
578
|
my ExtUtils::ParseXS $pxs = shift; |
|
4816
|
258
|
|
|
|
|
486
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4817
|
258
|
|
|
|
|
497
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4818
|
|
|
|
|
|
|
|
|
4819
|
258
|
|
|
|
|
928
|
$self->SUPER::parse($pxs); # set file/line_no |
|
4820
|
|
|
|
|
|
|
|
|
4821
|
258
|
|
|
|
|
735
|
$xbody->{seen_autocall} = 1; |
|
4822
|
|
|
|
|
|
|
|
|
4823
|
258
|
|
|
|
|
582
|
my $ioparams = $xbody->{ioparams}; |
|
4824
|
258
|
|
|
|
|
1322
|
my ($args, $types); |
|
4825
|
258
|
|
|
|
|
732
|
$args = $ioparams->{auto_function_sig_override}; # C_ARGS |
|
4826
|
258
|
100
|
|
|
|
1046
|
if (defined $args) { |
|
4827
|
|
|
|
|
|
|
# Try to determine the C_ARGS types; for example, with |
|
4828
|
|
|
|
|
|
|
# |
|
4829
|
|
|
|
|
|
|
# foo(short s, int i, long l) |
|
4830
|
|
|
|
|
|
|
# C_ARGS: s, l |
|
4831
|
|
|
|
|
|
|
# |
|
4832
|
|
|
|
|
|
|
# set $types to ['short', 'long']. May give the wrong results if |
|
4833
|
|
|
|
|
|
|
# C_ARGS isn't just a simple list of parameter names |
|
4834
|
18
|
|
|
|
|
147
|
for my $var (split /,/, $args) { |
|
4835
|
37
|
|
|
|
|
182
|
$var =~ s/^\s+//; |
|
4836
|
37
|
|
|
|
|
104
|
$var =~ s/\s+$//; |
|
4837
|
37
|
|
|
|
|
87
|
my $param = $ioparams->{names}{$var}; |
|
4838
|
|
|
|
|
|
|
# 'void*' is a desperate guess if no such parameter |
|
4839
|
|
|
|
|
|
|
push @$types, ($param && defined $param->{type}) |
|
4840
|
37
|
100
|
66
|
|
|
262
|
? $param->{type} : 'void*'; |
|
4841
|
|
|
|
|
|
|
} |
|
4842
|
18
|
|
|
|
|
63
|
$self->{args} = $args; |
|
4843
|
|
|
|
|
|
|
} |
|
4844
|
|
|
|
|
|
|
else { |
|
4845
|
240
|
|
|
|
|
1650
|
($args, $types) = $ioparams->C_func_signature($pxs); |
|
4846
|
240
|
|
|
|
|
1185
|
$self->{args} = join ', ', @$args; |
|
4847
|
|
|
|
|
|
|
} |
|
4848
|
|
|
|
|
|
|
|
|
4849
|
258
|
50
|
|
|
|
1004
|
unless ($pxs->{config_RetainCplusplusHierarchicalTypes}) { |
|
4850
|
258
|
|
|
|
|
1750
|
s/:/_/g for @$types; |
|
4851
|
|
|
|
|
|
|
} |
|
4852
|
258
|
|
|
|
|
926
|
$self->{types} = join ', ', @$types; |
|
4853
|
|
|
|
|
|
|
|
|
4854
|
258
|
|
|
|
|
1324
|
1; |
|
4855
|
|
|
|
|
|
|
} |
|
4856
|
|
|
|
|
|
|
|
|
4857
|
|
|
|
|
|
|
|
|
4858
|
|
|
|
|
|
|
sub as_code { |
|
4859
|
254
|
|
|
254
|
|
4091
|
my __PACKAGE__ $self = shift; |
|
4860
|
254
|
|
|
|
|
542
|
my ExtUtils::ParseXS $pxs = shift; |
|
4861
|
254
|
|
|
|
|
483
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
4862
|
254
|
|
|
|
|
416
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
4863
|
|
|
|
|
|
|
|
|
4864
|
254
|
|
|
|
|
966
|
my $class = $xsub->{decl}{class}; |
|
4865
|
254
|
|
|
|
|
750
|
my $name = $xsub->{decl}{name}; |
|
4866
|
|
|
|
|
|
|
|
|
4867
|
254
|
100
|
100
|
|
|
1255
|
if ( defined $class |
|
4868
|
|
|
|
|
|
|
and $name eq "DESTROY") |
|
4869
|
|
|
|
|
|
|
{ |
|
4870
|
|
|
|
|
|
|
# Emit a default body for a C++ DESTROY method: "delete THIS;" |
|
4871
|
1
|
|
|
|
|
9
|
print "\n\t"; |
|
4872
|
1
|
|
|
|
|
15
|
print "delete THIS;\n"; |
|
4873
|
|
|
|
|
|
|
|
|
4874
|
|
|
|
|
|
|
} |
|
4875
|
|
|
|
|
|
|
else { |
|
4876
|
|
|
|
|
|
|
# Emit a default body: this will be a call to the function being |
|
4877
|
|
|
|
|
|
|
# wrapped. Typically: |
|
4878
|
|
|
|
|
|
|
# RETVAL = foo(args); |
|
4879
|
|
|
|
|
|
|
# with the function name being appropriately modified when it's |
|
4880
|
|
|
|
|
|
|
# a C++ new() method etc. |
|
4881
|
|
|
|
|
|
|
|
|
4882
|
253
|
|
|
|
|
841
|
print "\n\t"; |
|
4883
|
|
|
|
|
|
|
|
|
4884
|
253
|
|
|
|
|
3187
|
my $ret_type = $xsub->{decl}{return_type}{type}; |
|
4885
|
253
|
100
|
|
|
|
936
|
if ($ret_type ne "void") { |
|
4886
|
149
|
|
|
|
|
953
|
print "RETVAL = "; |
|
4887
|
|
|
|
|
|
|
} |
|
4888
|
|
|
|
|
|
|
|
|
4889
|
253
|
100
|
|
|
|
968
|
if (defined $class) { |
|
4890
|
26
|
100
|
|
|
|
151
|
if ($xsub->{decl}{return_type}{static}) { |
|
4891
|
|
|
|
|
|
|
# it has a return type of 'static foo' |
|
4892
|
4
|
100
|
|
|
|
22
|
if ($name eq 'new') { |
|
4893
|
2
|
|
|
|
|
10
|
$name = "$class"; |
|
4894
|
|
|
|
|
|
|
} |
|
4895
|
|
|
|
|
|
|
else { |
|
4896
|
2
|
|
|
|
|
12
|
print "${class}::"; |
|
4897
|
|
|
|
|
|
|
} |
|
4898
|
|
|
|
|
|
|
} |
|
4899
|
|
|
|
|
|
|
else { |
|
4900
|
22
|
100
|
|
|
|
98
|
if ($name eq 'new') { |
|
4901
|
7
|
|
|
|
|
24
|
$name .= " $class"; |
|
4902
|
|
|
|
|
|
|
} |
|
4903
|
|
|
|
|
|
|
else { |
|
4904
|
15
|
|
|
|
|
58
|
print "THIS->"; |
|
4905
|
|
|
|
|
|
|
} |
|
4906
|
|
|
|
|
|
|
} |
|
4907
|
|
|
|
|
|
|
} |
|
4908
|
|
|
|
|
|
|
|
|
4909
|
|
|
|
|
|
|
# Handle "xsubpp -s=strip_prefix" hack |
|
4910
|
253
|
|
|
|
|
769
|
my $strip = $pxs->{config_strip_c_func_prefix}; |
|
4911
|
253
|
50
|
|
|
|
704
|
$name =~ s/^\Q$strip// |
|
4912
|
|
|
|
|
|
|
if defined $strip; |
|
4913
|
|
|
|
|
|
|
|
|
4914
|
253
|
100
|
66
|
|
|
3028
|
if ( $xsub->{seen_INTERFACE} |
|
4915
|
|
|
|
|
|
|
or $xsub->{seen_INTERFACE_MACRO}) |
|
4916
|
|
|
|
|
|
|
{ |
|
4917
|
|
|
|
|
|
|
$ret_type =~ s/:/_/g |
|
4918
|
9
|
50
|
|
|
|
114
|
unless $pxs->{config_RetainCplusplusHierarchicalTypes}; |
|
4919
|
9
|
|
|
|
|
48
|
$name = "(($ret_type (*)($self->{types}))(XSFUNCTION))"; |
|
4920
|
|
|
|
|
|
|
} |
|
4921
|
|
|
|
|
|
|
|
|
4922
|
253
|
|
|
|
|
1456
|
print "$name($self->{args});\n"; |
|
4923
|
|
|
|
|
|
|
|
|
4924
|
|
|
|
|
|
|
} |
|
4925
|
|
|
|
|
|
|
} |
|
4926
|
|
|
|
|
|
|
|
|
4927
|
|
|
|
|
|
|
|
|
4928
|
|
|
|
|
|
|
# ====================================================================== |
|
4929
|
|
|
|
|
|
|
|
|
4930
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::FALLBACK; |
|
4931
|
|
|
|
|
|
|
|
|
4932
|
|
|
|
|
|
|
# Process the 'FALLBACK' keyword. |
|
4933
|
|
|
|
|
|
|
# Its main effect is to update $pxs->{map_package_to_fallback_string} with |
|
4934
|
|
|
|
|
|
|
# the fallback value for the current package. That is later used to plant |
|
4935
|
|
|
|
|
|
|
# boot code to set ${package}::() to a true/false/undef value. |
|
4936
|
|
|
|
|
|
|
|
|
4937
|
19
|
|
|
19
|
|
144
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
4938
|
|
|
|
|
|
|
'value', # Str: TRUE, FALSE or UNDEF |
|
4939
|
|
|
|
|
|
|
)}; |
|
4940
|
|
|
|
|
|
|
|
|
4941
|
|
|
|
|
|
|
|
|
4942
|
|
|
|
|
|
|
sub parse { |
|
4943
|
1
|
|
|
1
|
|
2
|
my __PACKAGE__ $self = shift; |
|
4944
|
1
|
|
|
|
|
7
|
my ExtUtils::ParseXS $pxs = shift; |
|
4945
|
|
|
|
|
|
|
|
|
4946
|
1
|
|
|
|
|
7
|
$self->SUPER::parse($pxs); # set file/line_no/text |
|
4947
|
|
|
|
|
|
|
|
|
4948
|
|
|
|
|
|
|
# The rest of the current line should contain either TRUE, |
|
4949
|
|
|
|
|
|
|
# FALSE or UNDEF, but we also secretly allow 0 or 1 and lower/mixed |
|
4950
|
|
|
|
|
|
|
# case. |
|
4951
|
|
|
|
|
|
|
|
|
4952
|
1
|
|
|
|
|
3
|
my $s = $self->{text}; |
|
4953
|
|
|
|
|
|
|
|
|
4954
|
1
|
50
|
|
|
|
5
|
$s = 'TRUE' if $s eq '1'; |
|
4955
|
1
|
50
|
|
|
|
16
|
$s = 'FALSE' if $s eq '0'; |
|
4956
|
1
|
|
|
|
|
4
|
$s = uc($s); |
|
4957
|
|
|
|
|
|
|
|
|
4958
|
1
|
50
|
|
|
|
12
|
$self->death("Error: FALLBACK: TRUE/FALSE/UNDEF") |
|
4959
|
|
|
|
|
|
|
unless $s =~ /^(TRUE|FALSE|UNDEF)$/; |
|
4960
|
|
|
|
|
|
|
|
|
4961
|
1
|
|
|
|
|
3
|
$self->{value} = $s; |
|
4962
|
1
|
|
|
|
|
7
|
$pxs->{map_package_to_fallback_string}{$pxs->{PACKAGE_name}} = $s; |
|
4963
|
|
|
|
|
|
|
|
|
4964
|
1
|
|
|
|
|
5
|
1; |
|
4965
|
|
|
|
|
|
|
} |
|
4966
|
|
|
|
|
|
|
|
|
4967
|
|
|
|
|
|
|
|
|
4968
|
|
|
|
|
|
|
# ====================================================================== |
|
4969
|
|
|
|
|
|
|
|
|
4970
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::REQUIRE; |
|
4971
|
|
|
|
|
|
|
|
|
4972
|
|
|
|
|
|
|
# Process the 'REQUIRE' keyword. |
|
4973
|
|
|
|
|
|
|
|
|
4974
|
19
|
|
|
19
|
|
94
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
4975
|
|
|
|
|
|
|
'version', # Str: the minimum version allowed, e.g.'1.23' |
|
4976
|
|
|
|
|
|
|
)}; |
|
4977
|
|
|
|
|
|
|
|
|
4978
|
|
|
|
|
|
|
|
|
4979
|
|
|
|
|
|
|
sub parse { |
|
4980
|
1
|
|
|
1
|
|
3
|
my __PACKAGE__ $self = shift; |
|
4981
|
1
|
|
|
|
|
8
|
my ExtUtils::ParseXS $pxs = shift; |
|
4982
|
|
|
|
|
|
|
|
|
4983
|
1
|
|
|
|
|
6
|
$self->SUPER::parse($pxs); # set file/line_no/text |
|
4984
|
|
|
|
|
|
|
|
|
4985
|
1
|
|
|
|
|
3
|
my $ver = $self->{text}; |
|
4986
|
|
|
|
|
|
|
|
|
4987
|
1
|
50
|
|
|
|
4
|
$pxs->death("Error: REQUIRE expects a version number") |
|
4988
|
|
|
|
|
|
|
unless length $ver; |
|
4989
|
|
|
|
|
|
|
|
|
4990
|
|
|
|
|
|
|
# check that the version number is of the form n.n |
|
4991
|
1
|
50
|
|
|
|
10
|
$pxs->death("Error: REQUIRE: expected a number, got '$ver'") |
|
4992
|
|
|
|
|
|
|
unless $ver =~ /^\d+(\.\d*)?/; |
|
4993
|
|
|
|
|
|
|
|
|
4994
|
1
|
|
|
|
|
6
|
my $got = $ExtUtils::ParseXS::VERSION; |
|
4995
|
1
|
50
|
|
|
|
11
|
$pxs->death("Error: xsubpp $ver (or better) required--this is only $got.") |
|
4996
|
|
|
|
|
|
|
unless $got >= $ver; |
|
4997
|
|
|
|
|
|
|
|
|
4998
|
1
|
|
|
|
|
3
|
$self->{version} = $ver; |
|
4999
|
|
|
|
|
|
|
|
|
5000
|
1
|
|
|
|
|
3
|
1; |
|
5001
|
|
|
|
|
|
|
} |
|
5002
|
|
|
|
|
|
|
|
|
5003
|
|
|
|
|
|
|
|
|
5004
|
|
|
|
|
|
|
# ====================================================================== |
|
5005
|
|
|
|
|
|
|
|
|
5006
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::include; |
|
5007
|
|
|
|
|
|
|
|
|
5008
|
|
|
|
|
|
|
# Common base class for the 'INCLUDE' and 'INCLUDE_COMMAND' keywords |
|
5009
|
|
|
|
|
|
|
|
|
5010
|
19
|
|
|
19
|
|
136
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
5011
|
|
|
|
|
|
|
'is_cmd', # Bool: is INCLUDE_COMMAND |
|
5012
|
|
|
|
|
|
|
'inc_filename', # Str: the file/command to be included |
|
5013
|
|
|
|
|
|
|
'old_filename', # Str: the previous file |
|
5014
|
|
|
|
|
|
|
)}; |
|
5015
|
|
|
|
|
|
|
|
|
5016
|
|
|
|
|
|
|
|
|
5017
|
|
|
|
|
|
|
sub parse { |
|
5018
|
2
|
|
|
2
|
|
5
|
my __PACKAGE__ $self = shift; |
|
5019
|
2
|
|
|
|
|
5
|
my ExtUtils::ParseXS $pxs = shift; |
|
5020
|
|
|
|
|
|
|
|
|
5021
|
2
|
|
|
|
|
14
|
$self->SUPER::parse($pxs); # set file/line_no/text |
|
5022
|
|
|
|
|
|
|
|
|
5023
|
2
|
|
|
|
|
6
|
my $f = $self->{text}; |
|
5024
|
2
|
|
|
|
|
21
|
my $is_cmd = $self->{is_cmd}; |
|
5025
|
|
|
|
|
|
|
|
|
5026
|
2
|
100
|
|
|
|
8
|
if ($is_cmd) { |
|
5027
|
1
|
50
|
|
|
|
9
|
$f = $self->QuoteArgs($f) if $^O eq 'VMS'; |
|
5028
|
|
|
|
|
|
|
|
|
5029
|
1
|
50
|
|
|
|
5
|
$pxs->death("INCLUDE_COMMAND: command missing") |
|
5030
|
|
|
|
|
|
|
unless length $f; |
|
5031
|
|
|
|
|
|
|
|
|
5032
|
1
|
50
|
33
|
|
|
15
|
$pxs->death("INCLUDE_COMMAND: pipes are illegal") |
|
5033
|
|
|
|
|
|
|
if $f =~ /^\s*\|/ or $f =~ /\|\s*$/; |
|
5034
|
|
|
|
|
|
|
} |
|
5035
|
|
|
|
|
|
|
else { |
|
5036
|
1
|
50
|
|
|
|
9
|
$pxs->death("INCLUDE: filename missing") |
|
5037
|
|
|
|
|
|
|
unless length $f; |
|
5038
|
|
|
|
|
|
|
|
|
5039
|
1
|
50
|
|
|
|
11
|
$pxs->death("INCLUDE: output pipe is illegal") |
|
5040
|
|
|
|
|
|
|
if $f =~ /^\s*\|/; |
|
5041
|
|
|
|
|
|
|
|
|
5042
|
|
|
|
|
|
|
# simple minded recursion detector |
|
5043
|
|
|
|
|
|
|
$pxs->death("INCLUDE loop detected") |
|
5044
|
1
|
50
|
|
|
|
7
|
if $pxs->{IncludedFiles}{$f}; |
|
5045
|
|
|
|
|
|
|
|
|
5046
|
1
|
50
|
|
|
|
9
|
++$pxs->{IncludedFiles}->{$f} unless $f =~ /\|\s*$/; |
|
5047
|
|
|
|
|
|
|
|
|
5048
|
1
|
50
|
33
|
|
|
10
|
if ($f =~ /\|\s*$/ && $f =~ /^\s*perl\s/) { |
|
5049
|
0
|
|
|
|
|
0
|
$pxs->Warn( |
|
5050
|
|
|
|
|
|
|
"The INCLUDE directive with a command is discouraged." |
|
5051
|
|
|
|
|
|
|
. " Use INCLUDE_COMMAND instead! In particular using 'perl'" |
|
5052
|
|
|
|
|
|
|
. " in an 'INCLUDE: ... |' directive is not guaranteed to pick" |
|
5053
|
|
|
|
|
|
|
. " up the correct perl. The INCLUDE_COMMAND directive allows" |
|
5054
|
|
|
|
|
|
|
. " the use of \$^X as the currently running perl, see" |
|
5055
|
|
|
|
|
|
|
. " 'perldoc perlxs' for details." |
|
5056
|
|
|
|
|
|
|
); |
|
5057
|
|
|
|
|
|
|
} |
|
5058
|
|
|
|
|
|
|
} |
|
5059
|
|
|
|
|
|
|
|
|
5060
|
|
|
|
|
|
|
# Save the current file context. |
|
5061
|
|
|
|
|
|
|
|
|
5062
|
2
|
|
|
|
|
14
|
my @save_keys = qw(in_fh in_filename in_pathname |
|
5063
|
|
|
|
|
|
|
lastline lastline_no line line_no); |
|
5064
|
2
|
|
|
|
|
11
|
my @saved = @$pxs{@save_keys}; |
|
5065
|
|
|
|
|
|
|
|
|
5066
|
2
|
|
66
|
|
|
18
|
my $isPipe = $is_cmd || $pxs->{in_filename} =~ /\|\s*$/; |
|
5067
|
|
|
|
|
|
|
|
|
5068
|
2
|
|
|
|
|
5
|
$pxs->{line} = []; |
|
5069
|
2
|
|
|
|
|
5
|
$pxs->{line_no} = []; |
|
5070
|
|
|
|
|
|
|
|
|
5071
|
|
|
|
|
|
|
# Open the new file / pipe |
|
5072
|
|
|
|
|
|
|
|
|
5073
|
2
|
|
|
|
|
31
|
$pxs->{in_fh} = Symbol::gensym(); |
|
5074
|
|
|
|
|
|
|
|
|
5075
|
2
|
100
|
|
|
|
83
|
if ($is_cmd) { |
|
5076
|
|
|
|
|
|
|
# Expand the special token '$^X' into the full path of the |
|
5077
|
|
|
|
|
|
|
# currently running perl interpreter |
|
5078
|
1
|
|
|
|
|
6
|
my $X = $pxs->_safe_quote($^X); # quotes if has spaces |
|
5079
|
1
|
|
|
|
|
8
|
$f =~ s/^\s*\$\^X/$X/; |
|
5080
|
|
|
|
|
|
|
|
|
5081
|
1
|
50
|
|
|
|
6629
|
open ($pxs->{in_fh}, "-|", $f) |
|
5082
|
|
|
|
|
|
|
or $pxs->death( |
|
5083
|
|
|
|
|
|
|
"Cannot run command '$f' to include its output: $!"); |
|
5084
|
|
|
|
|
|
|
} |
|
5085
|
|
|
|
|
|
|
else { |
|
5086
|
1
|
50
|
|
|
|
75
|
open($pxs->{in_fh}, $f) |
|
5087
|
|
|
|
|
|
|
or $pxs->death("Cannot open '$f': $!"); |
|
5088
|
|
|
|
|
|
|
} |
|
5089
|
|
|
|
|
|
|
|
|
5090
|
2
|
|
|
|
|
30
|
$self->{old_filename} = $pxs->{in_filename}; |
|
5091
|
2
|
|
|
|
|
25
|
$self->{inc_filename} = $f; |
|
5092
|
2
|
|
|
|
|
18
|
$pxs->{in_filename} = $f; |
|
5093
|
|
|
|
|
|
|
|
|
5094
|
2
|
|
|
|
|
21
|
my $path = $f; |
|
5095
|
2
|
100
|
|
|
|
32
|
if ($is_cmd) { |
|
5096
|
|
|
|
|
|
|
#$path =~ s/\"/\\"/g; # Fails? See CPAN RT #53938: MinGW Broken after 2.21 |
|
5097
|
1
|
|
|
|
|
13
|
$path =~ s/\\/\\\\/g; # Works according to reporter of #53938 |
|
5098
|
|
|
|
|
|
|
} |
|
5099
|
|
|
|
|
|
|
else { |
|
5100
|
|
|
|
|
|
|
$path = ($^O =~ /^mswin/i) |
|
5101
|
|
|
|
|
|
|
# See CPAN RT #61908: gcc doesn't like |
|
5102
|
|
|
|
|
|
|
# backslashes on win32? |
|
5103
|
|
|
|
|
|
|
? "$pxs->{dir}/$path" |
|
5104
|
1
|
50
|
|
|
|
36
|
: File::Spec->catfile($pxs->{dir}, $path); |
|
5105
|
|
|
|
|
|
|
} |
|
5106
|
2
|
|
|
|
|
31
|
$pxs->{in_pathname} = $self->{file} = $path; |
|
5107
|
|
|
|
|
|
|
|
|
5108
|
|
|
|
|
|
|
# Prime the pump by reading the first non-blank line |
|
5109
|
2
|
|
|
|
|
468845
|
while (readline($pxs->{in_fh})) { |
|
5110
|
4
|
100
|
|
|
|
88
|
last unless /^\s*$/; |
|
5111
|
|
|
|
|
|
|
} |
|
5112
|
|
|
|
|
|
|
|
|
5113
|
2
|
|
|
|
|
27
|
$pxs->{lastline} = $_; |
|
5114
|
2
|
|
|
|
|
21
|
chomp $pxs->{lastline}; |
|
5115
|
2
|
|
|
|
|
25
|
$pxs->{lastline_no} = $self->{line_no} = $.; |
|
5116
|
|
|
|
|
|
|
|
|
5117
|
|
|
|
|
|
|
# Parse included file |
|
5118
|
|
|
|
|
|
|
|
|
5119
|
|
|
|
|
|
|
my $cpp_scope = ExtUtils::ParseXS::Node::cpp_scope->new({ |
|
5120
|
|
|
|
|
|
|
type => 'include', |
|
5121
|
|
|
|
|
|
|
is_cmd => $self->{is_cmd}, |
|
5122
|
2
|
|
|
|
|
149
|
}); |
|
5123
|
2
|
50
|
|
|
|
31
|
$cpp_scope->parse($pxs) |
|
5124
|
|
|
|
|
|
|
or return; |
|
5125
|
2
|
|
|
|
|
11
|
push @{$self->{kids}}, $cpp_scope; |
|
|
2
|
|
|
|
|
5
|
|
|
5126
|
|
|
|
|
|
|
|
|
5127
|
|
|
|
|
|
|
--$pxs->{IncludedFiles}->{$pxs->{in_filename}} |
|
5128
|
2
|
100
|
|
|
|
12
|
unless $isPipe; |
|
5129
|
|
|
|
|
|
|
|
|
5130
|
2
|
|
|
|
|
65
|
close $pxs->{in_fh}; |
|
5131
|
|
|
|
|
|
|
|
|
5132
|
|
|
|
|
|
|
# Restore the current file context. |
|
5133
|
|
|
|
|
|
|
|
|
5134
|
2
|
|
|
|
|
18
|
@$pxs{@save_keys} = @saved; |
|
5135
|
|
|
|
|
|
|
|
|
5136
|
2
|
50
|
66
|
|
|
36
|
if ($isPipe and $? ) { |
|
5137
|
0
|
|
|
|
|
0
|
--$pxs->{lastline_no}; |
|
5138
|
0
|
|
|
|
|
0
|
print STDERR "Error reading from pipe '$self->{inc_filename}': $! in $pxs->{in_filename}, line $pxs->{lastline_no}\n" ; |
|
5139
|
0
|
|
|
|
|
0
|
exit 1; |
|
5140
|
|
|
|
|
|
|
} |
|
5141
|
|
|
|
|
|
|
|
|
5142
|
2
|
|
|
|
|
17
|
1; |
|
5143
|
|
|
|
|
|
|
} |
|
5144
|
|
|
|
|
|
|
|
|
5145
|
|
|
|
|
|
|
|
|
5146
|
|
|
|
|
|
|
sub as_code { |
|
5147
|
2
|
|
|
2
|
|
6
|
my __PACKAGE__ $self = shift; |
|
5148
|
2
|
|
|
|
|
3
|
my ExtUtils::ParseXS $pxs = shift; |
|
5149
|
|
|
|
|
|
|
|
|
5150
|
|
|
|
|
|
|
my $comment = $self->{is_cmd} |
|
5151
|
2
|
100
|
|
|
|
10
|
? "INCLUDE_COMMAND: Including output of" |
|
5152
|
|
|
|
|
|
|
: "INCLUDE: Including"; |
|
5153
|
|
|
|
|
|
|
|
|
5154
|
2
|
|
|
|
|
9
|
$comment .= " '$self->{inc_filename}' from '$self->{old_filename}'"; |
|
5155
|
|
|
|
|
|
|
|
|
5156
|
2
|
|
|
|
|
37
|
print $self->Q(<<"EOF"); |
|
5157
|
|
|
|
|
|
|
| |
|
5158
|
|
|
|
|
|
|
|/* $comment */ |
|
5159
|
|
|
|
|
|
|
| |
|
5160
|
|
|
|
|
|
|
EOF |
|
5161
|
|
|
|
|
|
|
|
|
5162
|
2
|
|
|
|
|
5
|
$_->as_code($pxs) for @{$self->{kids}}; |
|
|
2
|
|
|
|
|
17
|
|
|
5163
|
|
|
|
|
|
|
|
|
5164
|
2
|
|
|
|
|
12
|
print $self->Q(<<"EOF"); |
|
5165
|
|
|
|
|
|
|
| |
|
5166
|
|
|
|
|
|
|
|/* INCLUDE: Returning to '$self->{old_filename}' from '$self->{inc_filename}' */ |
|
5167
|
|
|
|
|
|
|
| |
|
5168
|
|
|
|
|
|
|
EOF |
|
5169
|
|
|
|
|
|
|
|
|
5170
|
|
|
|
|
|
|
} |
|
5171
|
|
|
|
|
|
|
|
|
5172
|
|
|
|
|
|
|
|
|
5173
|
|
|
|
|
|
|
# ====================================================================== |
|
5174
|
|
|
|
|
|
|
|
|
5175
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INCLUDE; |
|
5176
|
|
|
|
|
|
|
|
|
5177
|
|
|
|
|
|
|
# Process the 'INCLUDE' keyword. Most processing is actually done by the |
|
5178
|
|
|
|
|
|
|
# parent 'include' class which handles INCLUDE_COMMAND too. |
|
5179
|
|
|
|
|
|
|
|
|
5180
|
19
|
|
|
19
|
|
219
|
BEGIN { $build_subclass->(-parent => 'include', |
|
5181
|
|
|
|
|
|
|
)}; |
|
5182
|
|
|
|
|
|
|
|
|
5183
|
|
|
|
|
|
|
|
|
5184
|
|
|
|
|
|
|
sub parse { |
|
5185
|
1
|
|
|
1
|
|
2
|
my __PACKAGE__ $self = shift; |
|
5186
|
1
|
|
|
|
|
4
|
my ExtUtils::ParseXS $pxs = shift; |
|
5187
|
|
|
|
|
|
|
|
|
5188
|
1
|
|
|
|
|
3
|
$self->{is_cmd} = 0; |
|
5189
|
1
|
|
|
|
|
7
|
$self->SUPER::parse($pxs); # main parsing done by Node::include |
|
5190
|
1
|
|
|
|
|
3
|
1; |
|
5191
|
|
|
|
|
|
|
} |
|
5192
|
|
|
|
|
|
|
|
|
5193
|
|
|
|
|
|
|
|
|
5194
|
|
|
|
|
|
|
# ====================================================================== |
|
5195
|
|
|
|
|
|
|
|
|
5196
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INCLUDE_COMMAND; |
|
5197
|
|
|
|
|
|
|
|
|
5198
|
|
|
|
|
|
|
# Process the 'INCLUDE_COMMAND' keyword. Most processing is actually done |
|
5199
|
|
|
|
|
|
|
# by the parent 'include' class which handles INCLUDE too. |
|
5200
|
|
|
|
|
|
|
|
|
5201
|
19
|
|
|
19
|
|
88
|
BEGIN { $build_subclass->(-parent => 'include', |
|
5202
|
|
|
|
|
|
|
)}; |
|
5203
|
|
|
|
|
|
|
|
|
5204
|
|
|
|
|
|
|
|
|
5205
|
|
|
|
|
|
|
sub parse { |
|
5206
|
1
|
|
|
1
|
|
3
|
my __PACKAGE__ $self = shift; |
|
5207
|
1
|
|
|
|
|
3
|
my ExtUtils::ParseXS $pxs = shift; |
|
5208
|
|
|
|
|
|
|
|
|
5209
|
1
|
|
|
|
|
4
|
$self->{is_cmd} = 1; |
|
5210
|
1
|
|
|
|
|
16
|
$self->SUPER::parse($pxs); # main parsing done by Node::include |
|
5211
|
1
|
|
|
|
|
8
|
1; |
|
5212
|
|
|
|
|
|
|
} |
|
5213
|
|
|
|
|
|
|
|
|
5214
|
|
|
|
|
|
|
|
|
5215
|
|
|
|
|
|
|
# ====================================================================== |
|
5216
|
|
|
|
|
|
|
|
|
5217
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::enable; |
|
5218
|
|
|
|
|
|
|
|
|
5219
|
|
|
|
|
|
|
# Base class for keywords which accept ENABLE/DISABLE as an argument |
|
5220
|
|
|
|
|
|
|
|
|
5221
|
19
|
|
|
19
|
|
86
|
BEGIN { $build_subclass->(-parent => 'oneline', |
|
5222
|
|
|
|
|
|
|
'enable', # Bool |
|
5223
|
|
|
|
|
|
|
)}; |
|
5224
|
|
|
|
|
|
|
|
|
5225
|
|
|
|
|
|
|
|
|
5226
|
|
|
|
|
|
|
sub parse { |
|
5227
|
329
|
|
|
329
|
|
918
|
my __PACKAGE__ $self = shift; |
|
5228
|
329
|
|
|
|
|
576
|
my ExtUtils::ParseXS $pxs = shift; |
|
5229
|
|
|
|
|
|
|
|
|
5230
|
329
|
|
|
|
|
1381
|
$self->SUPER::parse($pxs); # set file/line_no, self->{text} |
|
5231
|
329
|
|
|
|
|
1017
|
my $s = $self->{text}; |
|
5232
|
|
|
|
|
|
|
|
|
5233
|
329
|
|
|
|
|
5368
|
my ($keyword) = ($self =~ /(\w+)=/); # final component of class name |
|
5234
|
|
|
|
|
|
|
|
|
5235
|
329
|
100
|
|
|
|
1367
|
if ($keyword eq 'PROTOTYPES') { |
|
5236
|
|
|
|
|
|
|
# For backwards compatibility, parsing the PROTOTYPES |
|
5237
|
|
|
|
|
|
|
# keyword's value is very lax: in particular, anything that |
|
5238
|
|
|
|
|
|
|
# didn't match 'ENABLE' (such as 'Enabled' or 'ENABLED') used to |
|
5239
|
|
|
|
|
|
|
# be treated as valid but false. Continue to use this |
|
5240
|
|
|
|
|
|
|
# interpretation for backcomp, but warn. |
|
5241
|
|
|
|
|
|
|
|
|
5242
|
309
|
100
|
|
|
|
3686
|
unless ($s =~ /^ ((ENABLE|DISABLE) D? ;?) \s* $ /xi) { |
|
5243
|
3
|
|
|
|
|
51
|
$pxs->death("Error: $keyword: ENABLE/DISABLE") |
|
5244
|
|
|
|
|
|
|
} |
|
5245
|
306
|
|
|
|
|
1508
|
my ($value, $en_dis) = ($1, $2); |
|
5246
|
306
|
100
|
|
|
|
1143
|
$self->{enable} = $en_dis eq 'ENABLE' ? 1 : 0; |
|
5247
|
306
|
100
|
|
|
|
1822
|
unless ($value =~ /^(ENABLE|DISABLE)$/) { |
|
5248
|
|
|
|
|
|
|
$pxs->Warn("Warning: invalid PROTOTYPES value '$value' interpreted as " |
|
5249
|
4
|
100
|
|
|
|
56
|
. ($self->{enable} ? 'ENABLE' : 'DISABLE')); |
|
5250
|
|
|
|
|
|
|
} |
|
5251
|
|
|
|
|
|
|
} |
|
5252
|
|
|
|
|
|
|
else { |
|
5253
|
|
|
|
|
|
|
# SCOPE / VERSIONCHECK / EXPORT_XSUB_SYMBOLS |
|
5254
|
20
|
100
|
|
|
|
394
|
$s =~ /^(ENABLE|DISABLE)\s*$/ |
|
5255
|
|
|
|
|
|
|
or $pxs->death("Error: $keyword: ENABLE/DISABLE"); |
|
5256
|
7
|
100
|
|
|
|
51
|
$self->{enable} = $1 eq 'ENABLE' ? 1 : 0; |
|
5257
|
|
|
|
|
|
|
} |
|
5258
|
|
|
|
|
|
|
|
|
5259
|
313
|
|
|
|
|
731
|
1; |
|
5260
|
|
|
|
|
|
|
} |
|
5261
|
|
|
|
|
|
|
|
|
5262
|
|
|
|
|
|
|
|
|
5263
|
|
|
|
|
|
|
# ====================================================================== |
|
5264
|
|
|
|
|
|
|
|
|
5265
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::EXPORT_XSUB_SYMBOLS; |
|
5266
|
|
|
|
|
|
|
|
|
5267
|
|
|
|
|
|
|
# Handle EXPORT_XSUB_SYMBOLS keyword |
|
5268
|
|
|
|
|
|
|
# |
|
5269
|
|
|
|
|
|
|
# Note that this keyword can appear both inside of and outside of an |
|
5270
|
|
|
|
|
|
|
# XSUB; for the latter, it it is currently created as a temporary |
|
5271
|
|
|
|
|
|
|
# object where as_code() is called immediately after parse() and then |
|
5272
|
|
|
|
|
|
|
# the object is discarded. |
|
5273
|
|
|
|
|
|
|
|
|
5274
|
19
|
|
|
19
|
|
107
|
BEGIN { $build_subclass->(-parent => 'enable', |
|
5275
|
|
|
|
|
|
|
)}; |
|
5276
|
|
|
|
|
|
|
|
|
5277
|
|
|
|
|
|
|
|
|
5278
|
|
|
|
|
|
|
sub parse { |
|
5279
|
3
|
|
|
3
|
|
21
|
my __PACKAGE__ $self = shift; |
|
5280
|
3
|
|
|
|
|
15
|
my ExtUtils::ParseXS $pxs = shift; |
|
5281
|
|
|
|
|
|
|
|
|
5282
|
3
|
|
|
|
|
23
|
$self->SUPER::parse($pxs); # set file/line_no, self->{enable} |
|
5283
|
0
|
|
|
|
|
0
|
1; |
|
5284
|
|
|
|
|
|
|
} |
|
5285
|
|
|
|
|
|
|
|
|
5286
|
|
|
|
|
|
|
|
|
5287
|
|
|
|
|
|
|
sub as_code { |
|
5288
|
0
|
|
|
0
|
|
0
|
my __PACKAGE__ $self = shift; |
|
5289
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS $pxs = shift; |
|
5290
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5291
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5292
|
|
|
|
|
|
|
|
|
5293
|
0
|
0
|
|
|
|
0
|
my $xs_impl = $self->{enable} ? 'XS_EXTERNAL' : 'XS_INTERNAL'; |
|
5294
|
|
|
|
|
|
|
|
|
5295
|
|
|
|
|
|
|
# Change the definition of XS_EUPXS, so that any subsequent |
|
5296
|
|
|
|
|
|
|
# XS_EUPXS(fXS_Foo_foo) XSUB declarations will expand to |
|
5297
|
|
|
|
|
|
|
# XS_EXTERNAL/XS_INTERNAL as appropriate |
|
5298
|
|
|
|
|
|
|
|
|
5299
|
0
|
|
|
|
|
0
|
print $self->Q(<<"EOF"); |
|
5300
|
|
|
|
|
|
|
|#undef XS_EUPXS |
|
5301
|
|
|
|
|
|
|
|#if defined(PERL_EUPXS_ALWAYS_EXPORT) |
|
5302
|
|
|
|
|
|
|
|# define XS_EUPXS(name) XS_EXTERNAL(name) |
|
5303
|
|
|
|
|
|
|
|#elif defined(PERL_EUPXS_NEVER_EXPORT) |
|
5304
|
|
|
|
|
|
|
|# define XS_EUPXS(name) XS_INTERNAL(name) |
|
5305
|
|
|
|
|
|
|
|#else |
|
5306
|
|
|
|
|
|
|
|# define XS_EUPXS(name) $xs_impl(name) |
|
5307
|
|
|
|
|
|
|
|#endif |
|
5308
|
|
|
|
|
|
|
EOF |
|
5309
|
|
|
|
|
|
|
} |
|
5310
|
|
|
|
|
|
|
|
|
5311
|
|
|
|
|
|
|
|
|
5312
|
|
|
|
|
|
|
# ====================================================================== |
|
5313
|
|
|
|
|
|
|
|
|
5314
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::PROTOTYPES; |
|
5315
|
|
|
|
|
|
|
|
|
5316
|
|
|
|
|
|
|
# Handle PROTOTYPES keyword |
|
5317
|
|
|
|
|
|
|
# |
|
5318
|
|
|
|
|
|
|
# Note that this keyword can appear both inside of and outside of an XSUB. |
|
5319
|
|
|
|
|
|
|
|
|
5320
|
19
|
|
|
19
|
|
94
|
BEGIN { $build_subclass->(-parent => 'enable', |
|
5321
|
|
|
|
|
|
|
)}; |
|
5322
|
|
|
|
|
|
|
|
|
5323
|
|
|
|
|
|
|
|
|
5324
|
|
|
|
|
|
|
sub parse { |
|
5325
|
309
|
|
|
309
|
|
827
|
my __PACKAGE__ $self = shift; |
|
5326
|
309
|
|
|
|
|
667
|
my ExtUtils::ParseXS $pxs = shift; |
|
5327
|
|
|
|
|
|
|
|
|
5328
|
309
|
|
|
|
|
2579
|
$self->SUPER::parse($pxs); # set file/line_no, self->{enable} |
|
5329
|
306
|
|
|
|
|
1172
|
$pxs->{PROTOTYPES_value} = $self->{enable}; |
|
5330
|
306
|
|
|
|
|
1125
|
$pxs->{proto_behaviour_specified} = 1; |
|
5331
|
306
|
|
|
|
|
1122
|
1; |
|
5332
|
|
|
|
|
|
|
} |
|
5333
|
|
|
|
|
|
|
|
|
5334
|
|
|
|
|
|
|
|
|
5335
|
|
|
|
|
|
|
# ====================================================================== |
|
5336
|
|
|
|
|
|
|
|
|
5337
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::SCOPE; |
|
5338
|
|
|
|
|
|
|
|
|
5339
|
|
|
|
|
|
|
# Handle SCOPE keyword |
|
5340
|
|
|
|
|
|
|
# |
|
5341
|
|
|
|
|
|
|
# Note that this keyword can appear both inside of and outside of an XSUB. |
|
5342
|
|
|
|
|
|
|
|
|
5343
|
19
|
|
|
19
|
|
90
|
BEGIN { $build_subclass->(-parent => 'enable', |
|
5344
|
|
|
|
|
|
|
)}; |
|
5345
|
|
|
|
|
|
|
|
|
5346
|
|
|
|
|
|
|
|
|
5347
|
|
|
|
|
|
|
sub parse { |
|
5348
|
12
|
|
|
12
|
|
79
|
my __PACKAGE__ $self = shift; |
|
5349
|
12
|
|
|
|
|
52
|
my ExtUtils::ParseXS $pxs = shift; |
|
5350
|
12
|
|
|
|
|
51
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5351
|
12
|
|
|
|
|
53
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5352
|
|
|
|
|
|
|
|
|
5353
|
12
|
|
|
|
|
130
|
$self->SUPER::parse($pxs); # set file/line_no, self->{enable} |
|
5354
|
|
|
|
|
|
|
|
|
5355
|
|
|
|
|
|
|
# $xsub not defined for file-scoped SCOPE |
|
5356
|
6
|
100
|
|
|
|
39
|
if ($xsub) { |
|
5357
|
|
|
|
|
|
|
$pxs->blurt("Error: only one SCOPE declaration allowed per XSUB") |
|
5358
|
4
|
100
|
|
|
|
45
|
if $xsub->{seen_SCOPE}; |
|
5359
|
4
|
|
|
|
|
17
|
$xsub->{seen_SCOPE} = 1; |
|
5360
|
|
|
|
|
|
|
} |
|
5361
|
|
|
|
|
|
|
|
|
5362
|
|
|
|
|
|
|
# Note that currently this parse method can be called either while |
|
5363
|
|
|
|
|
|
|
# parsing an XSUB, or while processing file-scoped keywords |
|
5364
|
|
|
|
|
|
|
# just before an XSUB declaration. So potentially set both types of |
|
5365
|
|
|
|
|
|
|
# state. |
|
5366
|
6
|
100
|
|
|
|
37
|
$xsub->{SCOPE_enabled} = $self->{enable} if $xsub; |
|
5367
|
6
|
|
|
|
|
18
|
$pxs->{file_SCOPE_enabled} = $self->{enable}; |
|
5368
|
6
|
|
|
|
|
22
|
1; |
|
5369
|
|
|
|
|
|
|
} |
|
5370
|
|
|
|
|
|
|
|
|
5371
|
|
|
|
|
|
|
|
|
5372
|
|
|
|
|
|
|
# ====================================================================== |
|
5373
|
|
|
|
|
|
|
|
|
5374
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::VERSIONCHECK; |
|
5375
|
|
|
|
|
|
|
|
|
5376
|
|
|
|
|
|
|
# Handle VERSIONCHECK keyword |
|
5377
|
|
|
|
|
|
|
# |
|
5378
|
|
|
|
|
|
|
# Note that this keyword can appear both inside of and outside of an XSUB. |
|
5379
|
|
|
|
|
|
|
|
|
5380
|
19
|
|
|
19
|
|
134
|
BEGIN { $build_subclass->(-parent => 'enable', |
|
5381
|
|
|
|
|
|
|
)}; |
|
5382
|
|
|
|
|
|
|
|
|
5383
|
|
|
|
|
|
|
|
|
5384
|
|
|
|
|
|
|
sub parse { |
|
5385
|
5
|
|
|
5
|
|
25
|
my __PACKAGE__ $self = shift; |
|
5386
|
5
|
|
|
|
|
16
|
my ExtUtils::ParseXS $pxs = shift; |
|
5387
|
|
|
|
|
|
|
|
|
5388
|
5
|
|
|
|
|
35
|
$self->SUPER::parse($pxs); # set file/line_no, self->{enable} |
|
5389
|
1
|
|
|
|
|
2
|
$pxs->{VERSIONCHECK_value} = $self->{enable}; |
|
5390
|
1
|
|
|
|
|
4
|
1; |
|
5391
|
|
|
|
|
|
|
} |
|
5392
|
|
|
|
|
|
|
|
|
5393
|
|
|
|
|
|
|
|
|
5394
|
|
|
|
|
|
|
# ====================================================================== |
|
5395
|
|
|
|
|
|
|
|
|
5396
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::multiline; |
|
5397
|
|
|
|
|
|
|
|
|
5398
|
|
|
|
|
|
|
# Generic base class for keyword Nodes which can contain multiple lines, |
|
5399
|
|
|
|
|
|
|
# e.g. C code or other data: so anything from ALIAS to PPCODE. |
|
5400
|
|
|
|
|
|
|
# On entry, $self->lines[0] will be any text (on the same line) which |
|
5401
|
|
|
|
|
|
|
# follows the keyword. |
|
5402
|
|
|
|
|
|
|
|
|
5403
|
19
|
|
|
19
|
|
77
|
BEGIN { $build_subclass->( |
|
5404
|
|
|
|
|
|
|
'lines', # Array ref of all lines until the next keyword |
|
5405
|
|
|
|
|
|
|
)}; |
|
5406
|
|
|
|
|
|
|
|
|
5407
|
|
|
|
|
|
|
|
|
5408
|
|
|
|
|
|
|
# Consume all the lines up until the next directive and store in @$lines. |
|
5409
|
|
|
|
|
|
|
|
|
5410
|
|
|
|
|
|
|
sub parse { |
|
5411
|
186
|
|
|
186
|
|
469
|
my __PACKAGE__ $self = shift; |
|
5412
|
186
|
|
|
|
|
318
|
my ExtUtils::ParseXS $pxs = shift; |
|
5413
|
|
|
|
|
|
|
|
|
5414
|
186
|
|
|
|
|
609
|
$self->SUPER::parse($pxs); # set file/line_no |
|
5415
|
|
|
|
|
|
|
|
|
5416
|
186
|
|
|
|
|
709
|
my @lines; |
|
5417
|
|
|
|
|
|
|
|
|
5418
|
|
|
|
|
|
|
# Consume lines until the next directive |
|
5419
|
186
|
|
100
|
|
|
382
|
while( @{$pxs->{line}} |
|
|
576
|
|
|
|
|
4358
|
|
|
5420
|
|
|
|
|
|
|
&& $pxs->{line}[0] !~ /^$ExtUtils::ParseXS::BLOCK_regexp/o) |
|
5421
|
|
|
|
|
|
|
{ |
|
5422
|
390
|
|
|
|
|
647
|
push @lines, shift @{$pxs->{line}}; |
|
|
390
|
|
|
|
|
1168
|
|
|
5423
|
|
|
|
|
|
|
} |
|
5424
|
|
|
|
|
|
|
|
|
5425
|
186
|
|
|
|
|
518
|
$self->{lines} = \@lines; |
|
5426
|
186
|
|
|
|
|
709
|
1; |
|
5427
|
|
|
|
|
|
|
} |
|
5428
|
|
|
|
|
|
|
|
|
5429
|
|
|
|
|
|
|
# No as_code() method - we rely on the sub-classes for that |
|
5430
|
|
|
|
|
|
|
|
|
5431
|
|
|
|
|
|
|
|
|
5432
|
|
|
|
|
|
|
# ====================================================================== |
|
5433
|
|
|
|
|
|
|
|
|
5434
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::multiline_merged; |
|
5435
|
|
|
|
|
|
|
|
|
5436
|
|
|
|
|
|
|
# Generic base class for keyword Nodes which can contain multiple lines. |
|
5437
|
|
|
|
|
|
|
# It's the same is is parent class, :Node::multiline, except that in |
|
5438
|
|
|
|
|
|
|
# addition, leading blank lines are skipped and the remainder concatenated |
|
5439
|
|
|
|
|
|
|
# into a single line, 'text'. |
|
5440
|
|
|
|
|
|
|
|
|
5441
|
19
|
|
|
19
|
|
101
|
BEGIN { $build_subclass->(-parent => 'multiline', |
|
5442
|
|
|
|
|
|
|
'text', # Str: singe string containing all concatenated lines |
|
5443
|
|
|
|
|
|
|
)}; |
|
5444
|
|
|
|
|
|
|
|
|
5445
|
|
|
|
|
|
|
|
|
5446
|
|
|
|
|
|
|
# Consume all the lines up until the next directive and store in |
|
5447
|
|
|
|
|
|
|
# @$lines, and in addition, concatenate and store in $text |
|
5448
|
|
|
|
|
|
|
|
|
5449
|
|
|
|
|
|
|
sub parse { |
|
5450
|
33
|
|
|
33
|
|
92
|
my __PACKAGE__ $self = shift; |
|
5451
|
33
|
|
|
|
|
99
|
my ExtUtils::ParseXS $pxs = shift; |
|
5452
|
|
|
|
|
|
|
|
|
5453
|
33
|
|
|
|
|
230
|
$self->SUPER::parse($pxs); # set file/line_no, read lines |
|
5454
|
|
|
|
|
|
|
|
|
5455
|
33
|
|
|
|
|
61
|
my @lines = @{$self->{lines}}; |
|
|
33
|
|
|
|
|
120
|
|
|
5456
|
33
|
|
100
|
|
|
491
|
shift @lines while @lines && $lines[0] !~ /\S/; |
|
5457
|
|
|
|
|
|
|
# XXX ParseXS originally didn't include a trailing \n, |
|
5458
|
|
|
|
|
|
|
# so we carry on doing the same. |
|
5459
|
33
|
|
|
|
|
140
|
$self->{text} = join "\n", @lines; |
|
5460
|
33
|
|
|
|
|
178
|
ExtUtils::ParseXS::Utilities::trim_whitespace($self->{text}); |
|
5461
|
33
|
|
|
|
|
132
|
1; |
|
5462
|
|
|
|
|
|
|
} |
|
5463
|
|
|
|
|
|
|
|
|
5464
|
|
|
|
|
|
|
# No as_code() method - we rely on the sub-classes for that |
|
5465
|
|
|
|
|
|
|
|
|
5466
|
|
|
|
|
|
|
|
|
5467
|
|
|
|
|
|
|
# ====================================================================== |
|
5468
|
|
|
|
|
|
|
|
|
5469
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::C_ARGS; |
|
5470
|
|
|
|
|
|
|
|
|
5471
|
|
|
|
|
|
|
# Handle C_ARGS keyword |
|
5472
|
|
|
|
|
|
|
|
|
5473
|
19
|
|
|
19
|
|
96
|
BEGIN { $build_subclass->(-parent => 'multiline_merged', |
|
5474
|
|
|
|
|
|
|
)}; |
|
5475
|
|
|
|
|
|
|
|
|
5476
|
|
|
|
|
|
|
|
|
5477
|
|
|
|
|
|
|
sub parse { |
|
5478
|
18
|
|
|
18
|
|
61
|
my __PACKAGE__ $self = shift; |
|
5479
|
18
|
|
|
|
|
35
|
my ExtUtils::ParseXS $pxs = shift; |
|
5480
|
18
|
|
|
|
|
44
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5481
|
18
|
|
|
|
|
32
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5482
|
|
|
|
|
|
|
|
|
5483
|
18
|
|
|
|
|
90
|
$self->SUPER::parse($pxs); # set file/line_no, get lines, set text |
|
5484
|
18
|
|
|
|
|
65
|
$xbody->{ioparams}{auto_function_sig_override} = $self->{text}; |
|
5485
|
18
|
|
|
|
|
65
|
1; |
|
5486
|
|
|
|
|
|
|
} |
|
5487
|
|
|
|
|
|
|
|
|
5488
|
|
|
|
|
|
|
|
|
5489
|
|
|
|
|
|
|
# ====================================================================== |
|
5490
|
|
|
|
|
|
|
|
|
5491
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INTERFACE; |
|
5492
|
|
|
|
|
|
|
|
|
5493
|
|
|
|
|
|
|
# Handle INTERFACE keyword |
|
5494
|
|
|
|
|
|
|
|
|
5495
|
19
|
|
|
19
|
|
89
|
BEGIN { $build_subclass->(-parent => 'multiline_merged', |
|
5496
|
|
|
|
|
|
|
)}; |
|
5497
|
|
|
|
|
|
|
|
|
5498
|
|
|
|
|
|
|
|
|
5499
|
|
|
|
|
|
|
sub parse { |
|
5500
|
9
|
|
|
9
|
|
53
|
my __PACKAGE__ $self = shift; |
|
5501
|
9
|
|
|
|
|
38
|
my ExtUtils::ParseXS $pxs = shift; |
|
5502
|
9
|
|
|
|
|
36
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5503
|
9
|
|
|
|
|
55
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5504
|
|
|
|
|
|
|
|
|
5505
|
9
|
|
|
|
|
82
|
$self->SUPER::parse($pxs); # set file/line_no, get lines, set text |
|
5506
|
9
|
|
|
|
|
43
|
$xsub->{seen_INTERFACE} = 1; |
|
5507
|
|
|
|
|
|
|
|
|
5508
|
9
|
|
|
|
|
27
|
my %map; |
|
5509
|
|
|
|
|
|
|
|
|
5510
|
9
|
|
|
|
|
76
|
foreach (split /[\s,]+/, $self->{text}) { |
|
5511
|
11
|
|
|
|
|
33
|
my $short = $_; |
|
5512
|
11
|
|
|
|
|
153
|
$short =~ s/^$pxs->{PREFIX_pattern}//; |
|
5513
|
11
|
|
|
|
|
275
|
$map{$short} = $_; |
|
5514
|
11
|
|
|
|
|
61
|
$xsub->{map_interface_name_short_to_original}{$short} = $_; |
|
5515
|
|
|
|
|
|
|
} |
|
5516
|
|
|
|
|
|
|
|
|
5517
|
9
|
|
|
|
|
57
|
1; |
|
5518
|
|
|
|
|
|
|
} |
|
5519
|
|
|
|
|
|
|
|
|
5520
|
|
|
|
|
|
|
|
|
5521
|
|
|
|
|
|
|
sub as_code { |
|
5522
|
9
|
|
|
9
|
|
29
|
my __PACKAGE__ $self = shift; |
|
5523
|
9
|
|
|
|
|
22
|
my ExtUtils::ParseXS $pxs = shift; |
|
5524
|
9
|
|
|
|
|
31
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5525
|
9
|
|
|
|
|
29
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5526
|
|
|
|
|
|
|
|
|
5527
|
9
|
|
|
|
|
40
|
my $macro = $xsub->{interface_macro}; |
|
5528
|
9
|
50
|
|
|
|
90
|
$macro = 'XSINTERFACE_FUNC' unless defined $macro; |
|
5529
|
|
|
|
|
|
|
|
|
5530
|
9
|
|
|
|
|
48
|
my $type = $xsub->{decl}{return_type}{type}; |
|
5531
|
|
|
|
|
|
|
$type =~ tr/:/_/ |
|
5532
|
9
|
50
|
|
|
|
62
|
unless $pxs->{config_RetainCplusplusHierarchicalTypes}; |
|
5533
|
9
|
|
|
|
|
69
|
print <<"EOF"; |
|
5534
|
|
|
|
|
|
|
XSFUNCTION = $macro($type,cv,XSANY.any_dptr); |
|
5535
|
|
|
|
|
|
|
EOF |
|
5536
|
|
|
|
|
|
|
} |
|
5537
|
|
|
|
|
|
|
|
|
5538
|
|
|
|
|
|
|
|
|
5539
|
|
|
|
|
|
|
# ====================================================================== |
|
5540
|
|
|
|
|
|
|
|
|
5541
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INTERFACE_MACRO; |
|
5542
|
|
|
|
|
|
|
|
|
5543
|
|
|
|
|
|
|
# Handle INTERFACE_MACRO keyword |
|
5544
|
|
|
|
|
|
|
|
|
5545
|
19
|
|
|
19
|
|
103
|
BEGIN { $build_subclass->(-parent => 'multiline_merged', |
|
5546
|
|
|
|
|
|
|
'get_macro', # Str: name of macro to get interface |
|
5547
|
|
|
|
|
|
|
'set_macro', # Str: name of macro to set interface |
|
5548
|
|
|
|
|
|
|
)}; |
|
5549
|
|
|
|
|
|
|
|
|
5550
|
|
|
|
|
|
|
|
|
5551
|
|
|
|
|
|
|
sub parse { |
|
5552
|
0
|
|
|
0
|
|
0
|
my __PACKAGE__ $self = shift; |
|
5553
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS $pxs = shift; |
|
5554
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5555
|
0
|
|
|
|
|
0
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5556
|
|
|
|
|
|
|
|
|
5557
|
0
|
|
|
|
|
0
|
$self->SUPER::parse($pxs); # set file/line_no, get lines, set text |
|
5558
|
|
|
|
|
|
|
|
|
5559
|
0
|
|
|
|
|
0
|
$xsub->{seen_INTERFACE_MACRO} = 1; |
|
5560
|
|
|
|
|
|
|
|
|
5561
|
0
|
|
|
|
|
0
|
my $s = $self->{text}; |
|
5562
|
0
|
|
|
|
|
0
|
my ($m1, $m2); |
|
5563
|
0
|
0
|
|
|
|
0
|
if ($s =~ /\s/) { # two macros |
|
5564
|
0
|
|
|
|
|
0
|
($m1, $m2) = split ' ', $s; |
|
5565
|
|
|
|
|
|
|
} |
|
5566
|
|
|
|
|
|
|
else { |
|
5567
|
|
|
|
|
|
|
# XXX rather than using a fake macro name which will probably |
|
5568
|
|
|
|
|
|
|
# give a compile error later, we should really warn/die here? |
|
5569
|
0
|
|
|
|
|
0
|
($m1, $m2) = ($s, 'UNKNOWN_CVT'); |
|
5570
|
|
|
|
|
|
|
} |
|
5571
|
|
|
|
|
|
|
|
|
5572
|
0
|
|
|
|
|
0
|
$self->{get_macro} = $xsub->{interface_macro} = $m1; |
|
5573
|
0
|
|
|
|
|
0
|
$self->{set_macro} = $xsub->{interface_macro_set} = $m2; |
|
5574
|
|
|
|
|
|
|
|
|
5575
|
0
|
|
|
|
|
0
|
1; |
|
5576
|
|
|
|
|
|
|
} |
|
5577
|
|
|
|
|
|
|
|
|
5578
|
|
|
|
|
|
|
|
|
5579
|
|
|
|
|
|
|
# ====================================================================== |
|
5580
|
|
|
|
|
|
|
|
|
5581
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::OVERLOAD; |
|
5582
|
|
|
|
|
|
|
|
|
5583
|
|
|
|
|
|
|
# Handle OVERLOAD keyword |
|
5584
|
|
|
|
|
|
|
|
|
5585
|
19
|
|
|
19
|
|
97
|
BEGIN { $build_subclass->(-parent => 'multiline_merged', |
|
5586
|
|
|
|
|
|
|
'ops', # Hash ref of seen overloaded op names |
|
5587
|
|
|
|
|
|
|
)}; |
|
5588
|
|
|
|
|
|
|
|
|
5589
|
|
|
|
|
|
|
# Add all overload method names, like 'cmp', '<=>', etc, (possibly |
|
5590
|
|
|
|
|
|
|
# multiple ones per line) until the next keyword line, as 'seen' keys to |
|
5591
|
|
|
|
|
|
|
# the $xsub->{overload_name_seen} hash. |
|
5592
|
|
|
|
|
|
|
|
|
5593
|
|
|
|
|
|
|
sub parse { |
|
5594
|
6
|
|
|
6
|
|
21
|
my __PACKAGE__ $self = shift; |
|
5595
|
6
|
|
|
|
|
19
|
my ExtUtils::ParseXS $pxs = shift; |
|
5596
|
6
|
|
|
|
|
21
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5597
|
6
|
|
|
|
|
18
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5598
|
|
|
|
|
|
|
|
|
5599
|
6
|
|
|
|
|
58
|
$self->SUPER::parse($pxs); # set file/line_no, get lines, set text |
|
5600
|
|
|
|
|
|
|
|
|
5601
|
6
|
|
|
|
|
21
|
my $s = $self->{text}; |
|
5602
|
6
|
|
|
|
|
56
|
while ($s =~ s/^\s*([\w:"\\)\+\-\*\/\%\<\>\.\&\|\^\!\~\{\}\=]+)\s*//) { |
|
5603
|
13
|
|
|
|
|
70
|
$self->{ops}{$1} = 1; |
|
5604
|
13
|
|
|
|
|
53
|
$xsub->{overload_name_seen}{$1} = 1; |
|
5605
|
|
|
|
|
|
|
} |
|
5606
|
|
|
|
|
|
|
|
|
5607
|
|
|
|
|
|
|
# Mark the current package as being overloaded |
|
5608
|
|
|
|
|
|
|
$pxs->{map_overloaded_package_to_C_package}->{$xsub->{PACKAGE_name}} |
|
5609
|
6
|
|
|
|
|
51
|
= $xsub->{PACKAGE_C_name}; |
|
5610
|
|
|
|
|
|
|
|
|
5611
|
6
|
|
|
|
|
21
|
1; |
|
5612
|
|
|
|
|
|
|
} |
|
5613
|
|
|
|
|
|
|
|
|
5614
|
|
|
|
|
|
|
|
|
5615
|
|
|
|
|
|
|
# ====================================================================== |
|
5616
|
|
|
|
|
|
|
|
|
5617
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::ATTRS; |
|
5618
|
|
|
|
|
|
|
|
|
5619
|
|
|
|
|
|
|
# Handle ATTRS keyword |
|
5620
|
|
|
|
|
|
|
|
|
5621
|
19
|
|
|
19
|
|
99
|
BEGIN { $build_subclass->(-parent => 'multiline', |
|
5622
|
|
|
|
|
|
|
)}; |
|
5623
|
|
|
|
|
|
|
|
|
5624
|
|
|
|
|
|
|
|
|
5625
|
|
|
|
|
|
|
# Read each lines's worth of attributes into a string that is pushed |
|
5626
|
|
|
|
|
|
|
# to the $xsub->{attributes} array. Note that it doesn't matter that multiple |
|
5627
|
|
|
|
|
|
|
# space-separated attributes on the same line are stored as a single |
|
5628
|
|
|
|
|
|
|
# string; later, all the attribute lines are joined together into a single |
|
5629
|
|
|
|
|
|
|
# string to pass to apply_attrs_string(). |
|
5630
|
|
|
|
|
|
|
|
|
5631
|
|
|
|
|
|
|
sub parse { |
|
5632
|
5
|
|
|
5
|
|
35
|
my __PACKAGE__ $self = shift; |
|
5633
|
5
|
|
|
|
|
25
|
my ExtUtils::ParseXS $pxs = shift; |
|
5634
|
5
|
|
|
|
|
17
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5635
|
5
|
|
|
|
|
11
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5636
|
|
|
|
|
|
|
|
|
5637
|
5
|
|
|
|
|
48
|
$self->SUPER::parse($pxs); # set file/line_no, get lines |
|
5638
|
5
|
|
|
|
|
16
|
for (@{$self->{lines}}) { |
|
|
5
|
|
|
|
|
23
|
|
|
5639
|
6
|
|
|
|
|
37
|
ExtUtils::ParseXS::Utilities::trim_whitespace($_); |
|
5640
|
6
|
|
|
|
|
17
|
push @{$xsub->{attributes}}, $_; |
|
|
6
|
|
|
|
|
31
|
|
|
5641
|
|
|
|
|
|
|
} |
|
5642
|
5
|
|
|
|
|
25
|
1; |
|
5643
|
|
|
|
|
|
|
} |
|
5644
|
|
|
|
|
|
|
|
|
5645
|
|
|
|
|
|
|
|
|
5646
|
|
|
|
|
|
|
# ====================================================================== |
|
5647
|
|
|
|
|
|
|
|
|
5648
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::PROTOTYPE; |
|
5649
|
|
|
|
|
|
|
|
|
5650
|
|
|
|
|
|
|
# Handle PROTOTYPE keyword |
|
5651
|
|
|
|
|
|
|
|
|
5652
|
19
|
|
|
19
|
|
87
|
BEGIN { $build_subclass->(-parent => 'multiline', |
|
5653
|
|
|
|
|
|
|
'prototype', # Str: 0 (disable), 1 (enable), 2 ("") or "$$@" etc |
|
5654
|
|
|
|
|
|
|
)}; |
|
5655
|
|
|
|
|
|
|
|
|
5656
|
|
|
|
|
|
|
|
|
5657
|
|
|
|
|
|
|
# PROTOTYPE: Process one or more lines of the form |
|
5658
|
|
|
|
|
|
|
# DISABLE |
|
5659
|
|
|
|
|
|
|
# ENABLE |
|
5660
|
|
|
|
|
|
|
# $$@ # a literal prototype |
|
5661
|
|
|
|
|
|
|
# # an empty prototype - equivalent to foo() { ...} |
|
5662
|
|
|
|
|
|
|
# |
|
5663
|
|
|
|
|
|
|
# The last line takes precedence. |
|
5664
|
|
|
|
|
|
|
# XXX It's a design flaw that more than one line can be processed. |
|
5665
|
|
|
|
|
|
|
|
|
5666
|
|
|
|
|
|
|
sub parse { |
|
5667
|
12
|
|
|
12
|
|
43
|
my __PACKAGE__ $self = shift; |
|
5668
|
12
|
|
|
|
|
34
|
my ExtUtils::ParseXS $pxs = shift; |
|
5669
|
12
|
|
|
|
|
30
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5670
|
12
|
|
|
|
|
29
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5671
|
|
|
|
|
|
|
|
|
5672
|
12
|
|
|
|
|
134
|
$self->SUPER::parse($pxs); # set file/line_no, get lines |
|
5673
|
|
|
|
|
|
|
|
|
5674
|
12
|
|
|
|
|
26
|
my $proto; |
|
5675
|
|
|
|
|
|
|
|
|
5676
|
|
|
|
|
|
|
$pxs->death("Error: only one PROTOTYPE definition allowed per xsub") |
|
5677
|
12
|
100
|
|
|
|
71
|
if $xsub->{seen_PROTOTYPE}; |
|
5678
|
11
|
|
|
|
|
43
|
$xsub->{seen_PROTOTYPE} = 1; |
|
5679
|
|
|
|
|
|
|
|
|
5680
|
11
|
|
|
|
|
24
|
for (@{$self->{lines}}) { |
|
|
11
|
|
|
|
|
38
|
|
|
5681
|
18
|
100
|
|
|
|
157
|
next unless /\S/; |
|
5682
|
12
|
|
|
|
|
60
|
ExtUtils::ParseXS::Utilities::trim_whitespace($_); |
|
5683
|
|
|
|
|
|
|
|
|
5684
|
12
|
100
|
|
|
|
67
|
if ($_ eq 'DISABLE') { |
|
|
|
100
|
|
|
|
|
|
|
5685
|
2
|
|
|
|
|
15
|
$proto = 0; |
|
5686
|
|
|
|
|
|
|
} |
|
5687
|
|
|
|
|
|
|
elsif ($_ eq 'ENABLE') { |
|
5688
|
1
|
|
|
|
|
11
|
$proto = 1; |
|
5689
|
|
|
|
|
|
|
} |
|
5690
|
|
|
|
|
|
|
else { |
|
5691
|
9
|
|
|
|
|
27
|
s/\s+//g; # remove any whitespace |
|
5692
|
9
|
100
|
|
|
|
52
|
$pxs->death("Error: invalid prototype '$_'") |
|
5693
|
|
|
|
|
|
|
unless ExtUtils::ParseXS::Utilities::valid_proto_string($_); |
|
5694
|
8
|
|
|
|
|
59
|
$proto = ExtUtils::ParseXS::Utilities::C_string($_); |
|
5695
|
|
|
|
|
|
|
} |
|
5696
|
|
|
|
|
|
|
} |
|
5697
|
|
|
|
|
|
|
|
|
5698
|
|
|
|
|
|
|
# If no prototype specified, then assume empty prototype "" |
|
5699
|
10
|
100
|
|
|
|
33
|
$proto = 2 unless defined $proto; |
|
5700
|
|
|
|
|
|
|
|
|
5701
|
10
|
|
|
|
|
37
|
$self->{prototype} = $proto; |
|
5702
|
10
|
|
|
|
|
46
|
$xsub->{prototype} = $proto; |
|
5703
|
|
|
|
|
|
|
|
|
5704
|
10
|
|
|
|
|
41
|
$pxs->{proto_behaviour_specified} = 1; |
|
5705
|
10
|
|
|
|
|
37
|
1; |
|
5706
|
|
|
|
|
|
|
} |
|
5707
|
|
|
|
|
|
|
|
|
5708
|
|
|
|
|
|
|
|
|
5709
|
|
|
|
|
|
|
# ====================================================================== |
|
5710
|
|
|
|
|
|
|
|
|
5711
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::codeblock; |
|
5712
|
|
|
|
|
|
|
|
|
5713
|
|
|
|
|
|
|
# Base class for Nodes which contain lines of literal C code |
|
5714
|
|
|
|
|
|
|
# (such as PREINIT: and CODE:) |
|
5715
|
|
|
|
|
|
|
|
|
5716
|
19
|
|
|
19
|
|
120
|
BEGIN { $build_subclass->(-parent => 'multiline', |
|
5717
|
|
|
|
|
|
|
)}; |
|
5718
|
|
|
|
|
|
|
|
|
5719
|
|
|
|
|
|
|
|
|
5720
|
|
|
|
|
|
|
# No parse() method: we just use the inherited Node::multiline's one |
|
5721
|
|
|
|
|
|
|
|
|
5722
|
|
|
|
|
|
|
|
|
5723
|
|
|
|
|
|
|
# Emit the lines of code, skipping any initial blank lines, |
|
5724
|
|
|
|
|
|
|
# and possibly wrapping in '#line' directives. |
|
5725
|
|
|
|
|
|
|
|
|
5726
|
|
|
|
|
|
|
sub as_code { |
|
5727
|
134
|
|
|
134
|
|
266
|
my __PACKAGE__ $self = shift; |
|
5728
|
134
|
|
|
|
|
751
|
my ExtUtils::ParseXS $pxs = shift; |
|
5729
|
134
|
|
|
|
|
271
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5730
|
134
|
|
|
|
|
254
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5731
|
|
|
|
|
|
|
|
|
5732
|
134
|
|
|
|
|
257
|
my @lines = map "$_\n", @{$self->{lines}}; |
|
|
134
|
|
|
|
|
1159
|
|
|
5733
|
|
|
|
|
|
|
|
|
5734
|
134
|
|
|
|
|
282
|
my $n; |
|
5735
|
|
|
|
|
|
|
|
|
5736
|
|
|
|
|
|
|
# Ignore any text following the keyword on the same line. |
|
5737
|
|
|
|
|
|
|
# XXX this quietly ignores any such text - really it should |
|
5738
|
|
|
|
|
|
|
# warn, but not yet for backwards compatibility. |
|
5739
|
134
|
50
|
|
|
|
524
|
$n++, shift @lines if @lines; |
|
5740
|
|
|
|
|
|
|
|
|
5741
|
|
|
|
|
|
|
# strip leading blank lines |
|
5742
|
134
|
|
66
|
|
|
1324
|
$n++, shift @lines while @lines && $lines[0] !~ /\S/; |
|
5743
|
|
|
|
|
|
|
|
|
5744
|
|
|
|
|
|
|
# Add a leading '#line' if needed. |
|
5745
|
|
|
|
|
|
|
# The XSubPPtmp test is a bit of a hack - it skips synthetic blocks |
|
5746
|
|
|
|
|
|
|
# added to boot etc which may not have line numbers. |
|
5747
|
134
|
|
|
|
|
378
|
my $line0 = $lines[0]; |
|
5748
|
134
|
100
|
66
|
|
|
1648
|
if ( $pxs->{config_WantLineNumbers} |
|
|
|
|
66
|
|
|
|
|
|
5749
|
|
|
|
|
|
|
&& ! ( defined $line0 |
|
5750
|
|
|
|
|
|
|
&& ( $line0 =~ /^\s*#\s*line\b/ |
|
5751
|
|
|
|
|
|
|
|| $line0 =~ /^#if XSubPPtmp/ |
|
5752
|
|
|
|
|
|
|
) |
|
5753
|
|
|
|
|
|
|
) |
|
5754
|
|
|
|
|
|
|
) { |
|
5755
|
|
|
|
|
|
|
unshift @lines, |
|
5756
|
|
|
|
|
|
|
"#line " |
|
5757
|
|
|
|
|
|
|
. ($self->{line_no} + $n) |
|
5758
|
|
|
|
|
|
|
. " \"" |
|
5759
|
|
|
|
|
|
|
. ExtUtils::ParseXS::Utilities::escape_file_for_line_directive( |
|
5760
|
|
|
|
|
|
|
$self->{file}) |
|
5761
|
120
|
|
|
|
|
807
|
. "\"\n"; |
|
5762
|
|
|
|
|
|
|
} |
|
5763
|
|
|
|
|
|
|
|
|
5764
|
|
|
|
|
|
|
# Add a final "restoring" '#line' |
|
5765
|
|
|
|
|
|
|
push @lines, 'ExtUtils::ParseXS::CountLines'->end_marker . "\n" |
|
5766
|
134
|
100
|
|
|
|
652
|
if $pxs->{config_WantLineNumbers}; |
|
5767
|
|
|
|
|
|
|
|
|
5768
|
134
|
|
|
|
|
599
|
print for @lines; |
|
5769
|
|
|
|
|
|
|
} |
|
5770
|
|
|
|
|
|
|
|
|
5771
|
|
|
|
|
|
|
|
|
5772
|
|
|
|
|
|
|
# ====================================================================== |
|
5773
|
|
|
|
|
|
|
|
|
5774
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::CODE; |
|
5775
|
|
|
|
|
|
|
|
|
5776
|
|
|
|
|
|
|
# Store the code lines associated with the CODE keyword |
|
5777
|
|
|
|
|
|
|
|
|
5778
|
19
|
|
|
19
|
|
120
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5779
|
|
|
|
|
|
|
)}; |
|
5780
|
|
|
|
|
|
|
|
|
5781
|
|
|
|
|
|
|
sub parse { |
|
5782
|
112
|
|
|
112
|
|
321
|
my __PACKAGE__ $self = shift; |
|
5783
|
112
|
|
|
|
|
241
|
my ExtUtils::ParseXS $pxs = shift; |
|
5784
|
112
|
|
|
|
|
199
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5785
|
112
|
|
|
|
|
190
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5786
|
|
|
|
|
|
|
|
|
5787
|
112
|
|
|
|
|
679
|
$self->SUPER::parse($pxs); # set file/line_no/lines |
|
5788
|
|
|
|
|
|
|
|
|
5789
|
|
|
|
|
|
|
# Check if the code block includes "RETVAL". This check is for later |
|
5790
|
|
|
|
|
|
|
# use to warn if RETVAL is used but no OUTPUT block is present. |
|
5791
|
|
|
|
|
|
|
# Ignore if its only being used in an 'ignore this var' situation. |
|
5792
|
112
|
|
|
|
|
215
|
my $code = join "\n", @{$self->{lines}}; |
|
|
112
|
|
|
|
|
454
|
|
|
5793
|
|
|
|
|
|
|
$xbody->{seen_RETVAL_in_CODE} = |
|
5794
|
112
|
|
100
|
|
|
1214
|
$code =~ /\bRETVAL\b/ |
|
5795
|
|
|
|
|
|
|
&& $code !~ /\b\QPERL_UNUSED_VAR(RETVAL)/; |
|
5796
|
|
|
|
|
|
|
|
|
5797
|
|
|
|
|
|
|
# Horrible 'void' return arg count hack. |
|
5798
|
|
|
|
|
|
|
# |
|
5799
|
|
|
|
|
|
|
# Until about 1996, xsubpp always emitted 'XSRETURN(1)', even for a |
|
5800
|
|
|
|
|
|
|
# void XSUB. This was fixed for CODE-less void XSUBs simply by |
|
5801
|
|
|
|
|
|
|
# actually honouring the 'void' type and emitting 'XSRETURN_EMPTY' |
|
5802
|
|
|
|
|
|
|
# instead. However, for CODE blocks, the documentation had already |
|
5803
|
|
|
|
|
|
|
# endorsed a coding style along the lines of |
|
5804
|
|
|
|
|
|
|
# |
|
5805
|
|
|
|
|
|
|
# void |
|
5806
|
|
|
|
|
|
|
# foo(...) |
|
5807
|
|
|
|
|
|
|
# CODE: |
|
5808
|
|
|
|
|
|
|
# ST(0) = sv_newmortal(); |
|
5809
|
|
|
|
|
|
|
# |
|
5810
|
|
|
|
|
|
|
# i.e. the XSUB returns an SV even when the return type is 'void'. |
|
5811
|
|
|
|
|
|
|
# In 2024 there is still lots of code of this style out in the wild, |
|
5812
|
|
|
|
|
|
|
# even in the distros bundled with perl. |
|
5813
|
|
|
|
|
|
|
# |
|
5814
|
|
|
|
|
|
|
# So honouring the void type here breaks lots of existing code. Thus |
|
5815
|
|
|
|
|
|
|
# this hack specifically looks for: void XSUBs with a CODE block that |
|
5816
|
|
|
|
|
|
|
# appears to put stuff on the stack via 'ST(n)=' or 'XST_m()', and if |
|
5817
|
|
|
|
|
|
|
# so, emits 'XSRETURN(1)' rather than the 'XSRETURN_EMPTY' implied by |
|
5818
|
|
|
|
|
|
|
# the 'void' return type. |
|
5819
|
|
|
|
|
|
|
# |
|
5820
|
|
|
|
|
|
|
# So set a flag which indicates that a CODE block sets ST(0). This |
|
5821
|
|
|
|
|
|
|
# will be used later when deciding how/whether to emit EXTEND(n) and |
|
5822
|
|
|
|
|
|
|
# XSRETURN(n). |
|
5823
|
|
|
|
|
|
|
|
|
5824
|
112
|
|
|
|
|
1275
|
my $st0 = |
|
5825
|
|
|
|
|
|
|
$code =~ m{ ( \b ST \s* \( [^;]* = ) |
|
5826
|
|
|
|
|
|
|
| ( \b XST_m\w+\s* \( ) }x; |
|
5827
|
|
|
|
|
|
|
|
|
5828
|
|
|
|
|
|
|
$pxs->Warn("Warning: ST(0) isn't consistently set in every CASE's CODE block") |
|
5829
|
|
|
|
|
|
|
if defined $xsub->{CODE_sets_ST0} |
|
5830
|
112
|
100
|
100
|
|
|
570
|
&& $xsub->{CODE_sets_ST0} ne $st0; |
|
5831
|
112
|
|
|
|
|
356
|
$xsub->{CODE_sets_ST0} = $st0; |
|
5832
|
|
|
|
|
|
|
|
|
5833
|
112
|
|
|
|
|
372
|
1; |
|
5834
|
|
|
|
|
|
|
} |
|
5835
|
|
|
|
|
|
|
|
|
5836
|
|
|
|
|
|
|
|
|
5837
|
|
|
|
|
|
|
# ====================================================================== |
|
5838
|
|
|
|
|
|
|
|
|
5839
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::CLEANUP; |
|
5840
|
|
|
|
|
|
|
|
|
5841
|
|
|
|
|
|
|
# Store the code lines associated with the CLEANUP: keyword |
|
5842
|
|
|
|
|
|
|
|
|
5843
|
19
|
|
|
19
|
|
105
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5844
|
|
|
|
|
|
|
)}; |
|
5845
|
|
|
|
|
|
|
|
|
5846
|
|
|
|
|
|
|
# Currently all methods are just inherited. |
|
5847
|
|
|
|
|
|
|
|
|
5848
|
|
|
|
|
|
|
|
|
5849
|
|
|
|
|
|
|
# ====================================================================== |
|
5850
|
|
|
|
|
|
|
|
|
5851
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INIT; |
|
5852
|
|
|
|
|
|
|
|
|
5853
|
|
|
|
|
|
|
# Store the code lines associated with the INIT: keyword |
|
5854
|
|
|
|
|
|
|
|
|
5855
|
19
|
|
|
19
|
|
84
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5856
|
|
|
|
|
|
|
)}; |
|
5857
|
|
|
|
|
|
|
|
|
5858
|
|
|
|
|
|
|
# Currently all methods are just inherited. |
|
5859
|
|
|
|
|
|
|
|
|
5860
|
|
|
|
|
|
|
|
|
5861
|
|
|
|
|
|
|
# ====================================================================== |
|
5862
|
|
|
|
|
|
|
|
|
5863
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::POSTCALL; |
|
5864
|
|
|
|
|
|
|
|
|
5865
|
|
|
|
|
|
|
# Store the code lines associated with the POSTCALL: keyword |
|
5866
|
|
|
|
|
|
|
|
|
5867
|
19
|
|
|
19
|
|
84
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5868
|
|
|
|
|
|
|
)}; |
|
5869
|
|
|
|
|
|
|
|
|
5870
|
|
|
|
|
|
|
# Currently all methods are just inherited. |
|
5871
|
|
|
|
|
|
|
|
|
5872
|
|
|
|
|
|
|
|
|
5873
|
|
|
|
|
|
|
# ====================================================================== |
|
5874
|
|
|
|
|
|
|
|
|
5875
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::PPCODE; |
|
5876
|
|
|
|
|
|
|
|
|
5877
|
|
|
|
|
|
|
# Store the code lines associated with the PPCODE keyword |
|
5878
|
|
|
|
|
|
|
|
|
5879
|
19
|
|
|
19
|
|
83
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5880
|
|
|
|
|
|
|
)}; |
|
5881
|
|
|
|
|
|
|
|
|
5882
|
|
|
|
|
|
|
sub parse { |
|
5883
|
8
|
|
|
8
|
|
19
|
my __PACKAGE__ $self = shift; |
|
5884
|
8
|
|
|
|
|
26
|
my ExtUtils::ParseXS $pxs = shift; |
|
5885
|
8
|
|
|
|
|
16
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5886
|
8
|
|
|
|
|
20
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5887
|
|
|
|
|
|
|
|
|
5888
|
8
|
|
|
|
|
51
|
$self->SUPER::parse($pxs); # set file/line_no/lines |
|
5889
|
8
|
|
|
|
|
22
|
$xsub->{seen_PPCODE} = 1; |
|
5890
|
8
|
100
|
|
|
|
17
|
$pxs->death("Error: PPCODE must be the last thing") if @{$pxs->{line}}; |
|
|
8
|
|
|
|
|
57
|
|
|
5891
|
7
|
|
|
|
|
20
|
1; |
|
5892
|
|
|
|
|
|
|
} |
|
5893
|
|
|
|
|
|
|
|
|
5894
|
|
|
|
|
|
|
|
|
5895
|
|
|
|
|
|
|
sub as_code { |
|
5896
|
7
|
|
|
7
|
|
18
|
my __PACKAGE__ $self = shift; |
|
5897
|
7
|
|
|
|
|
32
|
my ExtUtils::ParseXS $pxs = shift; |
|
5898
|
7
|
|
|
|
|
11
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5899
|
7
|
|
|
|
|
11
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5900
|
|
|
|
|
|
|
|
|
5901
|
|
|
|
|
|
|
# Just emit the code block and then code to do PUTBACK and return. |
|
5902
|
|
|
|
|
|
|
# The # user of PPCODE is supposed to have done all the return stack |
|
5903
|
|
|
|
|
|
|
# manipulation themselves. |
|
5904
|
|
|
|
|
|
|
# Note that PPCODE blocks often include a XSRETURN(1) or |
|
5905
|
|
|
|
|
|
|
# similar, so any final code we emit after that is in danger of |
|
5906
|
|
|
|
|
|
|
# triggering a "statement is unreachable" warning. |
|
5907
|
|
|
|
|
|
|
|
|
5908
|
7
|
|
|
|
|
41
|
$self->SUPER::as_code($pxs, $xsub, $xbody); # emit code block |
|
5909
|
|
|
|
|
|
|
|
|
5910
|
7
|
50
|
|
|
|
67
|
print "\tLEAVE;\n" if $xsub->{SCOPE_enabled}; |
|
5911
|
|
|
|
|
|
|
|
|
5912
|
|
|
|
|
|
|
# Suppress "statement is unreachable" warning on HPUX |
|
5913
|
7
|
50
|
|
|
|
56
|
print "#if defined(__HP_cc) || defined(__HP_aCC)\n", |
|
5914
|
|
|
|
|
|
|
"#pragma diag_suppress 2111\n", |
|
5915
|
|
|
|
|
|
|
"#endif\n" |
|
5916
|
|
|
|
|
|
|
if $^O eq "hpux"; |
|
5917
|
|
|
|
|
|
|
|
|
5918
|
7
|
|
|
|
|
22
|
print "\tPUTBACK;\n\treturn;\n"; |
|
5919
|
|
|
|
|
|
|
|
|
5920
|
|
|
|
|
|
|
# Suppress "statement is unreachable" warning on HPUX |
|
5921
|
7
|
50
|
|
|
|
86
|
print "#if defined(__HP_cc) || defined(__HP_aCC)\n", |
|
5922
|
|
|
|
|
|
|
"#pragma diag_default 2111\n", |
|
5923
|
|
|
|
|
|
|
"#endif\n" |
|
5924
|
|
|
|
|
|
|
if $^O eq "hpux"; |
|
5925
|
|
|
|
|
|
|
} |
|
5926
|
|
|
|
|
|
|
|
|
5927
|
|
|
|
|
|
|
|
|
5928
|
|
|
|
|
|
|
# ====================================================================== |
|
5929
|
|
|
|
|
|
|
|
|
5930
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::PREINIT; |
|
5931
|
|
|
|
|
|
|
|
|
5932
|
|
|
|
|
|
|
# Store the code lines associated with the PREINIT: keyword |
|
5933
|
|
|
|
|
|
|
|
|
5934
|
19
|
|
|
19
|
|
94
|
BEGIN { $build_subclass->(-parent => 'codeblock', |
|
5935
|
|
|
|
|
|
|
)}; |
|
5936
|
|
|
|
|
|
|
|
|
5937
|
|
|
|
|
|
|
# Currently all methods are just inherited. |
|
5938
|
|
|
|
|
|
|
|
|
5939
|
|
|
|
|
|
|
|
|
5940
|
|
|
|
|
|
|
# ====================================================================== |
|
5941
|
|
|
|
|
|
|
|
|
5942
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::keylines; |
|
5943
|
|
|
|
|
|
|
|
|
5944
|
|
|
|
|
|
|
# Base class for keyword FOO nodes which have a FOO_line kid node for |
|
5945
|
|
|
|
|
|
|
# each line making up the keyword - such as OUTPUT etc. |
|
5946
|
|
|
|
|
|
|
|
|
5947
|
19
|
|
|
19
|
|
112
|
BEGIN { $build_subclass->( |
|
5948
|
|
|
|
|
|
|
'lines', # Array ref of all lines until the next keyword |
|
5949
|
|
|
|
|
|
|
)}; |
|
5950
|
|
|
|
|
|
|
|
|
5951
|
|
|
|
|
|
|
|
|
5952
|
|
|
|
|
|
|
# Process each line on and following the keyword line. |
|
5953
|
|
|
|
|
|
|
# For each line, create a FOO_line kid and call its parse() method. |
|
5954
|
|
|
|
|
|
|
|
|
5955
|
|
|
|
|
|
|
sub parse { |
|
5956
|
469
|
|
|
469
|
|
1587
|
my __PACKAGE__ $self = shift; |
|
5957
|
469
|
|
|
|
|
905
|
my ExtUtils::ParseXS $pxs = shift; |
|
5958
|
469
|
|
|
|
|
825
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
5959
|
469
|
|
|
|
|
764
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
5960
|
469
|
|
|
|
|
868
|
my $do_notimplemented = shift; |
|
5961
|
|
|
|
|
|
|
|
|
5962
|
469
|
|
|
|
|
2002
|
$self->SUPER::parse($pxs); # set file/line_no |
|
5963
|
|
|
|
|
|
|
|
|
5964
|
|
|
|
|
|
|
# Consume and process lines until the next directive. |
|
5965
|
469
|
|
100
|
|
|
834
|
while( @{$pxs->{line}} |
|
|
825
|
|
|
|
|
8333
|
|
|
5966
|
|
|
|
|
|
|
&& $pxs->{line}[0] !~ /^$ExtUtils::ParseXS::BLOCK_regexp/o) |
|
5967
|
|
|
|
|
|
|
{ |
|
5968
|
358
|
100
|
|
|
|
897
|
if ($do_notimplemented) { |
|
5969
|
|
|
|
|
|
|
# treat NOT_IMPLEMENTED_YET as another block separator, in |
|
5970
|
|
|
|
|
|
|
# addition to $BLOCK_regexp. |
|
5971
|
157
|
100
|
|
|
|
635
|
last if $pxs->{line}[0] =~ /^\s*NOT_IMPLEMENTED_YET/; |
|
5972
|
|
|
|
|
|
|
} |
|
5973
|
|
|
|
|
|
|
|
|
5974
|
356
|
100
|
|
|
|
1855
|
unless ($pxs->{line}[0] =~ /\S/) { # skip blank lines |
|
5975
|
67
|
|
|
|
|
124
|
shift @{$pxs->{line}}; |
|
|
67
|
|
|
|
|
172
|
|
|
5976
|
67
|
|
|
|
|
185
|
next; |
|
5977
|
|
|
|
|
|
|
} |
|
5978
|
|
|
|
|
|
|
|
|
5979
|
289
|
|
|
|
|
452
|
push @{$self->{lines}}, $pxs->{line}[0]; |
|
|
289
|
|
|
|
|
999
|
|
|
5980
|
|
|
|
|
|
|
|
|
5981
|
289
|
|
|
|
|
705
|
my $class = ref($self) . '_line'; |
|
5982
|
289
|
|
|
|
|
1848
|
my $kid = $class->new(); |
|
5983
|
|
|
|
|
|
|
# Keep the current line in $self->{lines} for now so that the |
|
5984
|
|
|
|
|
|
|
# parse() method below sees the right line number. We rely on that |
|
5985
|
|
|
|
|
|
|
# method to actually pop the line. |
|
5986
|
289
|
100
|
|
|
|
1174
|
if ($kid->parse($pxs, $xsub, $xbody, $self)) { |
|
5987
|
264
|
|
|
|
|
467
|
push @{$self->{kids}}, $kid; |
|
|
264
|
|
|
|
|
896
|
|
|
5988
|
|
|
|
|
|
|
} |
|
5989
|
|
|
|
|
|
|
} |
|
5990
|
|
|
|
|
|
|
|
|
5991
|
469
|
|
|
|
|
1652
|
1; |
|
5992
|
|
|
|
|
|
|
} |
|
5993
|
|
|
|
|
|
|
|
|
5994
|
|
|
|
|
|
|
|
|
5995
|
|
|
|
|
|
|
# call as_code() on any kids which have that method |
|
5996
|
|
|
|
|
|
|
|
|
5997
|
|
|
|
|
|
|
sub as_code { |
|
5998
|
184
|
|
|
184
|
|
341
|
my __PACKAGE__ $self = shift; |
|
5999
|
184
|
|
|
|
|
327
|
my ExtUtils::ParseXS $pxs = shift; |
|
6000
|
184
|
|
|
|
|
264
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6001
|
184
|
|
|
|
|
293
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6002
|
|
|
|
|
|
|
|
|
6003
|
184
|
100
|
|
|
|
605
|
return unless $self->{kids}; |
|
6004
|
178
|
|
|
|
|
560
|
$_->as_code($pxs, $xsub, $xbody) for @{$self->{kids}}; |
|
|
178
|
|
|
|
|
913
|
|
|
6005
|
|
|
|
|
|
|
} |
|
6006
|
|
|
|
|
|
|
|
|
6007
|
|
|
|
|
|
|
|
|
6008
|
|
|
|
|
|
|
# ====================================================================== |
|
6009
|
|
|
|
|
|
|
|
|
6010
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::keyline; |
|
6011
|
|
|
|
|
|
|
|
|
6012
|
|
|
|
|
|
|
# Base class for FOO_line nodes which have a FOO node as |
|
6013
|
|
|
|
|
|
|
# their parent. |
|
6014
|
|
|
|
|
|
|
|
|
6015
|
19
|
|
|
19
|
|
101
|
BEGIN { $build_subclass->( |
|
6016
|
|
|
|
|
|
|
'line', # Str: text of current line |
|
6017
|
|
|
|
|
|
|
)}; |
|
6018
|
|
|
|
|
|
|
|
|
6019
|
|
|
|
|
|
|
|
|
6020
|
|
|
|
|
|
|
# The two jobs of this parse method are to grab the next line, and also to |
|
6021
|
|
|
|
|
|
|
# set the right line number for any warning or error messages triggered by |
|
6022
|
|
|
|
|
|
|
# the current line. It is called as a SUPER by the parse() methods of its |
|
6023
|
|
|
|
|
|
|
# concrete subclasses. |
|
6024
|
|
|
|
|
|
|
|
|
6025
|
|
|
|
|
|
|
sub parse { |
|
6026
|
289
|
|
|
289
|
|
482
|
my __PACKAGE__ $self = shift; |
|
6027
|
289
|
|
|
|
|
583
|
my ExtUtils::ParseXS $pxs = shift; |
|
6028
|
|
|
|
|
|
|
|
|
6029
|
289
|
|
|
|
|
817
|
$self->SUPER::parse($pxs); # set file/line_no |
|
6030
|
|
|
|
|
|
|
# By shifting *now*, the line above gets the correct line number of |
|
6031
|
|
|
|
|
|
|
# this src line, while subsequent processing gives the right line |
|
6032
|
|
|
|
|
|
|
# number for warnings etc, since the warn/err methods assume the line |
|
6033
|
|
|
|
|
|
|
# being processed has already been popped. |
|
6034
|
289
|
|
|
|
|
449
|
my $line = shift @{$pxs->{line}}; # line of text to be processed |
|
|
289
|
|
|
|
|
600
|
|
|
6035
|
289
|
|
|
|
|
710
|
$self->{line} = $line; |
|
6036
|
289
|
|
|
|
|
456
|
1; |
|
6037
|
|
|
|
|
|
|
} |
|
6038
|
|
|
|
|
|
|
|
|
6039
|
|
|
|
|
|
|
|
|
6040
|
|
|
|
|
|
|
# ====================================================================== |
|
6041
|
|
|
|
|
|
|
|
|
6042
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::ALIAS; |
|
6043
|
|
|
|
|
|
|
|
|
6044
|
|
|
|
|
|
|
# Handle ALIAS keyword |
|
6045
|
|
|
|
|
|
|
|
|
6046
|
19
|
|
|
19
|
|
112
|
BEGIN { $build_subclass->(-parent => 'keylines', |
|
6047
|
|
|
|
|
|
|
'aliases', # hashref of all alias => value pairs. |
|
6048
|
|
|
|
|
|
|
# Populated by ALIAS_line::parse() |
|
6049
|
|
|
|
|
|
|
)}; |
|
6050
|
|
|
|
|
|
|
|
|
6051
|
|
|
|
|
|
|
sub parse { |
|
6052
|
18
|
|
|
18
|
|
65
|
my __PACKAGE__ $self = shift; |
|
6053
|
18
|
|
|
|
|
39
|
my ExtUtils::ParseXS $pxs = shift; |
|
6054
|
18
|
|
|
|
|
31
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6055
|
18
|
|
|
|
|
40
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6056
|
|
|
|
|
|
|
|
|
6057
|
18
|
|
|
|
|
50
|
$xsub->{seen_ALIAS} = 1; |
|
6058
|
18
|
|
|
|
|
62
|
$self->SUPER::parse($pxs, $xsub, $xbody); |
|
6059
|
|
|
|
|
|
|
} |
|
6060
|
|
|
|
|
|
|
|
|
6061
|
|
|
|
|
|
|
|
|
6062
|
|
|
|
|
|
|
# ====================================================================== |
|
6063
|
|
|
|
|
|
|
|
|
6064
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::ALIAS_line; |
|
6065
|
|
|
|
|
|
|
|
|
6066
|
|
|
|
|
|
|
# Handle one line from an ALIAS keyword block |
|
6067
|
|
|
|
|
|
|
|
|
6068
|
19
|
|
|
19
|
|
126
|
BEGIN { $build_subclass->(-parent => 'keyline', |
|
6069
|
|
|
|
|
|
|
)}; |
|
6070
|
|
|
|
|
|
|
|
|
6071
|
|
|
|
|
|
|
|
|
6072
|
|
|
|
|
|
|
# Parse one line from an ALIAS block |
|
6073
|
|
|
|
|
|
|
# |
|
6074
|
|
|
|
|
|
|
# Each line can have zero or more definitions, separated by white space. |
|
6075
|
|
|
|
|
|
|
# Each definition is of one of the two forms: |
|
6076
|
|
|
|
|
|
|
# |
|
6077
|
|
|
|
|
|
|
# name = value |
|
6078
|
|
|
|
|
|
|
# name => other_name |
|
6079
|
|
|
|
|
|
|
# |
|
6080
|
|
|
|
|
|
|
# where 'value' is a positive integer (or C macro) and the names are |
|
6081
|
|
|
|
|
|
|
# simple or qualified perl function names. E.g. |
|
6082
|
|
|
|
|
|
|
# |
|
6083
|
|
|
|
|
|
|
# foo = 1 Bar::foo = 2 Bar::baz => Bar::foo |
|
6084
|
|
|
|
|
|
|
# |
|
6085
|
|
|
|
|
|
|
# The RHS of a '=>' is the name of an existing alias |
|
6086
|
|
|
|
|
|
|
# |
|
6087
|
|
|
|
|
|
|
# The results are added to a hash in the parent ALIAS node, as well as |
|
6088
|
|
|
|
|
|
|
# to a couple of per-xsub hashes which accumulate the results across |
|
6089
|
|
|
|
|
|
|
# possibly multiple ALIAS keywords. |
|
6090
|
|
|
|
|
|
|
# |
|
6091
|
|
|
|
|
|
|
# Updates: |
|
6092
|
|
|
|
|
|
|
# $parent->{aliases}{$alias} = $value; |
|
6093
|
|
|
|
|
|
|
# $xsub->{map_alias_name_to_value}{$alias} = $value; |
|
6094
|
|
|
|
|
|
|
# $xsub->{map_alias_value_to_name_seen_hash}{$value}{$alias}++; |
|
6095
|
|
|
|
|
|
|
|
|
6096
|
|
|
|
|
|
|
|
|
6097
|
|
|
|
|
|
|
sub parse { |
|
6098
|
57
|
|
|
57
|
|
97
|
my __PACKAGE__ $self = shift; |
|
6099
|
57
|
|
|
|
|
76
|
my ExtUtils::ParseXS $pxs = shift; |
|
6100
|
57
|
|
|
|
|
104
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6101
|
57
|
|
|
|
|
78
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6102
|
57
|
|
|
|
|
80
|
my ExtUtils::ParseXS::Node::ALIAS $parent = shift; # parent ALIAS node |
|
6103
|
|
|
|
|
|
|
|
|
6104
|
57
|
|
|
|
|
162
|
$self->SUPER::parse($pxs); # set file/line_no/line |
|
6105
|
57
|
|
|
|
|
142
|
my $line = $self->{line}; # line of text to be processed |
|
6106
|
|
|
|
|
|
|
|
|
6107
|
57
|
|
|
|
|
191
|
ExtUtils::ParseXS::Utilities::trim_whitespace($line); |
|
6108
|
|
|
|
|
|
|
# XXX this skip doesn't make sense - we've already confirmed |
|
6109
|
|
|
|
|
|
|
# line has non-whitespace with the /\S/; so we just skip if the |
|
6110
|
|
|
|
|
|
|
# line is "0" ? |
|
6111
|
57
|
50
|
|
|
|
157
|
return unless $line; |
|
6112
|
|
|
|
|
|
|
|
|
6113
|
57
|
|
|
|
|
102
|
my $orig = $line; # keep full line for error messages |
|
6114
|
|
|
|
|
|
|
|
|
6115
|
|
|
|
|
|
|
# we use this later for symbolic aliases |
|
6116
|
57
|
|
|
|
|
188
|
my $fname = $pxs->{PACKAGE_class} . $xsub->{decl}{name}; |
|
6117
|
|
|
|
|
|
|
|
|
6118
|
|
|
|
|
|
|
# chop out and process one alias entry from $line |
|
6119
|
|
|
|
|
|
|
|
|
6120
|
57
|
|
|
|
|
464
|
while ($line =~ s/^\s*([\w:]+)\s*=(>?)\s*([\w:]+)\s*//) { |
|
6121
|
58
|
|
|
|
|
291
|
my ($alias, $is_symbolic, $value) = ($1, $2, $3); |
|
6122
|
58
|
|
|
|
|
86
|
my $orig_alias = $alias; |
|
6123
|
|
|
|
|
|
|
|
|
6124
|
58
|
100
|
100
|
|
|
374
|
$pxs->blurt( "Error: in alias definition for '$alias' the value " |
|
6125
|
|
|
|
|
|
|
. "may not contain ':' unless it is symbolic.") |
|
6126
|
|
|
|
|
|
|
if !$is_symbolic and $value=~/:/; |
|
6127
|
|
|
|
|
|
|
|
|
6128
|
|
|
|
|
|
|
# check for optional package definition in the alias |
|
6129
|
58
|
100
|
|
|
|
225
|
$alias = $pxs->{PACKAGE_class} . $alias if $alias !~ /::/; |
|
6130
|
|
|
|
|
|
|
|
|
6131
|
58
|
100
|
|
|
|
119
|
if ($is_symbolic) { |
|
6132
|
11
|
|
|
|
|
36
|
my $orig_value = $value; |
|
6133
|
11
|
100
|
|
|
|
101
|
$value = $pxs->{PACKAGE_class} . $value if $value !~ /::/; |
|
6134
|
11
|
100
|
|
|
|
74
|
if (defined $xsub->{map_alias_name_to_value}{$value}) { |
|
|
|
50
|
|
|
|
|
|
|
6135
|
10
|
|
|
|
|
42
|
$value = $xsub->{map_alias_name_to_value}{$value}; |
|
6136
|
|
|
|
|
|
|
} elsif ($value eq $fname) { |
|
6137
|
0
|
|
|
|
|
0
|
$value = 0; |
|
6138
|
|
|
|
|
|
|
} else { |
|
6139
|
1
|
|
|
|
|
39
|
$pxs->blurt( "Error: unknown alias '$value' in " |
|
6140
|
|
|
|
|
|
|
. "symbolic definition for '$orig_alias'"); |
|
6141
|
|
|
|
|
|
|
} |
|
6142
|
|
|
|
|
|
|
} |
|
6143
|
|
|
|
|
|
|
|
|
6144
|
|
|
|
|
|
|
# check for duplicate alias name & duplicate value |
|
6145
|
58
|
|
|
|
|
163
|
my $prev_value = $xsub->{map_alias_name_to_value}{$alias}; |
|
6146
|
58
|
100
|
|
|
|
162
|
if (defined $prev_value) { |
|
6147
|
4
|
100
|
|
|
|
30
|
if ($prev_value eq $value) { |
|
6148
|
1
|
|
|
|
|
34
|
$pxs->Warn("Warning: ignoring duplicate alias '$orig_alias'") |
|
6149
|
|
|
|
|
|
|
} else { |
|
6150
|
3
|
|
|
|
|
76
|
$pxs->Warn( "Warning: conflicting duplicate alias " |
|
6151
|
|
|
|
|
|
|
. "'$orig_alias' changes definition " |
|
6152
|
|
|
|
|
|
|
. "from '$prev_value' to '$value'"); |
|
6153
|
|
|
|
|
|
|
delete $xsub->{map_alias_value_to_name_seen_hash} |
|
6154
|
3
|
|
|
|
|
22
|
->{$prev_value}{$alias}; |
|
6155
|
|
|
|
|
|
|
} |
|
6156
|
|
|
|
|
|
|
} |
|
6157
|
|
|
|
|
|
|
|
|
6158
|
|
|
|
|
|
|
# Check and see if this alias results in two aliases having the same |
|
6159
|
|
|
|
|
|
|
# value, we only check non-symbolic definitions as the whole point of |
|
6160
|
|
|
|
|
|
|
# symbolic definitions is to say we want to duplicate the value and |
|
6161
|
|
|
|
|
|
|
# it is NOT a mistake. |
|
6162
|
58
|
100
|
|
|
|
136
|
unless ($is_symbolic) { |
|
6163
|
47
|
|
|
|
|
66
|
my @keys= sort keys %{$xsub-> |
|
6164
|
47
|
100
|
|
|
|
385
|
{map_alias_value_to_name_seen_hash}->{$value}||{}}; |
|
6165
|
|
|
|
|
|
|
# deal with an alias of 0, which might not be in the aliases |
|
6166
|
|
|
|
|
|
|
# dataset yet as 0 is the default for the base function ($fname) |
|
6167
|
|
|
|
|
|
|
push @keys, $fname |
|
6168
|
|
|
|
|
|
|
if $value eq "0" and |
|
6169
|
47
|
100
|
100
|
|
|
246
|
!defined $xsub->{map_alias_name_to_value}{$fname}; |
|
6170
|
47
|
100
|
100
|
|
|
164
|
if (@keys and $pxs->{config_author_warnings}) { |
|
6171
|
|
|
|
|
|
|
# We do not warn about value collisions unless author_warnings |
|
6172
|
|
|
|
|
|
|
# are enabled. They aren't helpful to a module consumer, only |
|
6173
|
|
|
|
|
|
|
# the module author. |
|
6174
|
11
|
|
|
|
|
54
|
@keys= map { "'$_'" } |
|
6175
|
7
|
|
|
|
|
34
|
map { my $copy= $_; |
|
|
11
|
|
|
|
|
33
|
|
|
6176
|
11
|
|
|
|
|
145
|
$copy=~s/^$pxs->{PACKAGE_class}//; |
|
6177
|
11
|
|
|
|
|
52
|
$copy |
|
6178
|
|
|
|
|
|
|
} @keys; |
|
6179
|
|
|
|
|
|
|
$pxs->WarnHint( |
|
6180
|
|
|
|
|
|
|
"Warning: aliases '$orig_alias' and " |
|
6181
|
|
|
|
|
|
|
. join(", ", @keys) |
|
6182
|
|
|
|
|
|
|
. " have identical values of $value" |
|
6183
|
|
|
|
|
|
|
. ( $value eq "0" |
|
6184
|
|
|
|
|
|
|
? " - the base function" |
|
6185
|
|
|
|
|
|
|
: "" ), |
|
6186
|
7
|
100
|
|
|
|
117
|
!$xsub->{alias_clash_hinted}++ |
|
|
|
100
|
|
|
|
|
|
|
6187
|
|
|
|
|
|
|
? "If this is deliberate use a " |
|
6188
|
|
|
|
|
|
|
. "symbolic alias instead." |
|
6189
|
|
|
|
|
|
|
: undef |
|
6190
|
|
|
|
|
|
|
); |
|
6191
|
|
|
|
|
|
|
} |
|
6192
|
|
|
|
|
|
|
} |
|
6193
|
|
|
|
|
|
|
|
|
6194
|
58
|
|
|
|
|
277
|
$parent->{aliases}{$alias} = $value; |
|
6195
|
58
|
|
|
|
|
149
|
$xsub->{map_alias_name_to_value}->{$alias} = $value; |
|
6196
|
58
|
|
|
|
|
398
|
$xsub->{map_alias_value_to_name_seen_hash}{$value}{$alias}++; |
|
6197
|
|
|
|
|
|
|
} |
|
6198
|
|
|
|
|
|
|
|
|
6199
|
57
|
100
|
|
|
|
136
|
$pxs->blurt("Error: cannot parse ALIAS definitions from '$orig'") |
|
6200
|
|
|
|
|
|
|
if $line; |
|
6201
|
|
|
|
|
|
|
|
|
6202
|
57
|
|
|
|
|
180
|
1; |
|
6203
|
|
|
|
|
|
|
} |
|
6204
|
|
|
|
|
|
|
|
|
6205
|
|
|
|
|
|
|
|
|
6206
|
|
|
|
|
|
|
# ====================================================================== |
|
6207
|
|
|
|
|
|
|
|
|
6208
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INPUT; |
|
6209
|
|
|
|
|
|
|
|
|
6210
|
|
|
|
|
|
|
# Handle an explicit INPUT: block, or any implicit INPUT |
|
6211
|
|
|
|
|
|
|
# block which can follow an xsub signature or CASE keyword. |
|
6212
|
|
|
|
|
|
|
|
|
6213
|
19
|
|
|
19
|
|
132
|
BEGIN { $build_subclass->(-parent => 'keylines', |
|
6214
|
|
|
|
|
|
|
'implicit', # Bool: this is an INPUT section at the start of the |
|
6215
|
|
|
|
|
|
|
# XSUB/CASE, without an explicit 'INPUT' keyword |
|
6216
|
|
|
|
|
|
|
)}; |
|
6217
|
|
|
|
|
|
|
|
|
6218
|
|
|
|
|
|
|
# The inherited parse() method will call INPUT_line->parse() for each line |
|
6219
|
|
|
|
|
|
|
|
|
6220
|
|
|
|
|
|
|
|
|
6221
|
|
|
|
|
|
|
sub parse { |
|
6222
|
387
|
|
|
387
|
|
839
|
my __PACKAGE__ $self = shift; |
|
6223
|
387
|
|
|
|
|
1462
|
my ExtUtils::ParseXS $pxs = shift; |
|
6224
|
387
|
|
|
|
|
1739
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6225
|
387
|
|
|
|
|
671
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6226
|
|
|
|
|
|
|
|
|
6227
|
|
|
|
|
|
|
# Call the SUPER parse method, which will call INPUT_line->parse() |
|
6228
|
|
|
|
|
|
|
# for each INPUT line. The '1' bool arg indicates to treat |
|
6229
|
|
|
|
|
|
|
# NOT_IMPLEMENTED_YET as another block separator, in addition to |
|
6230
|
|
|
|
|
|
|
# $BLOCK_regexp. |
|
6231
|
387
|
|
|
|
|
3093
|
$self->SUPER::parse($pxs, $xsub, $xbody, 1); |
|
6232
|
|
|
|
|
|
|
|
|
6233
|
387
|
|
|
|
|
6906
|
1; |
|
6234
|
|
|
|
|
|
|
} |
|
6235
|
|
|
|
|
|
|
|
|
6236
|
|
|
|
|
|
|
|
|
6237
|
|
|
|
|
|
|
# ====================================================================== |
|
6238
|
|
|
|
|
|
|
|
|
6239
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::INPUT_line; |
|
6240
|
|
|
|
|
|
|
|
|
6241
|
|
|
|
|
|
|
# Handle one line from an INPUT keyword block |
|
6242
|
|
|
|
|
|
|
|
|
6243
|
19
|
|
|
19
|
|
123
|
BEGIN { $build_subclass->(-parent => 'keyline', |
|
6244
|
|
|
|
|
|
|
'ioparam', # The IO_Param object associated with this INPUT line. |
|
6245
|
|
|
|
|
|
|
|
|
6246
|
|
|
|
|
|
|
# The parsed components of this INPUT line: |
|
6247
|
|
|
|
|
|
|
'type', # Str: char * |
|
6248
|
|
|
|
|
|
|
'is_addr', # Bool: & |
|
6249
|
|
|
|
|
|
|
'name', # Str: foo |
|
6250
|
|
|
|
|
|
|
'init_op', # Str: = |
|
6251
|
|
|
|
|
|
|
'init', # Str: SvIv($arg) |
|
6252
|
|
|
|
|
|
|
)}; |
|
6253
|
|
|
|
|
|
|
|
|
6254
|
|
|
|
|
|
|
|
|
6255
|
|
|
|
|
|
|
# Parse one line in an INPUT block. This method does two main things: |
|
6256
|
|
|
|
|
|
|
# |
|
6257
|
|
|
|
|
|
|
# It parses the line and stores its components in the fields of the |
|
6258
|
|
|
|
|
|
|
# INPUT_line object (which aren't further used for parsing or code |
|
6259
|
|
|
|
|
|
|
# generation) |
|
6260
|
|
|
|
|
|
|
# |
|
6261
|
|
|
|
|
|
|
# It also uses those values to create/update the IO_Param object |
|
6262
|
|
|
|
|
|
|
# associated with this variable. For example with |
|
6263
|
|
|
|
|
|
|
# |
|
6264
|
|
|
|
|
|
|
# void |
|
6265
|
|
|
|
|
|
|
# foo(a = 0) |
|
6266
|
|
|
|
|
|
|
# int a |
|
6267
|
|
|
|
|
|
|
# |
|
6268
|
|
|
|
|
|
|
# a IO_Param object will already have been created with the name 'a' and |
|
6269
|
|
|
|
|
|
|
# default value '0' when the signature was parsed. Parsing the 'int a' |
|
6270
|
|
|
|
|
|
|
# line will set the INPUT_line object's fields to (type => 'int', |
|
6271
|
|
|
|
|
|
|
# name => 'a'), while the IO_Param object will have its type field set to |
|
6272
|
|
|
|
|
|
|
# 'int'. The INPUT_line object also stores a ref to the IO_Param object. |
|
6273
|
|
|
|
|
|
|
# |
|
6274
|
|
|
|
|
|
|
|
|
6275
|
|
|
|
|
|
|
sub parse { |
|
6276
|
151
|
|
|
151
|
|
246
|
my __PACKAGE__ $self = shift; |
|
6277
|
151
|
|
|
|
|
238
|
my ExtUtils::ParseXS $pxs = shift; |
|
6278
|
151
|
|
|
|
|
220
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6279
|
151
|
|
|
|
|
219
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6280
|
151
|
|
|
|
|
241
|
my ExtUtils::ParseXS::Node::INPUT $parent = shift; # parent INPUT node |
|
6281
|
|
|
|
|
|
|
|
|
6282
|
151
|
|
|
|
|
713
|
$self->SUPER::parse($pxs); # set file/line_no/line |
|
6283
|
151
|
|
|
|
|
331
|
my $line = $self->{line}; # line of text to be processed |
|
6284
|
|
|
|
|
|
|
|
|
6285
|
151
|
|
|
|
|
564
|
ExtUtils::ParseXS::Utilities::trim_whitespace($line); |
|
6286
|
|
|
|
|
|
|
|
|
6287
|
|
|
|
|
|
|
# remove any trailing semicolon, except for initialisations |
|
6288
|
151
|
100
|
|
|
|
1009
|
$line =~ s/\s*;$//g unless $line =~ /[=;+].*\S/; |
|
6289
|
|
|
|
|
|
|
|
|
6290
|
|
|
|
|
|
|
# Extract optional initialisation code (which overrides the |
|
6291
|
|
|
|
|
|
|
# normal typemap), such as 'int foo = ($type)SvIV($arg)' |
|
6292
|
151
|
|
|
|
|
454
|
my $var_init = ''; |
|
6293
|
151
|
|
|
|
|
225
|
my $init_op; |
|
6294
|
151
|
100
|
|
|
|
918
|
($init_op, $var_init) = ($1, $2) if $line =~ s/\s* ([=;+]) \s* (.*) $//xs; |
|
6295
|
|
|
|
|
|
|
|
|
6296
|
151
|
|
|
|
|
727
|
$line =~ s/\s+/ /g; |
|
6297
|
|
|
|
|
|
|
|
|
6298
|
|
|
|
|
|
|
# Split 'char * &foo' into ('char *', '&', 'foo') |
|
6299
|
|
|
|
|
|
|
# skip to next INPUT line if not valid. |
|
6300
|
|
|
|
|
|
|
# |
|
6301
|
|
|
|
|
|
|
# Note that this pattern has a very liberal sense of what is "valid", |
|
6302
|
|
|
|
|
|
|
# since we don't fully parse C types. For example: |
|
6303
|
|
|
|
|
|
|
# |
|
6304
|
|
|
|
|
|
|
# int foo(a) |
|
6305
|
|
|
|
|
|
|
# int a XYZ |
|
6306
|
|
|
|
|
|
|
# |
|
6307
|
|
|
|
|
|
|
# would be interpreted as an "alien" (i.e. not in the signature) |
|
6308
|
|
|
|
|
|
|
# variable called "XYZ", with a type of "int a". And because it's |
|
6309
|
|
|
|
|
|
|
# alien the initialiser is skipped, so 'int a' is never looked up in |
|
6310
|
|
|
|
|
|
|
# a typemap, so we don't detect anything wrong. Later on, the C |
|
6311
|
|
|
|
|
|
|
# compiler is likely to trip over on the emitted declaration |
|
6312
|
|
|
|
|
|
|
# however: |
|
6313
|
|
|
|
|
|
|
# int a XYZ; |
|
6314
|
|
|
|
|
|
|
|
|
6315
|
|
|
|
|
|
|
my ($var_type, $var_addr, $var_name) = |
|
6316
|
|
|
|
|
|
|
$line =~ /^ |
|
6317
|
|
|
|
|
|
|
( .*? [^&\s] ) # type |
|
6318
|
|
|
|
|
|
|
\s* |
|
6319
|
|
|
|
|
|
|
(\&?) # addr |
|
6320
|
|
|
|
|
|
|
\s* \b |
|
6321
|
|
|
|
|
|
|
(\w+ | length\(\w+\)) # name or length(name) |
|
6322
|
|
|
|
|
|
|
$ |
|
6323
|
|
|
|
|
|
|
/xs |
|
6324
|
151
|
100
|
|
|
|
1648
|
or do { |
|
6325
|
1
|
|
|
|
|
28
|
$pxs->blurt("Error: invalid parameter declaration '$self->{line}'"); |
|
6326
|
1
|
|
|
|
|
26
|
return; |
|
6327
|
|
|
|
|
|
|
}; |
|
6328
|
|
|
|
|
|
|
|
|
6329
|
|
|
|
|
|
|
# length(s) is only allowed in the XSUB's signature. |
|
6330
|
150
|
100
|
|
|
|
633
|
if ($var_name =~ /^length\((\w+)\)$/) { |
|
6331
|
2
|
|
|
|
|
53
|
$pxs->blurt("Error: length() not permitted in INPUT section"); |
|
6332
|
2
|
|
|
|
|
29
|
return; |
|
6333
|
|
|
|
|
|
|
} |
|
6334
|
|
|
|
|
|
|
|
|
6335
|
148
|
|
|
|
|
387
|
my ($var_num, $is_alien); |
|
6336
|
|
|
|
|
|
|
|
|
6337
|
148
|
|
|
|
|
393
|
my $ioparams = $xbody->{ioparams}; |
|
6338
|
|
|
|
|
|
|
|
|
6339
|
|
|
|
|
|
|
my ExtUtils::ParseXS::Node::IO_Param $ioparam = |
|
6340
|
148
|
|
|
|
|
377
|
$ioparams->{names}{$var_name}; |
|
6341
|
|
|
|
|
|
|
|
|
6342
|
148
|
100
|
|
|
|
384
|
if (defined $ioparam) { |
|
6343
|
|
|
|
|
|
|
# The var appeared in the signature too. |
|
6344
|
|
|
|
|
|
|
|
|
6345
|
|
|
|
|
|
|
# Check for duplicate definitions of a particular parameter name. |
|
6346
|
|
|
|
|
|
|
# This can be either because it has appeared in multiple INPUT |
|
6347
|
|
|
|
|
|
|
# lines, or because the type was already defined in the signature, |
|
6348
|
|
|
|
|
|
|
# and thus shouldn't be defined again. The exception to this are |
|
6349
|
|
|
|
|
|
|
# synthetic params like THIS, which are assigned a provisional type |
|
6350
|
|
|
|
|
|
|
# which can be overridden. |
|
6351
|
136
|
100
|
100
|
|
|
1181
|
if ( $ioparam->{in_input} |
|
|
|
|
100
|
|
|
|
|
|
6352
|
|
|
|
|
|
|
or (!$ioparam->{is_synthetic} and defined $ioparam->{type}) |
|
6353
|
|
|
|
|
|
|
) { |
|
6354
|
8
|
|
|
|
|
105
|
$pxs->blurt( |
|
6355
|
|
|
|
|
|
|
"Error: duplicate definition of parameter '$var_name' ignored"); |
|
6356
|
8
|
|
|
|
|
93
|
return; |
|
6357
|
|
|
|
|
|
|
} |
|
6358
|
|
|
|
|
|
|
|
|
6359
|
128
|
100
|
100
|
|
|
464
|
if ($var_name eq 'RETVAL' and $ioparam->{is_synthetic}) { |
|
6360
|
|
|
|
|
|
|
# Convert a synthetic RETVAL into a real parameter |
|
6361
|
11
|
|
|
|
|
32
|
delete $ioparam->{is_synthetic}; |
|
6362
|
11
|
|
|
|
|
34
|
delete $ioparam->{no_init}; |
|
6363
|
11
|
100
|
|
|
|
72
|
if (! defined $ioparam->{arg_num}) { |
|
6364
|
|
|
|
|
|
|
# if has arg_num, RETVAL has appeared in signature but with no |
|
6365
|
|
|
|
|
|
|
# type, and has already been moved to the correct position; |
|
6366
|
|
|
|
|
|
|
# otherwise, it's an alien var that didn't appear in the |
|
6367
|
|
|
|
|
|
|
# signature; move to the correct position. |
|
6368
|
6
|
|
|
|
|
24
|
@{$ioparams->{kids}} = |
|
6369
|
6
|
|
|
|
|
22
|
grep $_ != $ioparam, @{$ioparams->{kids}}; |
|
|
6
|
|
|
|
|
37
|
|
|
6370
|
6
|
|
|
|
|
22
|
push @{$ioparams->{kids}}, $ioparam; |
|
|
6
|
|
|
|
|
26
|
|
|
6371
|
6
|
|
|
|
|
15
|
$is_alien = 1; |
|
6372
|
6
|
|
|
|
|
19
|
$ioparam->{is_alien} = 1; |
|
6373
|
|
|
|
|
|
|
} |
|
6374
|
|
|
|
|
|
|
} |
|
6375
|
|
|
|
|
|
|
|
|
6376
|
128
|
|
|
|
|
280
|
$ioparam->{in_input} = 1; |
|
6377
|
128
|
|
|
|
|
301
|
$var_num = $ioparam->{arg_num}; |
|
6378
|
|
|
|
|
|
|
} |
|
6379
|
|
|
|
|
|
|
else { |
|
6380
|
|
|
|
|
|
|
# The var is in an INPUT line, but not in signature. Treat it as a |
|
6381
|
|
|
|
|
|
|
# general var declaration (which really should have been in a |
|
6382
|
|
|
|
|
|
|
# PREINIT section). Legal but nasty: flag is as 'alien' |
|
6383
|
12
|
|
|
|
|
45
|
$is_alien = 1; |
|
6384
|
12
|
|
|
|
|
143
|
$ioparam = ExtUtils::ParseXS::Node::IO_Param->new({ |
|
6385
|
|
|
|
|
|
|
var => $var_name, |
|
6386
|
|
|
|
|
|
|
is_alien => 1, |
|
6387
|
|
|
|
|
|
|
}); |
|
6388
|
|
|
|
|
|
|
|
|
6389
|
12
|
|
|
|
|
62
|
push @{$ioparams->{kids}}, $ioparam; |
|
|
12
|
|
|
|
|
88
|
|
|
6390
|
12
|
|
|
|
|
121
|
$ioparams->{names}{$var_name} = $ioparam; |
|
6391
|
|
|
|
|
|
|
} |
|
6392
|
|
|
|
|
|
|
|
|
6393
|
|
|
|
|
|
|
# Parse the initialisation part of the INPUT line (if any) |
|
6394
|
|
|
|
|
|
|
|
|
6395
|
140
|
|
|
|
|
274
|
my ($init, $defer); |
|
6396
|
140
|
|
|
|
|
294
|
my $no_init = $ioparam->{no_init}; # may have had OUT in signature |
|
6397
|
|
|
|
|
|
|
|
|
6398
|
140
|
100
|
100
|
|
|
684
|
if (!$no_init && defined $init_op) { |
|
6399
|
|
|
|
|
|
|
# Use the init code based on overridden $var_init, which was |
|
6400
|
|
|
|
|
|
|
# preceded by /[=;+]/ which has been extracted into $init_op |
|
6401
|
|
|
|
|
|
|
|
|
6402
|
20
|
100
|
100
|
|
|
308
|
if ( $init_op =~ /^[=;]$/ |
|
|
|
100
|
|
|
|
|
|
|
6403
|
|
|
|
|
|
|
and $var_init =~ /^NO_INIT\s*;?\s*$/ |
|
6404
|
|
|
|
|
|
|
) { |
|
6405
|
|
|
|
|
|
|
# NO_INIT: skip initialisation |
|
6406
|
1
|
|
|
|
|
12
|
$no_init = 1; |
|
6407
|
|
|
|
|
|
|
} |
|
6408
|
|
|
|
|
|
|
elsif ($init_op eq '=') { |
|
6409
|
|
|
|
|
|
|
# Overridden typemap, such as '= ($type)SvUV($arg)' |
|
6410
|
13
|
|
|
|
|
107
|
$var_init =~ s/;\s*$//; |
|
6411
|
13
|
|
|
|
|
52
|
$init = $var_init, |
|
6412
|
|
|
|
|
|
|
} |
|
6413
|
|
|
|
|
|
|
else { |
|
6414
|
|
|
|
|
|
|
# "; extra code" or "+ extra code" : |
|
6415
|
|
|
|
|
|
|
# append the extra code (after passing through eval) after all the |
|
6416
|
|
|
|
|
|
|
# INPUT and PREINIT blocks have been processed, indirectly using |
|
6417
|
|
|
|
|
|
|
# the $input_part->{deferred_code_lines} mechanism. |
|
6418
|
|
|
|
|
|
|
# In addition, for '+', also generate the normal initialisation |
|
6419
|
|
|
|
|
|
|
# code from the standard typemap - assuming that it's a real |
|
6420
|
|
|
|
|
|
|
# parameter that appears in the signature as well as the INPUT |
|
6421
|
|
|
|
|
|
|
# line. |
|
6422
|
6
|
|
66
|
|
|
47
|
$no_init = !($init_op eq '+' && !$is_alien); |
|
6423
|
|
|
|
|
|
|
# But in either case, add the deferred code |
|
6424
|
6
|
|
|
|
|
16
|
$defer = $var_init; |
|
6425
|
|
|
|
|
|
|
} |
|
6426
|
|
|
|
|
|
|
} |
|
6427
|
|
|
|
|
|
|
else { |
|
6428
|
|
|
|
|
|
|
# no initialiser: emit var and init code based on typemap entry, |
|
6429
|
|
|
|
|
|
|
# unless: it's alien (so no stack arg to bind to it) |
|
6430
|
120
|
100
|
|
|
|
292
|
$no_init = 1 if $is_alien; |
|
6431
|
|
|
|
|
|
|
} |
|
6432
|
|
|
|
|
|
|
|
|
6433
|
|
|
|
|
|
|
# Save the basic information parsed from this line |
|
6434
|
|
|
|
|
|
|
|
|
6435
|
|
|
|
|
|
|
$self->{type} = $var_type, |
|
6436
|
|
|
|
|
|
|
$self->{is_addr} = !!$var_addr, |
|
6437
|
|
|
|
|
|
|
$self->{name} = $var_name, |
|
6438
|
|
|
|
|
|
|
$self->{init_op} = $init_op, |
|
6439
|
|
|
|
|
|
|
$self->{init} = $var_init, |
|
6440
|
140
|
|
|
|
|
890
|
$self->{ioparam} = $ioparam; |
|
6441
|
|
|
|
|
|
|
|
|
6442
|
|
|
|
|
|
|
# and also update the ioparam object using that information |
|
6443
|
|
|
|
|
|
|
|
|
6444
|
140
|
|
|
|
|
1529
|
%$ioparam = ( |
|
6445
|
|
|
|
|
|
|
%$ioparam, |
|
6446
|
|
|
|
|
|
|
type => $var_type, |
|
6447
|
|
|
|
|
|
|
arg_num => $var_num, |
|
6448
|
|
|
|
|
|
|
var => $var_name, |
|
6449
|
|
|
|
|
|
|
defer => $defer, |
|
6450
|
|
|
|
|
|
|
init => $init, |
|
6451
|
|
|
|
|
|
|
init_op => $init_op, |
|
6452
|
|
|
|
|
|
|
no_init => $no_init, |
|
6453
|
|
|
|
|
|
|
is_addr => !!$var_addr, |
|
6454
|
|
|
|
|
|
|
); |
|
6455
|
|
|
|
|
|
|
|
|
6456
|
140
|
|
|
|
|
615
|
1; |
|
6457
|
|
|
|
|
|
|
} |
|
6458
|
|
|
|
|
|
|
|
|
6459
|
|
|
|
|
|
|
|
|
6460
|
|
|
|
|
|
|
sub as_code { |
|
6461
|
140
|
|
|
140
|
|
307
|
my __PACKAGE__ $self = shift; |
|
6462
|
140
|
|
|
|
|
259
|
my ExtUtils::ParseXS $pxs = shift; |
|
6463
|
140
|
|
|
|
|
200
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6464
|
140
|
|
|
|
|
271
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6465
|
|
|
|
|
|
|
|
|
6466
|
|
|
|
|
|
|
# Emit "type var" declaration and possibly various forms of |
|
6467
|
|
|
|
|
|
|
# initialiser code. |
|
6468
|
|
|
|
|
|
|
|
|
6469
|
140
|
|
|
|
|
312
|
my $ioparam = $self->{ioparam}; |
|
6470
|
|
|
|
|
|
|
|
|
6471
|
|
|
|
|
|
|
# Synthetic params like THIS will be emitted later - they |
|
6472
|
|
|
|
|
|
|
# are treated like ANSI params, except the type can overridden |
|
6473
|
|
|
|
|
|
|
# within an INPUT statement |
|
6474
|
140
|
100
|
|
|
|
377
|
return if $ioparam->{is_synthetic}; |
|
6475
|
|
|
|
|
|
|
|
|
6476
|
|
|
|
|
|
|
# The ioparam object contains data from both the INPUT line and |
|
6477
|
|
|
|
|
|
|
# the XSUB signature. |
|
6478
|
132
|
|
|
|
|
429
|
$ioparam->as_input_code($pxs, $xsub, $xbody); |
|
6479
|
|
|
|
|
|
|
} |
|
6480
|
|
|
|
|
|
|
|
|
6481
|
|
|
|
|
|
|
|
|
6482
|
|
|
|
|
|
|
# ====================================================================== |
|
6483
|
|
|
|
|
|
|
|
|
6484
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::OUTPUT; |
|
6485
|
|
|
|
|
|
|
|
|
6486
|
|
|
|
|
|
|
# Handle an OUTPUT: block |
|
6487
|
|
|
|
|
|
|
|
|
6488
|
19
|
|
|
19
|
|
115
|
BEGIN { $build_subclass->(-parent => 'keylines', |
|
6489
|
|
|
|
|
|
|
)}; |
|
6490
|
|
|
|
|
|
|
|
|
6491
|
|
|
|
|
|
|
# The inherited parse() method will call OUTPUT_line->parse() for each line |
|
6492
|
|
|
|
|
|
|
|
|
6493
|
|
|
|
|
|
|
|
|
6494
|
|
|
|
|
|
|
# ====================================================================== |
|
6495
|
|
|
|
|
|
|
|
|
6496
|
|
|
|
|
|
|
package ExtUtils::ParseXS::Node::OUTPUT_line; |
|
6497
|
|
|
|
|
|
|
|
|
6498
|
|
|
|
|
|
|
# Handle one line from an OUTPUT keyword block |
|
6499
|
|
|
|
|
|
|
|
|
6500
|
19
|
|
|
19
|
|
85
|
BEGIN { $build_subclass->(-parent => 'keyline', |
|
6501
|
|
|
|
|
|
|
'ioparam', # the IO_Param object associated with this OUTPUT line. |
|
6502
|
|
|
|
|
|
|
'is_setmagic', # Bool: the line is a SETMAGIC: line |
|
6503
|
|
|
|
|
|
|
'do_setmagic', # Bool: the current SETMAGIC state |
|
6504
|
|
|
|
|
|
|
'name', # Str: name of the parameter to output |
|
6505
|
|
|
|
|
|
|
'code', # Str: optional setting code |
|
6506
|
|
|
|
|
|
|
)}; |
|
6507
|
|
|
|
|
|
|
|
|
6508
|
|
|
|
|
|
|
|
|
6509
|
|
|
|
|
|
|
# Parse one line from an OUTPUT block |
|
6510
|
|
|
|
|
|
|
|
|
6511
|
|
|
|
|
|
|
sub parse { |
|
6512
|
81
|
|
|
81
|
|
162
|
my __PACKAGE__ $self = shift; |
|
6513
|
81
|
|
|
|
|
136
|
my ExtUtils::ParseXS $pxs = shift; |
|
6514
|
81
|
|
|
|
|
134
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6515
|
81
|
|
|
|
|
118
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6516
|
81
|
|
|
|
|
160
|
my ExtUtils::ParseXS::Node::OUTPUT $parent = shift; # parent OUTPUT node |
|
6517
|
|
|
|
|
|
|
|
|
6518
|
81
|
|
|
|
|
443
|
$self->SUPER::parse($pxs); # set file/line_no/line |
|
6519
|
81
|
|
|
|
|
209
|
my $line = $self->{line}; # line of text to be processed |
|
6520
|
|
|
|
|
|
|
|
|
6521
|
81
|
50
|
|
|
|
449
|
return unless $line =~ /\S/; # skip blank lines |
|
6522
|
|
|
|
|
|
|
|
|
6523
|
|
|
|
|
|
|
# set some sane default values in case we do one of the early returns |
|
6524
|
|
|
|
|
|
|
# below |
|
6525
|
|
|
|
|
|
|
|
|
6526
|
81
|
|
|
|
|
224
|
$self->{do_setmagic} = $xbody->{OUTPUT_SETMAGIC_state}; |
|
6527
|
81
|
|
|
|
|
174
|
$self->{is_setmagic} = 0; |
|
6528
|
|
|
|
|
|
|
|
|
6529
|
81
|
100
|
|
|
|
401
|
if ($line =~ /^\s*SETMAGIC\s*:\s*(ENABLE|DISABLE)\s*/) { |
|
6530
|
6
|
100
|
|
|
|
56
|
$xbody->{OUTPUT_SETMAGIC_state} = ($1 eq "ENABLE" ? 1 : 0); |
|
6531
|
6
|
|
|
|
|
18
|
$self->{do_setmagic} = $xbody->{OUTPUT_SETMAGIC_state}; |
|
6532
|
6
|
|
|
|
|
20
|
$self->{is_setmagic} = 1; |
|
6533
|
6
|
|
|
|
|
71
|
return; |
|
6534
|
|
|
|
|
|
|
} |
|
6535
|
|
|
|
|
|
|
|
|
6536
|
|
|
|
|
|
|
# Expect lines of the two forms |
|
6537
|
|
|
|
|
|
|
# SomeVar |
|
6538
|
|
|
|
|
|
|
# SomeVar sv_setsv(....); |
|
6539
|
|
|
|
|
|
|
# |
|
6540
|
75
|
|
|
|
|
595
|
my ($outarg, $outcode) = $line =~ /^\s*(\S+)\s*(.*?)\s*$/s; |
|
6541
|
|
|
|
|
|
|
|
|
6542
|
75
|
|
|
|
|
238
|
$self->{name} = $outarg; |
|
6543
|
|
|
|
|
|
|
|
|
6544
|
|
|
|
|
|
|
my ExtUtils::ParseXS::Node::IO_Param $ioparam = |
|
6545
|
75
|
|
|
|
|
371
|
$xbody->{ioparams}{names}{$outarg}; |
|
6546
|
75
|
|
|
|
|
156
|
$self->{ioparam} = $ioparam; |
|
6547
|
|
|
|
|
|
|
|
|
6548
|
75
|
100
|
100
|
|
|
511
|
if ($ioparam && $ioparam->{in_output}) { |
|
6549
|
2
|
|
|
|
|
30
|
$pxs->blurt("Error: duplicate OUTPUT parameter '$outarg' ignored"); |
|
6550
|
2
|
|
|
|
|
18
|
return; |
|
6551
|
|
|
|
|
|
|
} |
|
6552
|
|
|
|
|
|
|
|
|
6553
|
73
|
100
|
100
|
|
|
482
|
if ( $outarg eq "RETVAL" |
|
6554
|
|
|
|
|
|
|
and $xsub->{decl}{return_type}{no_output}) |
|
6555
|
|
|
|
|
|
|
{ |
|
6556
|
3
|
|
|
|
|
43
|
$pxs->blurt( "Error: can't use RETVAL in OUTPUT " |
|
6557
|
|
|
|
|
|
|
. "when NO_OUTPUT declared"); |
|
6558
|
3
|
|
|
|
|
30
|
return; |
|
6559
|
|
|
|
|
|
|
} |
|
6560
|
|
|
|
|
|
|
|
|
6561
|
70
|
100
|
100
|
|
|
419
|
if ( !$ioparam # no such param or, for RETVAL, RETVAL was void; |
|
|
|
|
100
|
|
|
|
|
|
6562
|
|
|
|
|
|
|
# not bound to an arg which can be updated |
|
6563
|
|
|
|
|
|
|
or $outarg ne "RETVAL" && !$ioparam->{arg_num}) |
|
6564
|
|
|
|
|
|
|
{ |
|
6565
|
3
|
|
|
|
|
46
|
$pxs->blurt("Error: OUTPUT $outarg not a parameter"); |
|
6566
|
3
|
|
|
|
|
35
|
return; |
|
6567
|
|
|
|
|
|
|
} |
|
6568
|
|
|
|
|
|
|
|
|
6569
|
67
|
|
|
|
|
146
|
$ioparam->{in_output} = 1; |
|
6570
|
|
|
|
|
|
|
$ioparam->{do_setmagic} = $outarg eq 'RETVAL' |
|
6571
|
|
|
|
|
|
|
? 0 # RETVAL never needs magic setting |
|
6572
|
67
|
100
|
|
|
|
292
|
: $xbody->{OUTPUT_SETMAGIC_state}; |
|
6573
|
67
|
100
|
|
|
|
188
|
$self->{code} = $ioparam->{output_code} = $outcode if length $outcode; |
|
6574
|
|
|
|
|
|
|
|
|
6575
|
67
|
|
|
|
|
259
|
1; |
|
6576
|
|
|
|
|
|
|
} |
|
6577
|
|
|
|
|
|
|
|
|
6578
|
|
|
|
|
|
|
|
|
6579
|
|
|
|
|
|
|
sub as_code { |
|
6580
|
67
|
|
|
67
|
|
115
|
my __PACKAGE__ $self = shift; |
|
6581
|
67
|
|
|
|
|
103
|
my ExtUtils::ParseXS $pxs = shift; |
|
6582
|
67
|
|
|
|
|
102
|
my ExtUtils::ParseXS::Node::xsub $xsub = shift; |
|
6583
|
67
|
|
|
|
|
90
|
my ExtUtils::ParseXS::Node::xbody $xbody = shift; |
|
6584
|
|
|
|
|
|
|
|
|
6585
|
|
|
|
|
|
|
# An OUTPUT: line serves two logically distinct purposes. First, any |
|
6586
|
|
|
|
|
|
|
# parameters listed are updated; i.e. the perl equivalent of |
|
6587
|
|
|
|
|
|
|
# |
|
6588
|
|
|
|
|
|
|
# my $foo = $_[0]; |
|
6589
|
|
|
|
|
|
|
# # maybe $foo's value gets changed here |
|
6590
|
|
|
|
|
|
|
# $_[0] = $foo; # update caller's arg with current value |
|
6591
|
|
|
|
|
|
|
# |
|
6592
|
|
|
|
|
|
|
# The code for updating such OUTPUT vars is emitted here, in the |
|
6593
|
|
|
|
|
|
|
# same order they appear in OUTPUT lines, and preserving the order |
|
6594
|
|
|
|
|
|
|
# of any intermixed POSTCALL etc blocks. |
|
6595
|
|
|
|
|
|
|
# |
|
6596
|
|
|
|
|
|
|
# Second, it can be used to indicate that an SV should be created, |
|
6597
|
|
|
|
|
|
|
# set to the current value of RETVAL, and pushed on the stack; i.e |
|
6598
|
|
|
|
|
|
|
# the perl equivalent of |
|
6599
|
|
|
|
|
|
|
# |
|
6600
|
|
|
|
|
|
|
# my $RETVAL; |
|
6601
|
|
|
|
|
|
|
# # maybe $RETVAL's value gets set here |
|
6602
|
|
|
|
|
|
|
# return $RETVAL; |
|
6603
|
|
|
|
|
|
|
# |
|
6604
|
|
|
|
|
|
|
# The code to return RETVAL is emitted later, after all other |
|
6605
|
|
|
|
|
|
|
# processing for XSUB is complete apart from any final CLEANUP block. |
|
6606
|
|
|
|
|
|
|
# It is done at the same time as any emitting for params declared as |
|
6607
|
|
|
|
|
|
|
# OUT or OUTLIST in the signature. |
|
6608
|
|
|
|
|
|
|
# |
|
6609
|
|
|
|
|
|
|
# There isn't any particularly strong reason to do things in this |
|
6610
|
|
|
|
|
|
|
# exact order; but the ordering was the result of how xsubpp was |
|
6611
|
|
|
|
|
|
|
# originally written and subsequently modified, and changing things |
|
6612
|
|
|
|
|
|
|
# now might break existing XS code which has come to rely on the |
|
6613
|
|
|
|
|
|
|
# ordering. |
|
6614
|
|
|
|
|
|
|
|
|
6615
|
67
|
100
|
|
|
|
416
|
return if $self->{name} eq 'RETVAL'; |
|
6616
|
|
|
|
|
|
|
|
|
6617
|
23
|
|
|
|
|
57
|
my $ioparam = $self->{ioparam}; |
|
6618
|
23
|
50
|
|
|
|
55
|
return unless $ioparam; # might be an ENABLE line with no param to emit |
|
6619
|
|
|
|
|
|
|
|
|
6620
|
23
|
|
|
|
|
98
|
$ioparam->as_output_code($pxs); |
|
6621
|
|
|
|
|
|
|
} |
|
6622
|
|
|
|
|
|
|
|
|
6623
|
|
|
|
|
|
|
|
|
6624
|
|
|
|
|
|
|
# ====================================================================== |
|
6625
|
|
|
|
|
|
|
|
|
6626
|
|
|
|
|
|
|
|
|
6627
|
|
|
|
|
|
|
1; |
|
6628
|
|
|
|
|
|
|
|
|
6629
|
|
|
|
|
|
|
# vim: ts=4 sts=4 sw=4: et: |