line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package xsub; |
2
|
|
|
|
|
|
|
$VERSION = 1.0; |
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
my %XSUB; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
sub import { |
7
|
35
|
|
|
35
|
|
44
|
my $p = shift; |
8
|
|
|
|
|
|
|
|
9
|
35
|
|
|
|
|
200
|
my ($package, $file, $line) = caller; |
10
|
|
|
|
|
|
|
|
11
|
35
|
|
|
|
|
52
|
my $source = pop; |
12
|
35
|
|
|
|
|
36
|
my $name = shift; |
13
|
35
|
100
|
66
|
|
|
269
|
my $prototype = @_ && $_[0] !~ /^:/ ? shift : undef; |
14
|
35
|
|
|
|
|
59
|
my $attributes = [@_]; |
15
|
35
|
|
|
|
|
59
|
s/^:// for @$attributes; |
16
|
|
|
|
|
|
|
|
17
|
35
|
|
|
|
|
217
|
my $xs = bless { |
18
|
|
|
|
|
|
|
name => $name, |
19
|
|
|
|
|
|
|
source => $source, |
20
|
|
|
|
|
|
|
package => $package, |
21
|
|
|
|
|
|
|
file => $file, |
22
|
|
|
|
|
|
|
line => $line, |
23
|
|
|
|
|
|
|
prototype => $prototype, |
24
|
|
|
|
|
|
|
attributes => $attributes, |
25
|
|
|
|
|
|
|
}, $p; |
26
|
|
|
|
|
|
|
|
27
|
35
|
100
|
|
|
|
76
|
if ($name) { |
28
|
34
|
50
|
|
|
|
68
|
my $pr = defined($prototype) ? "($prototype)" : ""; |
29
|
34
|
|
|
|
|
1203
|
eval "package $package; sub $name $pr"; |
30
|
34
|
50
|
|
|
|
100
|
$@ and die $@; |
31
|
|
|
|
|
|
|
} |
32
|
|
|
|
|
|
|
|
33
|
35
|
|
|
|
|
38
|
local *XSUB = \@{$XSUB{$file}}; |
|
35
|
|
|
|
|
87
|
|
34
|
35
|
|
|
|
|
1977
|
push @XSUB, $xs; |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _reindent($$) { |
38
|
37
|
|
|
37
|
|
48
|
my $v = ' ' x shift; |
39
|
37
|
|
|
|
|
135
|
my @l = split /\n/, $_[0]; |
40
|
|
|
|
|
|
|
|
41
|
37
|
|
|
|
|
51
|
my $i = 0; |
42
|
37
|
|
66
|
|
|
215
|
$i++ while $i < @l && $l[$i] eq ''; |
43
|
37
|
50
|
33
|
|
|
176
|
$i < @l && $l[$i] =~ m/^(\s+)/ or return $_[0]; |
44
|
37
|
|
|
|
|
54
|
my $k = $1; |
45
|
|
|
|
|
|
|
|
46
|
37
|
|
|
|
|
625
|
s/^$k/$v/ for @l; |
47
|
37
|
|
|
|
|
182
|
join "\n", @l, ''; |
48
|
|
|
|
|
|
|
} |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
sub _unindent($) { |
51
|
3
|
|
|
3
|
|
8
|
_reindent(0, $_[0]) |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub _compile { |
55
|
1
|
|
|
1
|
|
3
|
my ($c, $so) = @_; |
56
|
1
|
|
|
|
|
1079
|
my $cmd = |
57
|
|
|
|
|
|
|
"$C{cc} $C{ccflags} -O3 $C{cccdlflags} " . |
58
|
|
|
|
|
|
|
"-I$C{archlib}/CORE $C{lddlflags} -o $so $c"; |
59
|
1
|
|
|
|
|
498156
|
my $x = system $cmd; |
60
|
1
|
50
|
|
|
|
4938
|
$x and die; |
61
|
0
|
0
|
|
|
|
0
|
-e $so or die; |
62
|
|
|
|
|
|
|
} |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub bootstrap { |
65
|
1
|
|
|
1
|
|
2
|
my $p = shift; |
66
|
1
|
|
|
|
|
27
|
my ($q, $qpm) = (caller)[0, 1]; |
67
|
1
|
|
|
|
|
1
|
my ($qc, $qso); |
68
|
|
|
|
|
|
|
|
69
|
1
|
|
|
|
|
4
|
local *XSUB = \@{$XSUB{$qpm}}; |
|
1
|
|
|
|
|
3
|
|
70
|
1
|
50
|
|
|
|
5
|
defined @XSUB or return; |
71
|
|
|
|
|
|
|
|
72
|
1
|
50
|
|
|
|
35
|
-e $qpm or die; |
73
|
1
|
50
|
|
|
|
8
|
$qpm =~ m/\.pm$/ or die; |
74
|
1
|
50
|
|
|
|
8
|
($qc = $qpm) =~ s/\.pm$/\.c/ or die; |
75
|
1
|
50
|
|
|
|
7
|
($qso = $qpm) =~ s/\.pm$/\.so/ or die; |
76
|
|
|
|
|
|
|
|
77
|
1
|
0
|
33
|
|
|
19
|
if (!-e $qso || (-M $qpm < -M $qso) || (-M __FILE__ < -M $qso)) { |
|
|
|
33
|
|
|
|
|
78
|
1
|
|
|
|
|
3
|
local *XS; |
79
|
1
|
50
|
|
|
|
127
|
open XS, '>', $qc or die; |
80
|
1
|
|
|
|
|
4
|
my $pre = select(XS); |
81
|
|
|
|
|
|
|
|
82
|
1
|
|
|
|
|
6
|
print _unindent qq{ |
83
|
|
|
|
|
|
|
#include "EXTERN.h" |
84
|
|
|
|
|
|
|
#include "perl.h" |
85
|
|
|
|
|
|
|
#include "XSUB.h" |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
#define __PACKAGE__ "$q" |
88
|
|
|
|
|
|
|
#define undef (&PL_sv_undef) |
89
|
|
|
|
|
|
|
#define true (&PL_sv_yes) |
90
|
|
|
|
|
|
|
#define yes true |
91
|
|
|
|
|
|
|
#define false (&PL_sv_no) |
92
|
|
|
|
|
|
|
#define no false |
93
|
|
|
|
|
|
|
#define unless(x) if (!(x)) |
94
|
|
|
|
|
|
|
#define wantarray (GIMME == G_ARRAY) |
95
|
|
|
|
|
|
|
#define wantvoid (GIMME == G_VOID) |
96
|
|
|
|
|
|
|
#define wantscalar (GIMME == G_SCALAR) |
97
|
|
|
|
|
|
|
}; |
98
|
|
|
|
|
|
|
|
99
|
1
|
|
|
|
|
3
|
print _unindent q{ |
100
|
|
|
|
|
|
|
#define _C_RETURN_AV(sv) { \ |
101
|
|
|
|
|
|
|
AV *av = (AV *)(sv); I32 n = 1 + AvFILL(av); \ |
102
|
|
|
|
|
|
|
EXTEND(SP, n); Copy(AvARRAY(av), SP + 1, n, SV *); SP += n; \ |
103
|
|
|
|
|
|
|
av_undef(av); \ |
104
|
|
|
|
|
|
|
PUTBACK; return; \ |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
#define _C_RETURN_SV(sv) { \ |
108
|
|
|
|
|
|
|
PUSHs(sv_2mortal(sv)); \ |
109
|
|
|
|
|
|
|
PUTBACK; return; \ |
110
|
|
|
|
|
|
|
} |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
#define _C_DECLARE(name) XS(name) { \ |
113
|
|
|
|
|
|
|
dXSARGS; SP -= items; { \ |
114
|
|
|
|
|
|
|
SV *(_C_ ## name)(U32, SV **); \ |
115
|
|
|
|
|
|
|
SV *sv = (_C_ ## name)(items, &ST(0)); \ |
116
|
|
|
|
|
|
|
if (!sv) { PUTBACK; return; } \ |
117
|
|
|
|
|
|
|
if (SvTYPE(sv) == SVt_PVAV) \ |
118
|
|
|
|
|
|
|
_C_RETURN_AV(sv) \ |
119
|
|
|
|
|
|
|
else \ |
120
|
|
|
|
|
|
|
_C_RETURN_SV(sv) \ |
121
|
|
|
|
|
|
|
} \ |
122
|
|
|
|
|
|
|
} SV *_C_ ## name (UV argc, SV **argv) |
123
|
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
|
125
|
1
|
|
|
|
|
4
|
for (@XSUB) { |
126
|
35
|
100
|
|
|
|
83
|
unless ($$_{name}) { |
127
|
1
|
|
|
|
|
5
|
print "#line $$_{line} \"$$_{file}\"\n"; |
128
|
1
|
|
|
|
|
3
|
print _unindent($$_{source}), "\n"; |
129
|
1
|
|
|
|
|
4
|
next; |
130
|
|
|
|
|
|
|
} |
131
|
|
|
|
|
|
|
|
132
|
34
|
|
|
|
|
77
|
(my $name = "XS_$$_{package}_$$_{name}") =~ s/::/__/g; |
133
|
|
|
|
|
|
|
|
134
|
34
|
|
|
|
|
36
|
print "\n"; |
135
|
34
|
|
|
|
|
47
|
print "_C_DECLARE($name) {\n"; |
136
|
34
|
|
|
|
|
85
|
print "#line $$_{line} \"$$_{file}\"\n"; |
137
|
34
|
|
|
|
|
58
|
print _reindent(2, $$_{source}); |
138
|
34
|
|
|
|
|
54
|
print "}\n"; |
139
|
|
|
|
|
|
|
# print "#define $$_{name} _C_$name\n"; |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
1
|
|
|
|
|
3
|
(my $boot_q = "boot_$q") =~ s/::/__/g; |
143
|
1
|
|
|
|
|
3
|
print "\nXS($boot_q) {\n"; |
144
|
1
|
|
|
|
|
2
|
for (@XSUB) { |
145
|
35
|
100
|
|
|
|
62
|
$$_{name} or next; |
146
|
34
|
|
|
|
|
56
|
my $realname = "$$_{package}::$$_{name}"; |
147
|
34
|
|
|
|
|
57
|
(my $name = "XS_$$_{package}_$$_{name}") =~ s/::/__/g; |
148
|
|
|
|
|
|
|
|
149
|
34
|
|
|
|
|
44
|
my $pr = $$_{prototype}; |
150
|
34
|
50
|
|
|
|
142
|
defined $pr and $pr =~ s/\\/\\\\/g; |
151
|
|
|
|
|
|
|
|
152
|
34
|
|
|
|
|
36
|
print " newXS"; |
153
|
34
|
50
|
|
|
|
56
|
print "proto" if defined $pr; |
154
|
34
|
|
|
|
|
49
|
print "(\"$realname\", $name, __FILE__"; |
155
|
34
|
50
|
|
|
|
65
|
print ", \"$pr\"" if defined $pr; |
156
|
34
|
|
|
|
|
179
|
print ");\n"; |
157
|
|
|
|
|
|
|
} |
158
|
1
|
|
|
|
|
3
|
print "}\n"; |
159
|
|
|
|
|
|
|
|
160
|
1
|
|
|
|
|
4
|
select($pre); |
161
|
1
|
|
|
|
|
32
|
close XS; |
162
|
|
|
|
|
|
|
|
163
|
1
|
|
|
|
|
8
|
require Config; |
164
|
1
|
|
|
|
|
3
|
local *C = \%Config::Config; |
165
|
|
|
|
|
|
|
|
166
|
1
|
|
|
|
|
26
|
unlink($qso); |
167
|
1
|
|
|
|
|
4
|
_compile($qc, $qso); |
168
|
0
|
|
|
|
|
|
unlink($qc); |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
|
require DynaLoader; |
172
|
0
|
0
|
|
|
|
|
$qso =~ m<^/> or $qso = "./$qso"; |
173
|
0
|
0
|
|
|
|
|
my $libref = DynaLoader::dl_load_file($qso, 0) or die; |
174
|
0
|
|
|
|
|
|
(my $boot_q = "boot_$q") =~ s/::/__/g; |
175
|
0
|
0
|
|
|
|
|
my $symref = DynaLoader::dl_find_symbol($libref, $boot_q) or die; |
176
|
0
|
0
|
|
|
|
|
DynaLoader::dl_install_xsub($boot_q, $symref, $qso) or die; |
177
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
&{$boot_q}; |
|
0
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
0
|
|
|
|
|
|
require attributes; |
181
|
0
|
|
|
|
|
|
for (@XSUB) { |
182
|
0
|
0
|
0
|
|
|
|
$$_{name} && @{$$_{attributes}} or next; |
|
0
|
|
|
|
|
|
|
183
|
0
|
|
|
|
|
|
for my $a (@{$$_{attributes}}) { |
|
0
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
|
import attributes $$_{package}, \&{"$$_{package}::$$_{name}"}, $a; |
|
0
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
1 |